about summary refs log tree commit diff stats
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 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 <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 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] <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 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 <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 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
 }