From e54486ee40c9cedde9d4dae3e89d8b5f932188ee Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Tue, 3 Oct 2023 22:12:10 +0200 Subject: commands: parse arguments with go-opt Use the argument parsing framework introduced earlier to unify the parsing of (almost) all command options. Remove custom parsing code and to avoid extraneous types, add fields with `opt` tags on command structs that have options and arguments. Commands that take no argument do not need anything. Since the command objects now carry data, create a new temporary instance of them before passing them to opt.ArgsToStruct when executing a command. A few of the commands use specific semantics for parsing (:choose), or are delegating argument parsing to another function (:sort, :search, :filter). For these commands, simply add a dummy "-" passthrough argument. Since all commands still have the argument list (after split) nothing needs to be changed in this area. There should be no functional change besides the Usage strings and reported errors which are now generated automatically. Signed-off-by: Robin Jarry Reviewed-by: Koni Marti Tested-by: Moritz Poldrack Tested-by: Inwit --- commands/msg/archive.go | 24 +++++-- commands/msg/copy.go | 28 ++------ commands/msg/delete.go | 5 -- commands/msg/envelope.go | 29 +++----- commands/msg/fold.go | 4 -- commands/msg/forward.go | 54 +++++--------- commands/msg/invite.go | 25 ++----- commands/msg/mark.go | 68 ++++++------------ commands/msg/modify-labels.go | 14 ++-- commands/msg/move.go | 29 ++------ commands/msg/pipe.go | 80 ++++++++------------- commands/msg/read.go | 132 ++++++++++++---------------------- commands/msg/recall.go | 34 +++------ commands/msg/reply.go | 65 ++++++----------- commands/msg/toggle-thread-context.go | 5 -- commands/msg/toggle-threads.go | 5 -- commands/msg/unsubscribe.go | 26 ++----- 17 files changed, 202 insertions(+), 425 deletions(-) (limited to 'commands/msg') diff --git a/commands/msg/archive.go b/commands/msg/archive.go index f326d0c6..f4d6e3be 100644 --- a/commands/msg/archive.go +++ b/commands/msg/archive.go @@ -1,7 +1,6 @@ package msg import ( - "errors" "fmt" "strings" "sync" @@ -19,7 +18,21 @@ const ( ARCHIVE_MONTH = "month" ) -type Archive struct{} +var ARCHIVE_TYPES = []string{ARCHIVE_FLAT, ARCHIVE_YEAR, ARCHIVE_MONTH} + +type Archive struct { + Type string `opt:"type" action:"ParseArchiveType" metavar:"flat|year|month"` +} + +func (a *Archive) ParseArchiveType(arg string) error { + for _, t := range ARCHIVE_TYPES { + if t == arg { + a.Type = arg + return nil + } + } + return fmt.Errorf("invalid archive type") +} func init() { register(Archive{}) @@ -34,16 +47,13 @@ func (Archive) Complete(args []string) []string { return commands.CompletionFromList(valid, args) } -func (Archive) Execute(args []string) error { - if len(args) != 2 { - return errors.New("Usage: archive ") - } +func (a Archive) Execute(args []string) error { h := newHelper() msgs, err := h.messages() if err != nil { return err } - err = archive(msgs, args[1]) + err = archive(msgs, a.Type) return err } diff --git a/commands/msg/copy.go b/commands/msg/copy.go index 1a902772..4109ef99 100644 --- a/commands/msg/copy.go +++ b/commands/msg/copy.go @@ -1,18 +1,17 @@ package msg import ( - "errors" - "strings" "time" - "git.sr.ht/~sircmpwn/getopt" - "git.sr.ht/~rjarry/aerc/app" "git.sr.ht/~rjarry/aerc/commands" "git.sr.ht/~rjarry/aerc/worker/types" ) -type Copy struct{} +type Copy struct { + CreateFolders bool `opt:"-p"` + Folder string `opt:"..." metavar:""` +} func init() { register(Copy{}) @@ -26,20 +25,7 @@ func (Copy) Complete(args []string) []string { return commands.GetFolders(args) } -func (Copy) Execute(args []string) error { - if len(args) == 1 { - return errors.New("Usage: cp [-p] ") - } - opts, optind, err := getopt.Getopts(args, "p") - if err != nil { - return err - } - var createParents bool - for _, opt := range opts { - if opt.Option == 'p' { - createParents = true - } - } +func (c Copy) Execute(args []string) error { h := newHelper() uids, err := h.markedOrSelectedUids() if err != nil { @@ -49,8 +35,8 @@ func (Copy) Execute(args []string) error { if err != nil { return err } - store.Copy(uids, strings.Join(args[optind:], " "), - createParents, func( + store.Copy(uids, c.Folder, + c.CreateFolders, func( msg types.WorkerMessage, ) { switch msg := msg.(type) { diff --git a/commands/msg/delete.go b/commands/msg/delete.go index 107c8a3f..49463abc 100644 --- a/commands/msg/delete.go +++ b/commands/msg/delete.go @@ -1,7 +1,6 @@ package msg import ( - "errors" "time" "git.sr.ht/~rjarry/aerc/app" @@ -27,10 +26,6 @@ func (Delete) Complete(args []string) []string { } func (Delete) Execute(args []string) error { - if len(args) != 1 { - return errors.New("Usage: :delete") - } - h := newHelper() store, err := h.store() if err != nil { diff --git a/commands/msg/envelope.go b/commands/msg/envelope.go index 3a388c12..6da82a1e 100644 --- a/commands/msg/envelope.go +++ b/commands/msg/envelope.go @@ -9,11 +9,13 @@ import ( "git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" - "git.sr.ht/~sircmpwn/getopt" "github.com/emersion/go-message/mail" ) -type Envelope struct{} +type Envelope struct { + Header bool `opt:"-h"` + Format string `opt:"-s" default:"%-20.20s: %s"` +} func init() { register(Envelope{}) @@ -27,22 +29,7 @@ func (Envelope) Complete(args []string) []string { return nil } -func (Envelope) Execute(args []string) error { - header := false - fmtStr := "%-20.20s: %s" - opts, _, err := getopt.Getopts(args, "hs:") - if err != nil { - return err - } - for _, opt := range opts { - switch opt.Option { - case 's': - fmtStr = opt.Value - case 'h': - header = true - } - } - +func (e Envelope) Execute(args []string) error { acct := app.SelectedAccount() if acct == nil { return errors.New("No account selected") @@ -53,10 +40,10 @@ func (Envelope) Execute(args []string) error { return err } else { if msg != nil { - if header { - list = parseHeader(msg, fmtStr) + if e.Header { + list = parseHeader(msg, e.Format) } else { - list = parseEnvelope(msg, fmtStr, + list = parseEnvelope(msg, e.Format, acct.UiConfig().TimestampFormat) } } else { diff --git a/commands/msg/fold.go b/commands/msg/fold.go index 1d40b90a..0621c8c3 100644 --- a/commands/msg/fold.go +++ b/commands/msg/fold.go @@ -2,7 +2,6 @@ package msg import ( "errors" - "fmt" "strings" "git.sr.ht/~rjarry/aerc/lib/ui" @@ -23,9 +22,6 @@ func (Fold) Complete(args []string) []string { } func (Fold) Execute(args []string) error { - if len(args) != 1 { - return fmt.Errorf("Usage: %s", args[0]) - } h := newHelper() store, err := h.store() if err != nil { diff --git a/commands/msg/forward.go b/commands/msg/forward.go index 68f162cc..e6e386a9 100644 --- a/commands/msg/forward.go +++ b/commands/msg/forward.go @@ -20,11 +20,16 @@ import ( "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" "github.com/emersion/go-message/mail" - - "git.sr.ht/~sircmpwn/getopt" ) -type forward struct{} +type forward struct { + AttachAll bool `opt:"-A"` + AttachFull bool `opt:"-F"` + Edit bool `opt:"-e"` + NoEdit bool `opt:"-E"` + Template string `opt:"-T"` + To []string `opt:"..." required:"false"` +} func init() { register(forward{}) @@ -38,36 +43,11 @@ func (forward) Complete(args []string) []string { return nil } -func (forward) Execute(args []string) error { - opts, optind, err := getopt.Getopts(args, "AFT:eE") - if err != nil { - return err - } - if len(args) != optind { - return errors.New("Usage: forward [-A|-F] [-T