Removes unnecessary types and reworks execute method to return an exec.Cmd pointer

This commit is contained in:
sloumdrone 2019-07-06 14:40:29 -07:00
parent cda1757e95
commit b787a49e9d
1 changed files with 33 additions and 49 deletions

View File

@ -19,34 +19,27 @@ import (
// contain options for various keys (test, view, edit, etc).
type Entry map[string]string
// Entries is a slice of entries that gets used as a part of the Cap type
type Entries []Entry
// Cap is a map of Entries and represents each mimetype and a slice of the
// various entries (programs) available for that mimetype.
type Cap map[string]Entries
// Mailcap is the main struct to interact with. It contains a Cap, as
// caps, that represents the full mailcap db for the system. It has a
// number of receivers to facilitate retrieving a command from a mimetype.
type Mailcap struct {
Caps Cap
DB map[string][]Entry
}
// Creates and initializes the mailcap struct/db
// and returns a pointer to Mailcap struct
func NewMailcap() *Mailcap {
mc := Mailcap{make(Cap)}
mc := Mailcap{make(map[string][]Entry)}
mc.getCaps()
return &mc
}
// Returns Entries for a given mimetype and an error or nil.
func (m *Mailcap) GetAllMime(mime string) (Entries, error) {
if v, ok := m.Caps[mime]; ok {
// Returns []Entry for a given mimetype and an error or nil.
func (m *Mailcap) GetAllMime(mime string) ([]Entry, error) {
if v, ok := m.DB[mime]; ok {
return v, nil
}
return make(Entries, 0), fmt.Errorf("Cannot find %s\n", mime)
return nil, fmt.Errorf("Cannot find %s\n", mime)
}
// Retrieves an Entry for a given mimetype and key.
@ -83,23 +76,22 @@ func (m *Mailcap) FindMatch(mime, key string, needsTerm bool) (Entry, error) {
return v, nil
}
return make(Entry), fmt.Errorf("Unable to find key %q in entries for %s", key, mime)
return nil, fmt.Errorf("Unable to find key %q in entries for %s", key, mime)
}
// Called on an Entry type returned by FindMatch. Executes the
// program associated with the Entry. Calls the action that was
// set by FindMatch when generating the entry. If not action is
// set, SetAction will need to be called. A filepath string is
// passed to Execute in order to declare the target of the program
// being called. Returns an error or nil.
func (e Entry) Execute(path string) error {
// Called on an Entry type that has an action set (either by calling
// SetAction on the Entry or by it being returned by FindMatch.
// Returns a pointer to type exec.Command and an error (or nil).
// The caller needs to remember to set Std in/out/err on the returned
// Cmd as is needed by their use case.
func (e Entry) Command(path string) (*exec.Cmd, error) {
key, ok := e["action"]
if !ok {
return fmt.Errorf("No action has been set for this entry, was the entry returned by FindMatch?")
return nil, fmt.Errorf("No action has been set for this entry, use SetAction to set the action")
}
command, ok := e[key]
if !ok {
return fmt.Errorf("Entry does not have the key %q", key)
return nil, fmt.Errorf("Entry does not have the key %q", key)
}
matchFields := strings.Fields(command)
@ -110,16 +102,7 @@ func (e Entry) Execute(path string) error {
}
c := exec.Command(matchFields[0], matchFields[1:]...)
c.Stdin = os.Stdin
c.Stdout = os.Stdout
c.Stderr = os.Stderr
execErr := c.Run()
if execErr != nil {
return execErr
}
return nil
return c, nil
}
// Sets the action (key) for the entry calling it. This action
@ -136,10 +119,11 @@ func (e Entry) SetAction(action string) error {
return nil
}
// Retrieve the command for a particular action as a string.
// The string will not have a path inserted into it and will have
// Retrieve the command string for a particular action. The
// string will not have a path inserted into it and will have
// %s to represent the place that the path will go.
func (e Entry) GetCommand(action string) (string, error) {
// Returns a string and error (or nil).
func (e Entry) CommandString(action string) (string, error) {
if v, ok := e[action]; ok {
return v, nil
}
@ -160,17 +144,17 @@ func (e Entry) Actions() []string {
// Look up all of the Entry types available for
// a given mime and key. Returns an Entry slice (Fields)
func (m *Mailcap) lookup(mime, key string) Entries {
f := make(Entries, 0, 5)
if val, ok := m.Caps[mime]; ok {
func (m *Mailcap) lookup(mime, key string) []Entry {
f := make([]Entry, 0, 5)
if val, ok := m.DB[mime]; ok {
f = append(f, val...)
}
splitMime := strings.SplitN(mime,"/",2)
catchAllMime := splitMime[0] + "/*"
if val, ok := m.Caps[catchAllMime]; ok && mime != catchAllMime {
if val, ok := m.DB[catchAllMime]; ok && mime != catchAllMime {
f = append(f, val...)
}
output := make(Entries, 0, len(f))
output := make([]Entry, 0, len(f))
for _, v := range f {
if _, ok := v[key]; ok {
output = append(output, v)
@ -191,7 +175,7 @@ func (m *Mailcap) lookup(mime, key string) Entries {
// Caps paramater of the Mailcap struct in question
func (m *Mailcap) getCaps() {
lnNum := 0
moreCaps := make(Cap)
moreCaps := make(map[string][]Entry)
for _, mailcapFile := range getMailcapFileList() {
file, err := os.Open(mailcapFile)
if err != nil {
@ -199,12 +183,12 @@ func (m *Mailcap) getCaps() {
}
moreCaps, lnNum = readMailcapFile(file, lnNum)
for k, v := range moreCaps {
if _, ok := m.Caps[k]; ok {
if _, ok := m.DB[k]; ok {
for _, item := range v {
m.Caps[k] = append(m.Caps[k], item)
m.DB[k] = append(m.DB[k], item)
}
} else {
m.Caps[k] = v
m.DB[k] = v
}
}
file.Close()
@ -234,8 +218,8 @@ func getMailcapFileList() (mCapSlice []string) {
// Reads an individual mailcap file and returns a Cap
// and a line number
func readMailcapFile(f *os.File,ln int) (Cap, int) {
caps := make(Cap)
func readMailcapFile(f *os.File,ln int) (map[string][]Entry, int) {
caps := make(map[string][]Entry)
reader := bufio.NewReader(f)
for {
l, e := reader.ReadString('\n')
@ -275,7 +259,7 @@ func readMailcapFile(f *os.File,ln int) (Cap, int) {
if _, ok := caps[key]; ok {
caps[key] = append(caps[key], fields)
} else {
caps[key] = make(Entries,0,10)
caps[key] = make([]Entry,0,10)
caps[key] = append(caps[key], fields)
}
}
@ -297,7 +281,7 @@ func parseLine(ln string) (string, Entry, error) {
i += 1
}
if len(fields) < 2 {
return "", outputFields,fmt.Errorf("Not enough fields present in line")
return "", nil,fmt.Errorf("Not enough fields present in line")
}
key, view := fields[0], fields[1]
outputFields["view"] = view