summary refs log tree commit diff stats
path: root/widgets/msgviewer.go
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/msgviewer.go')
-rw-r--r--widgets/msgviewer.go81
1 files changed, 65 insertions, 16 deletions
diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go
index ab42ee0..3a3e962 100644
--- a/widgets/msgviewer.go
+++ b/widgets/msgviewer.go
@@ -6,24 +6,30 @@ import (
 	"io"
 	"os/exec"
 
+	"github.com/danwakefield/fnmatch"
 	"github.com/emersion/go-imap"
 	"github.com/emersion/go-message"
 	"github.com/emersion/go-message/mail"
 	"github.com/gdamore/tcell"
+	"github.com/google/shlex"
 	"github.com/mattn/go-runewidth"
 
+	"git.sr.ht/~sircmpwn/aerc2/config"
 	"git.sr.ht/~sircmpwn/aerc2/lib"
 	"git.sr.ht/~sircmpwn/aerc2/lib/ui"
 	"git.sr.ht/~sircmpwn/aerc2/worker/types"
 )
 
 type MessageViewer struct {
-	cmd    *exec.Cmd
-	msg    *types.MessageInfo
-	source io.Reader
-	sink   io.WriteCloser
-	grid   *ui.Grid
-	term   *Terminal
+	conf    *config.AercConfig
+	filter  *exec.Cmd
+	msg     *types.MessageInfo
+	pager   *exec.Cmd
+	source  io.Reader
+	pagerin io.WriteCloser
+	sink    io.WriteCloser
+	grid    *ui.Grid
+	term    *Terminal
 }
 
 func formatAddresses(addrs []*imap.Address) string {
@@ -43,7 +49,7 @@ func formatAddresses(addrs []*imap.Address) string {
 	return val.String()
 }
 
-func NewMessageViewer(store *lib.MessageStore,
+func NewMessageViewer(conf *config.AercConfig, store *lib.MessageStore,
 	msg *types.MessageInfo) *MessageViewer {
 
 	grid := ui.NewGrid().Rows([]ui.GridSpec{
@@ -86,9 +92,40 @@ func NewMessageViewer(store *lib.MessageStore,
 		{ui.SIZE_EXACT, 20},
 	})
 
-	cmd := exec.Command("less")
-	pipe, _ := cmd.StdinPipe()
-	term, _ := NewTerminal(cmd)
+	var (
+		filter  *exec.Cmd
+		pager   *exec.Cmd
+		pipe    io.WriteCloser
+		pagerin io.WriteCloser
+	)
+	cmd, err := shlex.Split(conf.Viewer.Pager)
+	if err != nil {
+		panic(err) // TODO: something useful
+	}
+	pager = exec.Command(cmd[0], cmd[1:]...)
+
+	for _, f := range conf.Filters {
+		cmd, err := shlex.Split(f.Command)
+		if err != nil {
+			panic(err) // TODO: Something useful
+		}
+		mime := msg.BodyStructure.MIMEType + "/" + msg.BodyStructure.MIMESubType
+		switch f.FilterType {
+		case config.FILTER_MIMETYPE:
+			if fnmatch.Match(f.Filter, mime, 0) {
+				filter = exec.Command(cmd[0], cmd[1:]...)
+				fmt.Printf("Using filter for %s: %s\n", mime, f.Command)
+			}
+		}
+	}
+	if filter != nil {
+		pipe, _ = filter.StdinPipe()
+		pagerin, _ = pager.StdinPipe()
+	} else {
+		pipe, _ = pager.StdinPipe()
+	}
+
+	term, _ := NewTerminal(pager)
 	// TODO: configure multipart view. I left a spot for it in the grid
 	body.AddChild(term).At(0, 0).Span(1, 2)
 
@@ -96,11 +133,13 @@ func NewMessageViewer(store *lib.MessageStore,
 	grid.AddChild(body).At(1, 0)
 
 	viewer := &MessageViewer{
-		cmd:  cmd,
-		grid: grid,
-		msg:  msg,
-		sink: pipe,
-		term: term,
+		filter:  filter,
+		grid:    grid,
+		msg:     msg,
+		pager:   pager,
+		pagerin: pagerin,
+		sink:    pipe,
+		term:    term,
 	}
 
 	store.FetchBodyPart(msg.Uid, 0, func(reader io.Reader) {
@@ -116,12 +155,22 @@ func NewMessageViewer(store *lib.MessageStore,
 }
 
 func (mv *MessageViewer) attemptCopy() {
-	if mv.source != nil && mv.cmd.Process != nil {
+	if mv.source != nil && mv.pager.Process != nil {
 		header := make(message.Header)
 		header.Set("Content-Transfer-Encoding", mv.msg.BodyStructure.Encoding)
 		header.SetContentType(
 			mv.msg.BodyStructure.MIMEType, mv.msg.BodyStructure.Params)
 		header.SetContentDescription(mv.msg.BodyStructure.Description)
+		if mv.filter != nil {
+			stdout, _ := mv.filter.StdoutPipe()
+			mv.filter.Start()
+			go func() {
+				_, err := io.Copy(mv.pagerin, stdout)
+				if err != nil {
+					io.WriteString(mv.sink, err.Error())
+				}
+			}()
+		}
 		go func() {
 			entity, err := message.New(header, mv.source)
 			if err != nil {