Add :exec and :pipe -b(ackground)

This commit is contained in:
Drew DeVault 2019-07-08 18:19:08 -04:00
parent c610c3cd9d
commit 7ecc6f96de
3 changed files with 104 additions and 25 deletions

45
commands/exec.go Normal file
View File

@ -0,0 +1,45 @@
package commands
import (
"errors"
"fmt"
"os/exec"
"time"
"git.sr.ht/~sircmpwn/aerc/widgets"
"github.com/gdamore/tcell"
)
type ExecCmd struct{}
func init() {
register(ExecCmd{})
}
func (_ ExecCmd) Aliases() []string {
return []string{"exec"}
}
func (_ ExecCmd) Complete(aerc *widgets.Aerc, args []string) []string {
return nil
}
func (_ ExecCmd) Execute(aerc *widgets.Aerc, args []string) error {
if len(args) < 2 {
return errors.New("Usage: exec [cmd...]")
}
cmd := exec.Command(args[1], args[2:]...)
go func() {
err := cmd.Run()
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorDefault, tcell.ColorRed)
} else {
aerc.PushStatus(fmt.Sprintf(
"%s: complete", args[0]), 10*time.Second).
Color(tcell.ColorDefault, tcell.ColorDefault)
}
}()
return nil
}

View File

@ -6,12 +6,15 @@ import (
"fmt" "fmt"
"io" "io"
"mime/quotedprintable" "mime/quotedprintable"
"os/exec"
"strings" "strings"
"time"
"git.sr.ht/~sircmpwn/getopt"
"git.sr.ht/~sircmpwn/aerc/commands" "git.sr.ht/~sircmpwn/aerc/commands"
"git.sr.ht/~sircmpwn/aerc/widgets" "git.sr.ht/~sircmpwn/aerc/widgets"
"git.sr.ht/~sircmpwn/getopt"
"github.com/gdamore/tcell"
) )
type Pipe struct{} type Pipe struct{}
@ -30,16 +33,19 @@ func (_ Pipe) Complete(aerc *widgets.Aerc, args []string) []string {
func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error { func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error {
var ( var (
pipeFull bool background bool
pipePart bool pipeFull bool
pipePart bool
) )
// TODO: let user specify part by index or preferred mimetype // TODO: let user specify part by index or preferred mimetype
opts, optind, err := getopt.Getopts(args, "mp") opts, optind, err := getopt.Getopts(args, "bmp")
if err != nil { if err != nil {
return err return err
} }
for _, opt := range opts { for _, opt := range opts {
switch opt.Option { switch opt.Option {
case 'b':
background = true
case 'm': case 'm':
if pipePart { if pipePart {
return errors.New("-m and -p are mutually exclusive") return errors.New("-m and -p are mutually exclusive")
@ -69,17 +75,38 @@ func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error {
} }
} }
doTerm := func(reader io.Reader, name string) {
term, err := commands.QuickTerm(aerc, cmd, reader)
if err != nil {
aerc.PushError(" " + err.Error())
return
}
aerc.NewTab(term, name)
}
doExec := func(reader io.Reader) {
ecmd := exec.Command(cmd[0], cmd[1:]...)
err := ecmd.Run()
if err != nil {
aerc.PushStatus(" "+err.Error(), 10*time.Second).
Color(tcell.ColorDefault, tcell.ColorRed)
} else {
aerc.PushStatus(fmt.Sprintf(
"%s: complete", args[0]), 10*time.Second).
Color(tcell.ColorDefault, tcell.ColorDefault)
}
}
if pipeFull { if pipeFull {
store := provider.Store() store := provider.Store()
msg := provider.SelectedMessage() msg := provider.SelectedMessage()
store.FetchFull([]uint32{msg.Uid}, func(reader io.Reader) { store.FetchFull([]uint32{msg.Uid}, func(reader io.Reader) {
term, err := commands.QuickTerm(aerc, cmd, reader) if background {
if err != nil { doExec(reader)
aerc.PushError(" " + err.Error()) } else {
return doTerm(reader, fmt.Sprintf(
"%s <%s", cmd[0], msg.Envelope.Subject))
} }
name := cmd[0] + " <" + msg.Envelope.Subject
aerc.NewTab(term, name)
}) })
} else if pipePart { } else if pipePart {
p := provider.SelectedMessagePart() p := provider.SelectedMessagePart()
@ -91,13 +118,13 @@ func (_ Pipe) Execute(aerc *widgets.Aerc, args []string) error {
reader = quotedprintable.NewReader(reader) reader = quotedprintable.NewReader(reader)
} }
term, err := commands.QuickTerm(aerc, cmd, reader) if background {
if err != nil { doExec(reader)
aerc.PushError(" " + err.Error()) } else {
return name := fmt.Sprintf("%s <%s/[%d]",
cmd[0], p.Msg.Envelope.Subject, p.Index)
doTerm(reader, name)
} }
name := fmt.Sprintf("%s <%s/[%d]", cmd[0], p.Msg.Envelope.Subject, p.Index)
aerc.NewTab(term, name)
}) })
} }

View File

@ -32,6 +32,11 @@ These commands work in any context.
*cd* <directory> *cd* <directory>
Changes aerc's current working directory. Changes aerc's current working directory.
*exec* <command...>
Executes an arbitrary command in the background.
*Note*: commands executed in this way are not executed with the shell.
*pwd* *pwd*
Displays aerc's current working directory in the status bar. Displays aerc's current working directory in the status bar.
@ -72,6 +77,16 @@ message list, the message in the message viewer, etc).
*move* <target> *move* <target>
Moves the selected message to the target folder. Moves the selected message to the target folder.
*pipe* [-bmp] <cmd>
Downloads and pipes the selected message into the given shell command, and
opens a new terminal tab to show the result. By default, the selected
message part is used in the message viewer and the full message is used in
the message list.
*-b*: Run the command in the background instead of opening a terminal tab
*-m*: Pipe the full message
*-p*: Pipe just the selected message part, if applicable
*reply* [-aq] *reply* [-aq]
Opens the composer to reply to the selected message. Opens the composer to reply to the selected message.
@ -113,10 +128,6 @@ message list, the message in the message viewer, etc).
a percentage, the percentage is applied to the number of messages shown on a percentage, the percentage is applied to the number of messages shown on
screen and the cursor advances that far. screen and the cursor advances that far.
*pipe* <cmd>
Downloads and pipes the selected message into the given shell command, and
opens a new terminal tab to show the result.
*select* <n> *select* <n>
Selects the nth message in the message list (and scrolls it into view if Selects the nth message in the message list (and scrolls it into view if
necessary). necessary).
@ -130,10 +141,6 @@ message list, the message in the message viewer, etc).
Saves the current message part in a temporary file and opens it Saves the current message part in a temporary file and opens it
with the system handler. with the system handler.
*pipe* <cmd>
Downloads and pipes the current message part into the given shell command,
and opens a new terminal tab to show the result.
*save* [-p] <path> *save* [-p] <path>
Saves the current message part to the given path. Saves the current message part to the given path.