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