Add :exec and :pipe -b(ackground)
This commit is contained in:
parent
c610c3cd9d
commit
7ecc6f96de
3 changed files with 104 additions and 25 deletions
45
commands/exec.go
Normal file
45
commands/exec.go
Normal 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
|
||||||
|
}
|
|
@ -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)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue