diff options
Diffstat (limited to 'commands/msg')
-rw-r--r-- | commands/msg/archive.go | 24 | ||||
-rw-r--r-- | commands/msg/copy.go | 28 | ||||
-rw-r--r-- | commands/msg/delete.go | 5 | ||||
-rw-r--r-- | commands/msg/envelope.go | 29 | ||||
-rw-r--r-- | commands/msg/fold.go | 4 | ||||
-rw-r--r-- | commands/msg/forward.go | 54 | ||||
-rw-r--r-- | commands/msg/invite.go | 25 | ||||
-rw-r--r-- | commands/msg/mark.go | 68 | ||||
-rw-r--r-- | commands/msg/modify-labels.go | 14 | ||||
-rw-r--r-- | commands/msg/move.go | 29 | ||||
-rw-r--r-- | commands/msg/pipe.go | 80 | ||||
-rw-r--r-- | commands/msg/read.go | 132 | ||||
-rw-r--r-- | commands/msg/recall.go | 34 | ||||
-rw-r--r-- | commands/msg/reply.go | 65 | ||||
-rw-r--r-- | commands/msg/toggle-thread-context.go | 5 | ||||
-rw-r--r-- | commands/msg/toggle-threads.go | 5 | ||||
-rw-r--r-- | commands/msg/unsubscribe.go | 26 |
17 files changed, 202 insertions, 425 deletions
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 <flat|year|month>") - } +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:"<folder>"` +} 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] <folder>") - } - 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 <template>] [-e|-E]") - } - attachAll := false - attachFull := false - template := "" - editHeaders := config.Compose.EditHeaders - for _, opt := range opts { - switch opt.Option { - case 'A': - attachAll = true - case 'F': - attachFull = true - case 'T': - template = opt.Value - case 'e': - editHeaders = true - case 'E': - editHeaders = false - } - } - - if attachAll && attachFull { +func (f forward) Execute(args []string) error { + if f.AttachAll && f.AttachFull { return errors.New("Options -A and -F are mutually exclusive") } + editHeaders := (config.Compose.EditHeaders || f.Edit) && !f.NoEdit widget := app.SelectedTabContent().(app.ProvidesMessage) acct := widget.SelectedAccount() @@ -89,7 +69,7 @@ func (forward) Execute(args []string) error { h.SetSubject(subject) var tolist []*mail.Address - to := strings.Join(args[optind:], ", ") + to := strings.Join(f.To, ", ") if strings.Contains(to, "@") { tolist, err = mail.ParseAddressList(to) if err != nil { @@ -109,7 +89,7 @@ func (forward) Execute(args []string) error { addTab := func() (*app.Composer, error) { composer, err := app.NewComposer(acct, acct.AccountConfig(), acct.Worker(), editHeaders, - template, h, &original, nil) + f.Template, h, &original, nil) if err != nil { app.PushError("Error: " + err.Error()) return nil, err @@ -124,7 +104,7 @@ func (forward) Execute(args []string) error { return composer, nil } - if attachFull { + if f.AttachFull { tmpDir, err := os.MkdirTemp("", "aerc-tmp-attachment") if err != nil { return err @@ -158,8 +138,8 @@ func (forward) Execute(args []string) error { }) }) } else { - if template == "" { - template = config.Templates.Forwards + if f.Template == "" { + f.Template = config.Templates.Forwards } part := lib.FindPlaintext(msg.BodyStructure, nil) @@ -186,7 +166,7 @@ func (forward) Execute(args []string) error { } // add attachments - if attachAll { + if f.AttachAll { var mu sync.Mutex parts := lib.FindAllNonMultipart(msg.BodyStructure, nil, nil) for _, p := range parts { diff --git a/commands/msg/invite.go b/commands/msg/invite.go index 60107480..5b8558b0 100644 --- a/commands/msg/invite.go +++ b/commands/msg/invite.go @@ -12,11 +12,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 invite struct{} +type invite struct { + Edit bool `opt:"-e"` + NoEdit bool `opt:"-E"` +} func init() { register(invite{}) @@ -30,7 +32,7 @@ func (invite) Complete(args []string) []string { return nil } -func (invite) Execute(args []string) error { +func (i invite) Execute(args []string) error { acct := app.SelectedAccount() if acct == nil { return errors.New("no account selected") @@ -49,22 +51,7 @@ func (invite) Execute(args []string) error { return fmt.Errorf("no invitation found (missing text/calendar)") } - editHeaders := config.Compose.EditHeaders - opts, optind, err := getopt.Getopts(args, "eE") - if err != nil { - return err - } - if len(args) != optind { - return errors.New("Usage: accept|accept-tentative|decline [-e|-E]") - } - for _, opt := range opts { - switch opt.Option { - case 'e': - editHeaders = true - case 'E': - editHeaders = false - } - } + editHeaders := (config.Compose.EditHeaders || i.Edit) && !i.NoEdit subject := trimLocalizedRe(msg.Envelope.Subject, acct.AccountConfig().LocalizedRe) switch args[0] { diff --git a/commands/msg/mark.go b/commands/msg/mark.go index eeaa5485..c2c21cf2 100644 --- a/commands/msg/mark.go +++ b/commands/msg/mark.go @@ -2,11 +2,15 @@ package msg import ( "fmt" - - "git.sr.ht/~sircmpwn/getopt" ) -type Mark struct{} +type Mark struct { + All bool `opt:"-a" aliases:"mark,unmark"` + Toggle bool `opt:"-t" aliases:"mark,unmark"` + Visual bool `opt:"-v" aliases:"mark,unmark"` + VisualClear bool `opt:"-V" aliases:"mark,unmark"` + Thread bool `opt:"-T" aliases:"mark,unmark"` +} func init() { register(Mark{}) @@ -20,7 +24,7 @@ func (Mark) Complete(args []string) []string { return nil } -func (Mark) Execute(args []string) error { +func (m Mark) Execute(args []string) error { h := newHelper() OnSelectedMessage := func(fn func(uint32)) error { if fn == nil { @@ -38,63 +42,38 @@ func (Mark) Execute(args []string) error { return err } marker := store.Marker() - opts, _, err := getopt.Getopts(args, "atvVT") - if err != nil { - return err - } - var all bool - var toggle bool - var visual bool - var clearVisual bool - var thread bool - for _, opt := range opts { - switch opt.Option { - case 'a': - all = true - case 'v': - visual = true - clearVisual = true - case 'V': - visual = true - case 't': - toggle = true - case 'T': - thread = true - } - } - if thread && all { + if m.Thread && m.All { return fmt.Errorf("-a and -T are mutually exclusive") } - if thread && visual { + if m.Thread && (m.Visual || m.VisualClear) { return fmt.Errorf("-v and -T are mutually exclusive") } + if m.Visual && m.All { + return fmt.Errorf("-a and -v are mutually exclusive") + } switch args[0] { case "mark": - if all && visual { - return fmt.Errorf("-a and -v are mutually exclusive") - } - var modFunc func(uint32) - if toggle { + if m.Toggle { modFunc = marker.ToggleMark } else { modFunc = marker.Mark } switch { - case all: + case m.All: uids := store.Uids() for _, uid := range uids { modFunc(uid) } return nil - case visual: - marker.ToggleVisualMark(clearVisual) + case m.Visual || m.VisualClear: + marker.ToggleVisualMark(m.VisualClear) return nil default: - if thread { + if m.Thread { threadPtr, err := store.SelectedThread() if err != nil { return err @@ -109,22 +88,22 @@ func (Mark) Execute(args []string) error { } case "unmark": - if visual { + if m.Visual || m.VisualClear { return fmt.Errorf("visual mode not supported for this command") } switch { - case all && toggle: + case m.All && m.Toggle: uids := store.Uids() for _, uid := range uids { marker.ToggleMark(uid) } return nil - case all && !toggle: + case m.All && !m.Toggle: marker.ClearVisualMark() return nil default: - if thread { + if m.Thread { threadPtr, err := store.SelectedThread() if err != nil { return err @@ -138,9 +117,6 @@ func (Mark) Execute(args []string) error { return nil } case "remark": - if all || visual || toggle || thread { - return fmt.Errorf("Usage: :remark") - } marker.Remark() return nil } diff --git a/commands/msg/modify-labels.go b/commands/msg/modify-labels.go index d219a57e..6fdbeac4 100644 --- a/commands/msg/modify-labels.go +++ b/commands/msg/modify-labels.go @@ -1,7 +1,6 @@ package msg import ( - "errors" "time" "git.sr.ht/~rjarry/aerc/app" @@ -9,7 +8,9 @@ import ( "git.sr.ht/~rjarry/aerc/worker/types" ) -type ModifyLabels struct{} +type ModifyLabels struct { + Labels []string `opt:"..." metavar:"[+-]<label>"` +} func init() { register(ModifyLabels{}) @@ -23,12 +24,7 @@ func (ModifyLabels) Complete(args []string) []string { return commands.GetLabels(args) } -func (ModifyLabels) Execute(args []string) error { - changes := args[1:] - if len(changes) == 0 { - return errors.New("Usage: modify-labels <[+-]label> ...") - } - +func (m ModifyLabels) Execute(args []string) error { h := newHelper() store, err := h.store() if err != nil { @@ -40,7 +36,7 @@ func (ModifyLabels) Execute(args []string) error { } var add, remove []string - for _, l := range changes { + for _, l := range m.Labels { switch l[0] { case '+': add = append(add, l[1:]) diff --git a/commands/msg/move.go b/commands/msg/move.go index 5ef9390a..1dd68d35 100644 --- a/commands/msg/move.go +++ b/commands/msg/move.go @@ -1,8 +1,6 @@ package msg import ( - "errors" - "strings" "time" "git.sr.ht/~rjarry/aerc/app" @@ -12,10 +10,12 @@ import ( "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" - "git.sr.ht/~sircmpwn/getopt" ) -type Move struct{} +type Move struct { + CreateFolders bool `opt:"-p"` + Folder string `opt:"..." metavar:"<folder>"` +} func init() { register(Move{}) @@ -29,21 +29,7 @@ func (Move) Complete(args []string) []string { return commands.GetFolders(args) } -func (Move) Execute(args []string) error { - if len(args) == 1 { - return errors.New("Usage: mv [-p] <folder>") - } - 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 (m Move) Execute(args []string) error { h := newHelper() acct, err := h.account() if err != nil { @@ -64,14 +50,13 @@ func (Move) Execute(args []string) error { marker := store.Marker() marker.ClearVisualMark() next := findNextNonDeleted(uids, store) - joinedArgs := strings.Join(args[optind:], " ") - store.Move(uids, joinedArgs, createParents, func( + store.Move(uids, m.Folder, m.CreateFolders, func( msg types.WorkerMessage, ) { switch msg := msg.(type) { case *types.Done: - handleDone(acct, next, "Messages moved to "+joinedArgs, store) + handleDone(acct, next, "Messages moved to "+m.Folder, store) case *types.Error: app.PushError(msg.Error.Error()) marker.Remark() diff --git a/commands/msg/pipe.go b/commands/msg/pipe.go index c9d88f40..75b63b10 100644 --- a/commands/msg/pipe.go +++ b/commands/msg/pipe.go @@ -14,11 +14,14 @@ import ( "git.sr.ht/~rjarry/aerc/log" mboxer "git.sr.ht/~rjarry/aerc/worker/mbox" "git.sr.ht/~rjarry/aerc/worker/types" - - "git.sr.ht/~sircmpwn/getopt" ) -type Pipe struct{} +type Pipe struct { + Background bool `opt:"-b"` + Full bool `opt:"-m"` + Part bool `opt:"-p"` + Command []string `opt:"..."` +} func init() { register(Pipe{}) @@ -32,44 +35,17 @@ func (Pipe) Complete(args []string) []string { return nil } -func (Pipe) Execute(args []string) error { - var ( - background bool - pipeFull bool - pipePart bool - ) - // TODO: let user specify part by index or preferred mimetype - opts, optind, err := getopt.Getopts(args, "bmp") - if err != nil { - return err - } - for _, opt := range opts { - switch opt.Option { - case 'b': - background = true - case 'm': - if pipePart { - return errors.New("-m and -p are mutually exclusive") - } - pipeFull = true - case 'p': - if pipeFull { - return errors.New("-m and -p are mutually exclusive") - } - pipePart = true - } - } - cmd := args[optind:] - if len(cmd) == 0 { - return errors.New("Usage: pipe [-mp] <cmd> [args...]") +func (p Pipe) Execute(args []string) error { + if p.Full && p.Part { + return errors.New("-m and -p are mutually exclusive") } provider := app.SelectedTabContent().(app.ProvidesMessage) - if !pipeFull && !pipePart { + if !p.Full && !p.Part { if _, ok := provider.(*app.MessageViewer); ok { - pipePart = true + p.Part = true } else if _, ok := provider.(*app.AccountView); ok { - pipeFull = true + p.Full = true } else { return errors.New( "Neither -m nor -p specified and cannot infer default") @@ -77,7 +53,7 @@ func (Pipe) Execute(args []string) error { } doTerm := func(reader io.Reader, name string) { - term, err := commands.QuickTerm(cmd, reader) + term, err := commands.QuickTerm(p.Command, reader) if err != nil { app.PushError(err.Error()) return @@ -86,7 +62,7 @@ func (Pipe) Execute(args []string) error { } doExec := func(reader io.Reader) { - ecmd := exec.Command(cmd[0], cmd[1:]...) + ecmd := exec.Command(p.Command[0], p.Command[1:]...) pipe, err := ecmd.StdinPipe() if err != nil { return @@ -106,17 +82,19 @@ func (Pipe) Execute(args []string) error { } else { if ecmd.ProcessState.ExitCode() != 0 { app.PushError(fmt.Sprintf( - "%s: completed with status %d", cmd[0], + "%s: completed with status %d", p.Command[0], ecmd.ProcessState.ExitCode())) } else { app.PushStatus(fmt.Sprintf( - "%s: completed with status %d", cmd[0], + "%s: completed with status %d", p.Command[0], ecmd.ProcessState.ExitCode()), 10*time.Second) } } } - if pipeFull { + app.PushStatus("Fetching messages ...", 10*time.Second) + + if p.Full { var uids []uint32 var title string @@ -125,12 +103,12 @@ func (Pipe) Execute(args []string) error { if err != nil { if mv, ok := provider.(*app.MessageViewer); ok { mv.MessageView().FetchFull(func(reader io.Reader) { - if background { + if p.Background { doExec(reader) } else { doTerm(reader, fmt.Sprintf("%s <%s", - cmd[0], title)) + p.Command[0], title)) } }) return nil @@ -202,27 +180,27 @@ func (Pipe) Execute(args []string) error { } reader := newMessagesReader(messages, len(messages) > 1) - if background { + if p.Background { doExec(reader) } else { - doTerm(reader, fmt.Sprintf("%s <%s", cmd[0], title)) + doTerm(reader, fmt.Sprintf("%s <%s", p.Command[0], title)) } }() - } else if pipePart { + } else if p.Part { mv, ok := provider.(*app.MessageViewer) if !ok { return fmt.Errorf("can only pipe message part from a message view") } - p := provider.SelectedMessagePart() - if p == nil { + part := provider.SelectedMessagePart() + if part == nil { return fmt.Errorf("could not fetch message part") } - mv.MessageView().FetchBodyPart(p.Index, func(reader io.Reader) { - if background { + mv.MessageView().FetchBodyPart(part.Index, func(reader io.Reader) { + if p.Background { doExec(reader) } else { name := fmt.Sprintf("%s <%s/[%d]", - cmd[0], p.Msg.Envelope.Subject, p.Index) + p.Command[0], part.Msg.Envelope.Subject, part.Index) doTerm(reader, name) } }) diff --git a/commands/msg/read.go b/commands/msg/read.go index bac2ceb3..e55ed00e 100644 --- a/commands/msg/read.go +++ b/commands/msg/read.go @@ -2,16 +2,20 @@ package msg import ( "fmt" + "strings" "time" - "git.sr.ht/~sircmpwn/getopt" - "git.sr.ht/~rjarry/aerc/app" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" ) -type FlagMsg struct{} +type FlagMsg struct { + Toggle bool `opt:"-t"` + Answered bool `opt:"-a" aliases:"flag,unflag"` + Flag models.Flags `opt:"-x" aliases:"flag,unflag" action:"ParseFlag"` + FlagName string +} func init() { register(FlagMsg{}) @@ -25,6 +29,23 @@ func (FlagMsg) Complete(args []string) []string { return nil } +func (f *FlagMsg) ParseFlag(arg string) error { + switch strings.ToLower(arg) { + case "seen": + f.Flag = models.SeenFlag + f.FlagName = "seen" + case "answered": + f.Flag = models.AnsweredFlag + f.FlagName = "answered" + case "flagged": + f.Flag = models.FlaggedFlag + f.FlagName = "flagged" + default: + return fmt.Errorf("Unknown flag %q", arg) + } + return nil +} + // If this was called as 'flag' or 'unflag', without the toggle (-t) // option, then it will flag the corresponding messages with the given // flag. If the toggle option was given, it will individually toggle @@ -32,85 +53,20 @@ func (FlagMsg) Complete(args []string) []string { // // If this was called as 'read' or 'unread', it has the same effect as // 'flag' or 'unflag', respectively, but the 'Seen' flag is affected. -func (FlagMsg) Execute(args []string) error { - // The flag to change - var flag models.Flags - // User-readable name of the flag to change - var flagName string - // Whether to toggle the flag (true) or to enable/disable it (false) - var toggle bool - // Whether to enable (true) or disable (false) the flag - enable := (args[0] == "read" || args[0] == "flag") +func (f FlagMsg) Execute(args []string) error { // User-readable name for the action being performed var actionName string - // Getopt option string, varies by command name - var getoptString string - // Help message to provide on parsing failure - var helpMessage string - // Used during parsing to prevent choosing a flag muliple times - // A default flag will be used if this is false - flagChosen := false - - if args[0] == "read" || args[0] == "unread" { - flag = models.SeenFlag - flagName = "read" - getoptString = "t" - helpMessage = "Usage: " + args[0] + " [-t]" - } else { // 'flag' / 'unflag' - flag = models.FlaggedFlag - flagName = "flagged" - getoptString = "tax:" - helpMessage = "Usage: " + args[0] + " [-t] [-a | -x <flag>]" - } - opts, optind, err := getopt.Getopts(args, getoptString) - if err != nil { - return err - } - for _, opt := range opts { - switch opt.Option { - case 't': - toggle = true - case 'a': - if flagChosen { - return fmt.Errorf("Cannot choose a flag multiple times! " + helpMessage) - } - flag = models.AnsweredFlag - flagName = "answered" - flagChosen = true - case 'x': - if flagChosen { - return fmt.Errorf("Cannot choose a flag multiple times! " + helpMessage) - } - // TODO: Support all flags? - switch opt.Value { - case "Seen": - flag = models.SeenFlag - flagName = "seen" - case "Answered": - flag = models.AnsweredFlag - flagName = "answered" - case "Flagged": - flag = models.FlaggedFlag - flagName = "flagged" - default: - return fmt.Errorf("Unknown / Prohibited flag \"%v\"", opt.Value) - } - flagChosen = true + switch args[0] { + case "read", "unread": + f.Flag = models.SeenFlag + f.FlagName = "seen" + case "flag", "unflag": + if f.Flag == 0 { + f.Flag = models.FlaggedFlag + f.FlagName = "flagged" } } - switch { - case toggle: - actionName = "Toggling" - case enable: - actionName = "Setting" - default: - actionName = "Unsetting" - } - if optind != len(args) { - // Any non-option arguments: Error - return fmt.Errorf(helpMessage) - } h := newHelper() store, err := h.store() @@ -122,7 +78,7 @@ func (FlagMsg) Execute(args []string) error { var toEnable []uint32 var toDisable []uint32 - if toggle { + if f.Toggle { // If toggling, split messages into those that need to // be enabled / disabled. msgs, err := h.messages() @@ -130,29 +86,35 @@ func (FlagMsg) Execute(args []string) error { return err } for _, m := range msgs { - if m.Flags.Has(flag) { + if m.Flags.Has(f.Flag) { toDisable = append(toDisable, m.Uid) } else { toEnable = append(toEnable, m.Uid) } } + actionName = "Toggling" } else { msgUids, err := h.markedOrSelectedUids() if err != nil { return err } - if enable { + switch args[0] { + case "read", "flag": toEnable = msgUids - } else { + actionName = "Setting" + default: toDisable = msgUids + actionName = "Unsetting" } } + status := fmt.Sprintf("%s flag %q successful", actionName, f.FlagName) + if len(toEnable) != 0 { - store.Flag(toEnable, flag, true, func(msg types.WorkerMessage) { + store.Flag(toEnable, f.Flag, true, func(msg types.WorkerMessage) { switch msg := msg.(type) { case *types.Done: - app.PushStatus(actionName+" flag '"+flagName+"' successful", 10*time.Second) + app.PushStatus(status, 10*time.Second) store.Marker().ClearVisualMark() case *types.Error: app.PushError(msg.Error.Error()) @@ -160,10 +122,10 @@ func (FlagMsg) Execute(args []string) error { }) } if len(toDisable) != 0 { - store.Flag(toDisable, flag, false, func(msg types.WorkerMessage) { + store.Flag(toDisable, f.Flag, false, func(msg types.WorkerMessage) { switch msg := msg.(type) { case *types.Done: - app.PushStatus(actionName+" flag '"+flagName+"' successful", 10*time.Second) + app.PushStatus(status, 10*time.Second) store.Marker().ClearVisualMark() case *types.Error: app.PushError(msg.Error.Error()) diff --git a/commands/msg/recall.go b/commands/msg/recall.go index 2d999b1d..3b78a763 100644 --- a/commands/msg/recall.go +++ b/commands/msg/recall.go @@ -15,10 +15,13 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/worker/types" - "git.sr.ht/~sircmpwn/getopt" ) -type Recall struct{} +type Recall struct { + Force bool `opt:"-f"` + Edit bool `opt:"-e"` + NoEdit bool `opt:"-E"` +} func init() { register(Recall{}) @@ -32,34 +35,15 @@ func (Recall) Complete(args []string) []string { return nil } -func (Recall) Execute(args []string) error { - force := false - editHeaders := config.Compose.EditHeaders - - opts, optind, err := getopt.Getopts(args, "feE") - if err != nil { - return err - } - for _, opt := range opts { - switch opt.Option { - case 'f': - force = true - case 'e': - editHeaders = true - case 'E': - editHeaders = false - } - } - if len(args) != optind { - return errors.New("Usage: recall [-f] [-e|-E]") - } +func (r Recall) Execute(args []string) error { + editHeaders := (config.Compose.EditHeaders || r.Edit) && !r.NoEdit widget := app.SelectedTabContent().(app.ProvidesMessage) acct := widget.SelectedAccount() if acct == nil { return errors.New("No account selected") } - if acct.SelectedDirectory() != acct.AccountConfig().Postpone && !force { + if acct.SelectedDirectory() != acct.AccountConfig().Postpone && !r.Force { return errors.New("Use -f to recall from outside the " + acct.AccountConfig().Postpone + " directory.") } @@ -164,7 +148,7 @@ func (Recall) Execute(args []string) error { }) } - if force { + if r.Force { composer.SetRecalledFrom(acct.SelectedDirectory()) } diff --git a/commands/msg/reply.go b/commands/msg/reply.go index fff90fff..2ab9e9f8 100644 --- a/commands/msg/reply.go +++ b/commands/msg/reply.go @@ -9,8 +9,6 @@ import ( "strings" "time" - "git.sr.ht/~sircmpwn/getopt" - "git.sr.ht/~rjarry/aerc/app" "git.sr.ht/~rjarry/aerc/commands/account" "git.sr.ht/~rjarry/aerc/config" @@ -24,7 +22,14 @@ import ( "github.com/emersion/go-message/mail" ) -type reply struct{} +type reply struct { + All bool `opt:"-a"` + Close bool `opt:"-c"` + Quote bool `opt:"-q"` + Template string `opt:"-T"` + Edit bool `opt:"-e"` + NoEdit bool `opt:"-E"` +} func init() { register(reply{}) @@ -38,37 +43,8 @@ func (reply) Complete(args []string) []string { return nil } -func (reply) Execute(args []string) error { - opts, optind, err := getopt.Getopts(args, "acqT:eE") - if err != nil { - return err - } - if optind != len(args) { - return errors.New("Usage: reply [-acq -T <template>] [-e|-E]") - } - var ( - quote bool - replyAll bool - closeOnReply bool - template string - ) - editHeaders := config.Compose.EditHeaders - for _, opt := range opts { - switch opt.Option { - case 'a': - replyAll = true - case 'c': - closeOnReply = true - case 'q': - quote = true - case 'T': - template = opt.Value - case 'e': - editHeaders = true - case 'E': - editHeaders = false - } - } +func (r reply) Execute(args []string) error { + editHeaders := (config.Compose.EditHeaders || r.Edit) && !r.NoEdit widget := app.SelectedTabContent().(app.ProvidesMessage) acct := widget.SelectedAccount() @@ -116,7 +92,7 @@ func (reply) Execute(args []string) error { recSet.AddList(to) - if replyAll { + if r.All { // order matters, due to the deduping // in order of importance, first parse the To, then the Cc header @@ -165,12 +141,12 @@ func (reply) Execute(args []string) error { addTab := func() error { composer, err := app.NewComposer(acct, acct.AccountConfig(), acct.Worker(), editHeaders, - template, h, &original, nil) + r.Template, h, &original, nil) if err != nil { app.PushError("Error: " + err.Error()) return err } - if mv != nil && closeOnReply { + if mv != nil && r.Close { app.RemoveTab(mv, true) } @@ -190,18 +166,19 @@ func (reply) Execute(args []string) error { } case c.Sent(): store.Answered([]uint32{msg.Uid}, true, nil) - case mv != nil && closeOnReply: + case mv != nil && r.Close: + view := account.ViewMessage{Peek: true} //nolint:errcheck // who cares? - account.ViewMessage{}.Execute([]string{"-p"}) + view.Execute([]string{"view", "-p"}) } }) return nil } - if quote { - if template == "" { - template = config.Templates.QuotedReply + if r.Quote { + if r.Template == "" { + r.Template = config.Templates.QuotedReply } if crypto.IsEncrypted(msg.BodyStructure) { @@ -256,8 +233,8 @@ func (reply) Execute(args []string) error { }) return nil } else { - if template == "" { - template = config.Templates.NewMessage + if r.Template == "" { + r.Template = config.Templates.NewMessage } return addTab() } diff --git a/commands/msg/toggle-thread-context.go b/commands/msg/toggle-thread-context.go index 7530bc9e..0ef6778f 100644 --- a/commands/msg/toggle-thread-context.go +++ b/commands/msg/toggle-thread-context.go @@ -1,8 +1,6 @@ package msg import ( - "errors" - "git.sr.ht/~rjarry/aerc/lib/ui" ) @@ -21,9 +19,6 @@ func (ToggleThreadContext) Complete(args []string) []string { } func (ToggleThreadContext) Execute(args []string) error { - if len(args) != 1 { - return errors.New("Usage: toggle-entire-thread") - } h := newHelper() store, err := h.store() if err != nil { diff --git a/commands/msg/toggle-threads.go b/commands/msg/toggle-threads.go index 1d38685a..88cc763f 100644 --- a/commands/msg/toggle-threads.go +++ b/commands/msg/toggle-threads.go @@ -1,8 +1,6 @@ package msg import ( - "errors" - "git.sr.ht/~rjarry/aerc/lib/state" "git.sr.ht/~rjarry/aerc/lib/ui" ) @@ -22,9 +20,6 @@ func (ToggleThreads) Complete(args []string) []string { } func (ToggleThreads) Execute(args []string) error { - if len(args) != 1 { - return errors.New("Usage: toggle-threads") - } h := newHelper() acct, err := h.account() if err != nil { diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go index 069aedab..a489b3b9 100644 --- a/commands/msg/unsubscribe.go +++ b/commands/msg/unsubscribe.go @@ -12,13 +12,15 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/log" - "git.sr.ht/~sircmpwn/getopt" "github.com/emersion/go-message/mail" ) // Unsubscribe helps people unsubscribe from mailing lists by way of the // List-Unsubscribe header. -type Unsubscribe struct{} +type Unsubscribe struct { + Edit bool `opt:"-e"` + NoEdit bool `opt:"-E"` +} func init() { register(Unsubscribe{}) @@ -35,23 +37,9 @@ func (Unsubscribe) Complete(args []string) []string { } // Execute runs the Unsubscribe command -func (Unsubscribe) Execute(args []string) error { - editHeaders := config.Compose.EditHeaders - opts, optind, err := getopt.Getopts(args, "eE") - if err != nil { - return err - } - if len(args) != optind { - return errors.New("Usage: unsubscribe [-e|-E]") - } - for _, opt := range opts { - switch opt.Option { - case 'e': - editHeaders = true - case 'E': - editHeaders = false - } - } +func (u Unsubscribe) Execute(args []string) error { + editHeaders := (config.Compose.EditHeaders || u.Edit) && !u.NoEdit + widget := app.SelectedTabContent().(app.ProvidesMessage) msg, err := widget.SelectedMessage() if err != nil { |