aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/account/pipe.go42
-rw-r--r--commands/msg/pipe.go105
-rw-r--r--commands/msgview/open.go2
-rw-r--r--commands/msgview/pipe.go55
-rw-r--r--commands/msgview/save.go2
-rw-r--r--widgets/account.go8
-rw-r--r--widgets/msgviewer.go9
-rw-r--r--widgets/providesmessage.go12
8 files changed, 125 insertions, 110 deletions
diff --git a/commands/account/pipe.go b/commands/account/pipe.go
deleted file mode 100644
index a68ef64e..00000000
--- 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 <cmd> [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 00000000..949bc95e
--- /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] <cmd> [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 d25fa678..f4a09318 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 56c125bf..00000000
--- 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 <cmd> [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 93fa83f8..75ba56f3 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 824f958e..0948c5c6 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 10c21820..b0ae79ed 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 7be8e7ed..4b716371 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
}