Add :prompt command
Usage: :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.
This commit is contained in:
parent
ea4fe71360
commit
ecd803aae4
|
@ -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
|
||||||
|
}
|
|
@ -67,6 +67,12 @@ These commands work in any context.
|
||||||
Cycles to the previous or next tab in the list, repeating n times
|
Cycles to the previous or next tab in the list, repeating n times
|
||||||
(default: 1).
|
(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*
|
*quit*
|
||||||
Exits aerc.
|
Exits aerc.
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ type Aerc struct {
|
||||||
statusbar *libui.Stack
|
statusbar *libui.Stack
|
||||||
statusline *StatusLine
|
statusline *StatusLine
|
||||||
pendingKeys []config.KeyStroke
|
pendingKeys []config.KeyStroke
|
||||||
|
prompts *libui.Stack
|
||||||
tabs *libui.Tabs
|
tabs *libui.Tabs
|
||||||
beep func() error
|
beep func() error
|
||||||
}
|
}
|
||||||
|
@ -65,6 +66,7 @@ func NewAerc(conf *config.AercConfig, logger *log.Logger,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
statusbar: statusbar,
|
statusbar: statusbar,
|
||||||
statusline: statusline,
|
statusline: statusline,
|
||||||
|
prompts: libui.NewStack(),
|
||||||
tabs: tabs,
|
tabs: tabs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +107,20 @@ func (aerc *Aerc) Tick() bool {
|
||||||
for _, acct := range aerc.accounts {
|
for _, acct := range aerc.accounts {
|
||||||
more = acct.Tick() || more
|
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
|
return more
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,8 +374,6 @@ func (aerc *Aerc) BeginExCommand() {
|
||||||
if aerc.simulating == 0 {
|
if aerc.simulating == 0 {
|
||||||
aerc.cmdHistory.Add(cmd)
|
aerc.cmdHistory.Add(cmd)
|
||||||
}
|
}
|
||||||
aerc.statusbar.Pop()
|
|
||||||
aerc.focus(previous)
|
|
||||||
}, func() {
|
}, func() {
|
||||||
aerc.statusbar.Pop()
|
aerc.statusbar.Pop()
|
||||||
aerc.focus(previous)
|
aerc.focus(previous)
|
||||||
|
@ -370,6 +384,22 @@ func (aerc *Aerc) BeginExCommand() {
|
||||||
aerc.focus(exline)
|
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 {
|
func (aerc *Aerc) Mailto(addr *url.URL) error {
|
||||||
acct := aerc.SelectedAccount()
|
acct := aerc.SelectedAccount()
|
||||||
if acct == nil {
|
if acct == nil {
|
||||||
|
|
|
@ -9,21 +9,21 @@ import (
|
||||||
|
|
||||||
type ExLine struct {
|
type ExLine struct {
|
||||||
ui.Invalidatable
|
ui.Invalidatable
|
||||||
cancel func()
|
|
||||||
commit func(cmd string)
|
commit func(cmd string)
|
||||||
|
finish func()
|
||||||
tabcomplete func(cmd string) []string
|
tabcomplete func(cmd string) []string
|
||||||
cmdHistory lib.History
|
cmdHistory lib.History
|
||||||
input *ui.TextInput
|
input *ui.TextInput
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExLine(commit func(cmd string), cancel func(),
|
func NewExLine(commit func(cmd string), finish func(),
|
||||||
tabcomplete func(cmd string) []string,
|
tabcomplete func(cmd string) []string,
|
||||||
cmdHistory lib.History) *ExLine {
|
cmdHistory lib.History) *ExLine {
|
||||||
|
|
||||||
input := ui.NewTextInput("").Prompt(":").TabComplete(tabcomplete)
|
input := ui.NewTextInput("").Prompt(":").TabComplete(tabcomplete)
|
||||||
exline := &ExLine{
|
exline := &ExLine{
|
||||||
cancel: cancel,
|
|
||||||
commit: commit,
|
commit: commit,
|
||||||
|
finish: finish,
|
||||||
tabcomplete: tabcomplete,
|
tabcomplete: tabcomplete,
|
||||||
cmdHistory: cmdHistory,
|
cmdHistory: cmdHistory,
|
||||||
input: input,
|
input: input,
|
||||||
|
@ -34,6 +34,22 @@ func NewExLine(commit func(cmd string), cancel func(),
|
||||||
return exline
|
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() {
|
func (ex *ExLine) Invalidate() {
|
||||||
ex.DoInvalidate(ex)
|
ex.DoInvalidate(ex)
|
||||||
}
|
}
|
||||||
|
@ -54,6 +70,7 @@ func (ex *ExLine) Event(event tcell.Event) bool {
|
||||||
cmd := ex.input.String()
|
cmd := ex.input.String()
|
||||||
ex.input.Focus(false)
|
ex.input.Focus(false)
|
||||||
ex.commit(cmd)
|
ex.commit(cmd)
|
||||||
|
ex.finish()
|
||||||
case tcell.KeyUp:
|
case tcell.KeyUp:
|
||||||
ex.input.Set(ex.cmdHistory.Prev())
|
ex.input.Set(ex.cmdHistory.Prev())
|
||||||
ex.Invalidate()
|
ex.Invalidate()
|
||||||
|
@ -63,10 +80,26 @@ func (ex *ExLine) Event(event tcell.Event) bool {
|
||||||
case tcell.KeyEsc, tcell.KeyCtrlC:
|
case tcell.KeyEsc, tcell.KeyCtrlC:
|
||||||
ex.input.Focus(false)
|
ex.input.Focus(false)
|
||||||
ex.cmdHistory.Reset()
|
ex.cmdHistory.Reset()
|
||||||
ex.cancel()
|
ex.finish()
|
||||||
default:
|
default:
|
||||||
return ex.input.Event(event)
|
return ex.input.Event(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
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() {}
|
||||||
|
|
Loading…
Reference in New Issue