aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands/prompt.go33
-rw-r--r--doc/aerc.1.scd6
-rw-r--r--widgets/aerc.go34
-rw-r--r--widgets/exline.go41
4 files changed, 108 insertions, 6 deletions
diff --git a/commands/prompt.go b/commands/prompt.go
new file mode 100644
index 0000000..3734881
--- /dev/null
+++ b/commands/prompt.go
@@ -0,0 +1,33 @@
+package commands
+
+import (
+ "errors"
+ "fmt"
+
+ "git.sr.ht/~sircmpwn/aerc/widgets"
+)
+
+type Prompt struct{}
+
+func init() {
+ register(Prompt{})
+}
+
+func (_ Prompt) Aliases() []string {
+ return []string{"prompt"}
+}
+
+func (_ Prompt) Complete(aerc *widgets.Aerc, args []string) []string {
+ return nil // TODO: add completions
+}
+
+func (_ Prompt) Execute(aerc *widgets.Aerc, args []string) error {
+ if len(args) < 3 {
+ return errors.New(fmt.Sprintf("Usage: %s <prompt> <cmd>", args[0]))
+ }
+
+ prompt := args[1]
+ cmd := args[2:]
+ aerc.RegisterPrompt(prompt, cmd)
+ return nil
+}
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index 4aa777c..225ded7 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -67,6 +67,12 @@ These commands work in any context.
Cycles to the previous or next tab in the list, repeating n times
(default: 1).
+*prompt* <prompt> <command...>
+ Displays the prompt on the status bar, waits for user input, then appends
+ that input as the last argument to the command and executes it. The input is
+ passed as one argument to the command, unless it is empty, in which case no
+ extra argument is added.
+
*quit*
Exits aerc.
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 5a7914a..345f3ea 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -30,6 +30,7 @@ type Aerc struct {
statusbar *libui.Stack
statusline *StatusLine
pendingKeys []config.KeyStroke
+ prompts *libui.Stack
tabs *libui.Tabs
beep func() error
}
@@ -65,6 +66,7 @@ func NewAerc(conf *config.AercConfig, logger *log.Logger,
logger: logger,
statusbar: statusbar,
statusline: statusline,
+ prompts: libui.NewStack(),
tabs: tabs,
}
@@ -105,6 +107,20 @@ func (aerc *Aerc) Tick() bool {
for _, acct := range aerc.accounts {
more = acct.Tick() || more
}
+
+ if len(aerc.prompts.Children()) > 0 {
+ more = true
+ previous := aerc.focused
+ prompt := aerc.prompts.Pop().(*ExLine)
+ prompt.finish = func() {
+ aerc.statusbar.Pop()
+ aerc.focus(previous)
+ }
+
+ aerc.statusbar.Push(prompt)
+ aerc.focus(prompt)
+ }
+
return more
}
@@ -358,8 +374,6 @@ func (aerc *Aerc) BeginExCommand() {
if aerc.simulating == 0 {
aerc.cmdHistory.Add(cmd)
}
- aerc.statusbar.Pop()
- aerc.focus(previous)
}, func() {
aerc.statusbar.Pop()
aerc.focus(previous)
@@ -370,6 +384,22 @@ func (aerc *Aerc) BeginExCommand() {
aerc.focus(exline)
}
+func (aerc *Aerc) RegisterPrompt(prompt string, cmd []string) {
+ p := NewPrompt(prompt, func(text string) {
+ if text != "" {
+ cmd = append(cmd, text)
+ }
+ err := aerc.cmd(cmd)
+ if err != nil {
+ aerc.PushStatus(" "+err.Error(), 10*time.Second).
+ Color(tcell.ColorDefault, tcell.ColorRed)
+ }
+ }, func(cmd string) []string {
+ return nil // TODO: completions
+ })
+ aerc.prompts.Push(p)
+}
+
func (aerc *Aerc) Mailto(addr *url.URL) error {
acct := aerc.SelectedAccount()
if acct == nil {
diff --git a/widgets/exline.go b/widgets/exline.go
index be1cde1..8ec69d6 100644
--- a/widgets/exline.go
+++ b/widgets/exline.go
@@ -9,21 +9,21 @@ import (
type ExLine struct {
ui.Invalidatable
- cancel func()
commit func(cmd string)
+ finish func()
tabcomplete func(cmd string) []string
cmdHistory lib.History
input *ui.TextInput
}
-func NewExLine(commit func(cmd string), cancel func(),
+func NewExLine(commit func(cmd string), finish func(),
tabcomplete func(cmd string) []string,
cmdHistory lib.History) *ExLine {
input := ui.NewTextInput("").Prompt(":").TabComplete(tabcomplete)
exline := &ExLine{
- cancel: cancel,
commit: commit,
+ finish: finish,
tabcomplete: tabcomplete,
cmdHistory: cmdHistory,
input: input,
@@ -34,6 +34,22 @@ func NewExLine(commit func(cmd string), cancel func(),
return exline
}
+func NewPrompt(prompt string, commit func(text string),
+ tabcomplete func(cmd string) []string) *ExLine {
+
+ input := ui.NewTextInput("").Prompt(prompt).TabComplete(tabcomplete)
+ exline := &ExLine{
+ commit: commit,
+ tabcomplete: tabcomplete,
+ cmdHistory: &nullHistory{input: input},
+ input: input,
+ }
+ input.OnInvalidate(func(d ui.Drawable) {
+ exline.Invalidate()
+ })
+ return exline
+}
+
func (ex *ExLine) Invalidate() {
ex.DoInvalidate(ex)
}
@@ -54,6 +70,7 @@ func (ex *ExLine) Event(event tcell.Event) bool {
cmd := ex.input.String()
ex.input.Focus(false)
ex.commit(cmd)
+ ex.finish()
case tcell.KeyUp:
ex.input.Set(ex.cmdHistory.Prev())
ex.Invalidate()
@@ -63,10 +80,26 @@ func (ex *ExLine) Event(event tcell.Event) bool {
case tcell.KeyEsc, tcell.KeyCtrlC:
ex.input.Focus(false)
ex.cmdHistory.Reset()
- ex.cancel()
+ ex.finish()
default:
return ex.input.Event(event)
}
}
return true
}
+
+type nullHistory struct {
+ input *ui.TextInput
+}
+
+func (_ *nullHistory) Add(string) {}
+
+func (h *nullHistory) Next() string {
+ return h.input.String()
+}
+
+func (h *nullHistory) Prev() string {
+ return h.input.String()
+}
+
+func (_ *nullHistory) Reset() {}