aboutsummaryrefslogtreecommitdiffstats
path: root/commands/msg/pipe.go
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2023-10-03 22:12:10 +0200
committerRobin Jarry <robin@jarry.cc>2023-10-28 19:24:49 +0200
commite54486ee40c9cedde9d4dae3e89d8b5f932188ee (patch)
tree254f032ef94920c28fbb9be8f918e61082a2015d /commands/msg/pipe.go
parent9a4518476d8c8f28340c6b44cd808e6d58fbeb98 (diff)
downloadaerc-e54486ee40c9cedde9d4dae3e89d8b5f932188ee.tar.gz
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 <robin@jarry.cc> Reviewed-by: Koni Marti <koni.marti@gmail.com> Tested-by: Moritz Poldrack <moritz@poldrack.dev> Tested-by: Inwit <inwit@sindominio.net>
Diffstat (limited to 'commands/msg/pipe.go')
-rw-r--r--commands/msg/pipe.go80
1 files changed, 29 insertions, 51 deletions
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)
}
})