From 363aab5cc19135599cae93f6c9c7abcd23c111c9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 5 Jul 2019 12:21:12 -0400 Subject: [PATCH] Make :pipe command more generic --- commands/account/pipe.go | 42 --------------- commands/msg/pipe.go | 105 +++++++++++++++++++++++++++++++++++++ commands/msgview/open.go | 2 +- commands/msgview/pipe.go | 55 ------------------- commands/msgview/save.go | 2 +- widgets/account.go | 8 ++- widgets/msgviewer.go | 9 +--- widgets/providesmessage.go | 12 ++++- 8 files changed, 125 insertions(+), 110 deletions(-) delete mode 100644 commands/account/pipe.go create mode 100644 commands/msg/pipe.go delete mode 100644 commands/msgview/pipe.go diff --git a/commands/account/pipe.go b/commands/account/pipe.go deleted file mode 100644 index a68ef64..0000000 --- a/commands/account/pipe.go +++ /dev/null @@ -1,42 +0,0 @@ -package account - -import ( - "errors" - "io" - - "git.sr.ht/~sircmpwn/aerc/commands" - "git.sr.ht/~sircmpwn/aerc/widgets" -) - -type Pipe struct{} - -func init() { - register(Pipe{}) -} - -func (_ Pipe) Aliases() []string { - return []string{"pipe"} -} - -func (_ Pipe) Complete(aerc *widgets.Aerc, args []string) []string { - return nil -} - -func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error { - if len(args) < 2 { - return errors.New("Usage: :pipe [args...]") - } - acct := aerc.SelectedAccount() - store := acct.Messages().Store() - msg := acct.Messages().Selected() - store.FetchFull([]uint32{msg.Uid}, func(reader io.Reader) { - term, err := commands.QuickTerm(aerc, args[1:], reader) - if err != nil { - aerc.PushError(" " + err.Error()) - return - } - name := args[1] + " <" + msg.Envelope.Subject - aerc.NewTab(term, name) - }) - return nil -} diff --git a/commands/msg/pipe.go b/commands/msg/pipe.go new file mode 100644 index 0000000..949bc95 --- /dev/null +++ b/commands/msg/pipe.go @@ -0,0 +1,105 @@ +package msg + +import ( + "encoding/base64" + "errors" + "fmt" + "io" + "mime/quotedprintable" + "strings" + + "git.sr.ht/~sircmpwn/getopt" + + "git.sr.ht/~sircmpwn/aerc/commands" + "git.sr.ht/~sircmpwn/aerc/widgets" +) + +type Pipe struct{} + +func init() { + register(Pipe{}) +} + +func (_ Pipe) Aliases() []string { + return []string{"pipe"} +} + +func (_ Pipe) Complete(aerc *widgets.Aerc, args []string) []string { + return nil +} + +func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error { + var ( + pipeFull bool + pipePart bool + ) + // TODO: let user specify part by index or preferred mimetype + opts, optind, err := getopt.Getopts(args, "mp") + if err != nil { + return err + } + for _, opt := range opts { + switch opt.Option { + 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] [args...]") + } + + provider := aerc.SelectedTab().(widgets.ProvidesMessage) + if !pipeFull && !pipePart { + if _, ok := provider.(*widgets.MessageViewer); ok { + pipePart = true + } else if _, ok := provider.(*widgets.AccountView); ok { + pipeFull = true + } else { + return errors.New( + "Neither -m nor -p specified and cannot infer default") + } + } + + if pipeFull { + store := provider.Store() + msg := provider.SelectedMessage() + store.FetchFull([]uint32{msg.Uid}, func(reader io.Reader) { + term, err := commands.QuickTerm(aerc, cmd, reader) + if err != nil { + aerc.PushError(" " + err.Error()) + return + } + name := cmd[0] + " <" + msg.Envelope.Subject + aerc.NewTab(term, name) + }) + } else if pipePart { + p := provider.SelectedMessagePart() + p.Store.FetchBodyPart(p.Msg.Uid, p.Index, func(reader io.Reader) { + // email parts are encoded as 7bit (plaintext), quoted-printable, or base64 + if strings.EqualFold(p.Part.Encoding, "base64") { + reader = base64.NewDecoder(base64.StdEncoding, reader) + } else if strings.EqualFold(p.Part.Encoding, "quoted-printable") { + reader = quotedprintable.NewReader(reader) + } + + term, err := commands.QuickTerm(aerc, cmd, reader) + if err != nil { + aerc.PushError(" " + err.Error()) + return + } + name := fmt.Sprintf("%s <%s/[%d]", cmd[0], p.Msg.Envelope.Subject, p.Index) + aerc.NewTab(term, name) + }) + } + + return nil +} diff --git a/commands/msgview/open.go b/commands/msgview/open.go index d25fa67..f4a0931 100644 --- a/commands/msgview/open.go +++ b/commands/msgview/open.go @@ -34,7 +34,7 @@ func (_ Open) Execute(aerc *widgets.Aerc, args []string) error { } mv := aerc.SelectedTab().(*widgets.MessageViewer) - p := mv.CurrentPart() + p := mv.SelectedMessagePart() p.Store.FetchBodyPart(p.Msg.Uid, p.Index, func(reader io.Reader) { // email parts are encoded as 7bit (plaintext), quoted-printable, or base64 diff --git a/commands/msgview/pipe.go b/commands/msgview/pipe.go deleted file mode 100644 index 56c125b..0000000 --- a/commands/msgview/pipe.go +++ /dev/null @@ -1,55 +0,0 @@ -package msgview - -import ( - "encoding/base64" - "errors" - "fmt" - "io" - "mime/quotedprintable" - "strings" - - "git.sr.ht/~sircmpwn/aerc/commands" - "git.sr.ht/~sircmpwn/aerc/widgets" -) - -type Pipe struct{} - -func init() { - register(Pipe{}) -} - -func (_ Pipe) Aliases() []string { - return []string{"pipe"} -} - -func (_ Pipe) Complete(aerc *widgets.Aerc, args []string) []string { - return nil -} - -func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error { - if len(args) < 2 { - return errors.New("Usage: :pipe [args...]") - } - - mv := aerc.SelectedTab().(*widgets.MessageViewer) - p := mv.CurrentPart() - - p.Store.FetchBodyPart(p.Msg.Uid, p.Index, func(reader io.Reader) { - // email parts are encoded as 7bit (plaintext), quoted-printable, or base64 - if strings.EqualFold(p.Part.Encoding, "base64") { - reader = base64.NewDecoder(base64.StdEncoding, reader) - } else if strings.EqualFold(p.Part.Encoding, "quoted-printable") { - reader = quotedprintable.NewReader(reader) - } - - term, err := commands.QuickTerm(aerc, args[1:], reader) - if err != nil { - aerc.PushError(" " + err.Error()) - return - } - name := fmt.Sprintf("%s <%s/[%d]", args[1], p.Msg.Envelope.Subject, p.Index) - aerc.NewTab(term, name) - }) - - return nil -} diff --git a/commands/msgview/save.go b/commands/msgview/save.go index 93fa83f..75ba56f 100644 --- a/commands/msgview/save.go +++ b/commands/msgview/save.go @@ -56,7 +56,7 @@ func (_ Save) Execute(aerc *widgets.Aerc, args []string) error { } mv := aerc.SelectedTab().(*widgets.MessageViewer) - p := mv.CurrentPart() + p := mv.SelectedMessagePart() p.Store.FetchBodyPart(p.Msg.Uid, p.Index, func(reader io.Reader) { // email parts are encoded as 7bit (plaintext), quoted-printable, or base64 diff --git a/widgets/account.go b/widgets/account.go index 824f958..0948c5c 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -165,12 +165,16 @@ func (acct *AccountView) Store() *lib.MessageStore { return acct.msglist.Store() } +func (acct *AccountView) SelectedAccount() *AccountView { + return acct +} + func (acct *AccountView) SelectedMessage() *types.MessageInfo { return acct.msglist.Selected() } -func (acct *AccountView) SelectedAccount() *AccountView { - return acct +func (acct *AccountView) SelectedMessagePart() *PartInfo { + return nil } func (acct *AccountView) onMessage(msg types.WorkerMessage) { diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index 10c2182..b0ae79e 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -227,7 +227,7 @@ func (mv *MessageViewer) ToggleHeaders() { switcher.Invalidate() } -func (mv *MessageViewer) CurrentPart() *PartInfo { +func (mv *MessageViewer) SelectedMessagePart() *PartInfo { switcher := mv.switcher part := switcher.parts[switcher.selected] @@ -332,13 +332,6 @@ type PartViewer struct { term *Terminal } -type PartInfo struct { - Index []int - Msg *types.MessageInfo - Part *imap.BodyStructure - Store *lib.MessageStore -} - func NewPartViewer(conf *config.AercConfig, store *lib.MessageStore, msg *types.MessageInfo, part *imap.BodyStructure, showHeaders bool, diff --git a/widgets/providesmessage.go b/widgets/providesmessage.go index 7be8e7e..4b71637 100644 --- a/widgets/providesmessage.go +++ b/widgets/providesmessage.go @@ -1,14 +1,24 @@ package widgets import ( + "github.com/emersion/go-imap" + "git.sr.ht/~sircmpwn/aerc/lib" "git.sr.ht/~sircmpwn/aerc/lib/ui" "git.sr.ht/~sircmpwn/aerc/worker/types" ) +type PartInfo struct { + Index []int + Msg *types.MessageInfo + Part *imap.BodyStructure + Store *lib.MessageStore +} + type ProvidesMessage interface { ui.Drawable Store() *lib.MessageStore - SelectedMessage() *types.MessageInfo SelectedAccount() *AccountView + SelectedMessage() *types.MessageInfo + SelectedMessagePart() *PartInfo }