Implement :pipe

This commit is contained in:
Drew DeVault 2019-03-30 11:58:24 -04:00
parent 4465646fed
commit 700dea23fa
5 changed files with 91 additions and 7 deletions

73
commands/account/pipe.go Normal file
View file

@ -0,0 +1,73 @@
package account
import (
"bytes"
"errors"
"io"
"os/exec"
"time"
"git.sr.ht/~sircmpwn/aerc2/widgets"
"github.com/gdamore/tcell"
"github.com/mohamedattahri/mail"
)
func init() {
register("pipe", Pipe)
}
func Pipe(aerc *widgets.Aerc, args []string) error {
if len(args) < 2 {
return errors.New("Usage: :pipe <cmd> [args...]")
}
acct := aerc.SelectedAccount()
if acct == nil {
return errors.New("No account selected")
}
store := acct.Messages().Store()
msg := acct.Messages().Selected()
store.FetchBodies([]uint32{msg.Uid}, func(msg *mail.Message) {
cmd := exec.Command(args[1], args[2:]...)
pipe, err := cmd.StdinPipe()
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorRed, tcell.ColorWhite)
return
}
term, err := widgets.NewTerminal(cmd)
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorRed, tcell.ColorWhite)
return
}
host := widgets.NewTermHost(term, aerc.Config())
name := msg.Subject()
if len(name) > 12 {
name = name[:12]
}
aerc.NewTab(host, args[1] + " <" + name)
term.OnClose = func(err error) {
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorRed, tcell.ColorWhite)
} else {
// TODO: Tab-specific status stacks
aerc.PushStatus("Process complete, press any key to close.",
10*time.Second)
}
}
term.OnStart = func() {
go func() {
reader := bytes.NewBuffer(msg.Bytes())
_, err := io.Copy(pipe, reader)
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorRed, tcell.ColorWhite)
}
pipe.Close()
}()
}
})
return nil
}

View file

@ -19,5 +19,6 @@ func CommandClose(aerc *widgets.Aerc, args []string) error {
return errors.New("Error: not a terminal") return errors.New("Error: not a terminal")
} }
thost.Terminal().Close(nil) thost.Terminal().Close(nil)
aerc.RemoveTab(thost)
return nil return nil
} }

2
go.mod
View file

@ -2,6 +2,7 @@ module git.sr.ht/~sircmpwn/aerc2
require ( require (
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a
git.sr.ht/~sircmpwn/pty v0.0.0-20190330154901-3a43678975a9
github.com/emersion/go-imap v1.0.0-beta.1 github.com/emersion/go-imap v1.0.0-beta.1
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 // indirect github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 // indirect
@ -9,7 +10,6 @@ require (
github.com/gdamore/tcell v1.0.0 github.com/gdamore/tcell v1.0.0
github.com/go-ini/ini v1.42.0 github.com/go-ini/ini v1.42.0
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/kr/pty v1.1.3
github.com/kyoh86/xdg v0.0.0-20171127140545-8db68a8ea76a github.com/kyoh86/xdg v0.0.0-20171127140545-8db68a8ea76a
github.com/lucasb-eyer/go-colorful v0.0.0-20180531031333-d9cec903b20c github.com/lucasb-eyer/go-colorful v0.0.0-20180531031333-d9cec903b20c
github.com/mattn/go-isatty v0.0.3 github.com/mattn/go-isatty v0.0.3

2
go.sum
View file

@ -20,6 +20,8 @@ git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322001004-741298f37f76 h1:D9PCVZ+pgt
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322001004-741298f37f76/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c= git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322001004-741298f37f76/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a h1:ktjo0NVokhdhhyS/VYA1/8R/Az8x5x43r0SuI6McqW4= git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a h1:ktjo0NVokhdhhyS/VYA1/8R/Az8x5x43r0SuI6McqW4=
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c= git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190322002230-17c9f17a421a/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
git.sr.ht/~sircmpwn/pty v0.0.0-20190330154901-3a43678975a9 h1:WWPN5lf6KzXp3xWRrPQZ4MLR3yrFEI4Ysz7HSQ1G/yo=
git.sr.ht/~sircmpwn/pty v0.0.0-20190330154901-3a43678975a9/go.mod h1:8Jmcax8M9nYoEwBhVBhv2ixLRCoUqlbQPE95VpPu43I=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emersion/go-imap v1.0.0-beta.1 h1:bTCaVlUnb5mKoW9lEukusxguSYYZPer+q0g5t+vw5X0= github.com/emersion/go-imap v1.0.0-beta.1 h1:bTCaVlUnb5mKoW9lEukusxguSYYZPer+q0g5t+vw5X0=

View file

@ -9,8 +9,8 @@ import (
"git.sr.ht/~sircmpwn/aerc2/lib/ui" "git.sr.ht/~sircmpwn/aerc2/lib/ui"
"git.sr.ht/~sircmpwn/go-libvterm" "git.sr.ht/~sircmpwn/go-libvterm"
"git.sr.ht/~sircmpwn/pty"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/kr/pty"
) )
type vtermKey struct { type vtermKey struct {
@ -105,6 +105,7 @@ type Terminal struct {
vterm *vterm.VTerm vterm *vterm.VTerm
OnClose func(err error) OnClose func(err error)
OnStart func()
OnTitle func(title string) OnTitle func(title string)
} }
@ -192,6 +193,9 @@ func (term *Terminal) flushTerminal() {
} }
func (term *Terminal) Close(err error) { func (term *Terminal) Close(err error) {
if term.closed {
return
}
term.mutex.Lock() term.mutex.Lock()
defer term.mutex.Unlock() defer term.mutex.Unlock()
term.err = err term.err = err
@ -226,11 +230,6 @@ func (term *Terminal) Invalidate() {
func (term *Terminal) Draw(ctx *ui.Context) { func (term *Terminal) Draw(ctx *ui.Context) {
if term.closed { if term.closed {
if term.err != nil {
ui.NewText(term.err.Error()).Strategy(ui.TEXT_CENTER).Draw(ctx)
} else {
ui.NewText("Terminal closed").Strategy(ui.TEXT_CENTER).Draw(ctx)
}
return return
} }
@ -252,6 +251,9 @@ func (term *Terminal) Draw(ctx *ui.Context) {
return return
} }
term.start <- nil term.start <- nil
if term.OnStart != nil {
term.OnStart()
}
} }
term.ctx = ctx // gross term.ctx = ctx // gross
@ -309,6 +311,9 @@ func (term *Terminal) Draw(ctx *ui.Context) {
} }
func (term *Terminal) Focus(focus bool) { func (term *Terminal) Focus(focus bool) {
if term.closed {
return
}
term.focus = focus term.focus = focus
if term.ctx != nil { if term.ctx != nil {
if !term.focus { if !term.focus {
@ -339,6 +344,9 @@ func convertMods(mods tcell.ModMask) vterm.Modifier {
} }
func (term *Terminal) Event(event tcell.Event) bool { func (term *Terminal) Event(event tcell.Event) bool {
if term.closed {
return false
}
switch event := event.(type) { switch event := event.(type) {
case *tcell.EventKey: case *tcell.EventKey:
if event.Key() == tcell.KeyRune { if event.Key() == tcell.KeyRune {