207 lines
4.5 KiB
Go
207 lines
4.5 KiB
Go
package action
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/zyedidia/micro/v2/internal/buffer"
|
|
"github.com/zyedidia/micro/v2/internal/config"
|
|
"github.com/zyedidia/micro/v2/internal/display"
|
|
"github.com/zyedidia/micro/v2/internal/info"
|
|
"github.com/zyedidia/micro/v2/internal/util"
|
|
"github.com/zyedidia/tcell/v2"
|
|
)
|
|
|
|
type InfoKeyAction func(*InfoPane)
|
|
|
|
var InfoBindings *KeyTree
|
|
var InfoBufBindings *KeyTree
|
|
|
|
func init() {
|
|
InfoBindings = NewKeyTree()
|
|
InfoBufBindings = NewKeyTree()
|
|
}
|
|
|
|
func InfoMapEvent(k Event, action string) {
|
|
config.Bindings["command"][k.Name()] = action
|
|
|
|
switch e := k.(type) {
|
|
case KeyEvent, KeySequenceEvent, RawEvent:
|
|
infoMapKey(e, action)
|
|
case MouseEvent:
|
|
infoMapMouse(e, action)
|
|
}
|
|
}
|
|
|
|
func infoMapKey(k Event, action string) {
|
|
if f, ok := InfoKeyActions[action]; ok {
|
|
InfoBindings.RegisterKeyBinding(k, InfoKeyActionGeneral(f))
|
|
} else if f, ok := BufKeyActions[action]; ok {
|
|
InfoBufBindings.RegisterKeyBinding(k, BufKeyActionGeneral(f))
|
|
}
|
|
}
|
|
|
|
func infoMapMouse(k MouseEvent, action string) {
|
|
// TODO: map mouse
|
|
if f, ok := BufMouseActions[action]; ok {
|
|
InfoBufBindings.RegisterMouseBinding(k, BufMouseActionGeneral(f))
|
|
} else {
|
|
infoMapKey(k, action)
|
|
}
|
|
}
|
|
|
|
func InfoKeyActionGeneral(a InfoKeyAction) PaneKeyAction {
|
|
return func(p Pane) bool {
|
|
a(p.(*InfoPane))
|
|
return true
|
|
}
|
|
}
|
|
|
|
type InfoPane struct {
|
|
*BufPane
|
|
*info.InfoBuf
|
|
}
|
|
|
|
func NewInfoPane(ib *info.InfoBuf, w display.BWindow, tab *Tab) *InfoPane {
|
|
ip := new(InfoPane)
|
|
ip.InfoBuf = ib
|
|
ip.BufPane = NewBufPane(ib.Buffer, w, tab)
|
|
ip.BufPane.bindings = InfoBufBindings
|
|
|
|
return ip
|
|
}
|
|
|
|
func NewInfoBar() *InfoPane {
|
|
ib := info.NewBuffer()
|
|
w := display.NewInfoWindow(ib)
|
|
return NewInfoPane(ib, w, nil)
|
|
}
|
|
|
|
func (h *InfoPane) Close() {
|
|
h.InfoBuf.Close()
|
|
h.BufPane.Close()
|
|
}
|
|
|
|
func (h *InfoPane) HandleEvent(event tcell.Event) {
|
|
switch e := event.(type) {
|
|
case *tcell.EventKey:
|
|
ke := KeyEvent{
|
|
code: e.Key(),
|
|
mod: metaToAlt(e.Modifiers()),
|
|
r: e.Rune(),
|
|
}
|
|
|
|
done := h.DoKeyEvent(ke)
|
|
hasYN := h.HasYN
|
|
if e.Key() == tcell.KeyRune && hasYN {
|
|
if (e.Rune() == 'y' || e.Rune() == 'Y') && hasYN {
|
|
h.YNResp = true
|
|
h.DonePrompt(false)
|
|
} else if (e.Rune() == 'n' || e.Rune() == 'N') && hasYN {
|
|
h.YNResp = false
|
|
h.DonePrompt(false)
|
|
}
|
|
}
|
|
if e.Key() == tcell.KeyRune && !done && !hasYN {
|
|
h.DoRuneInsert(e.Rune())
|
|
done = true
|
|
}
|
|
if done && h.HasPrompt && !hasYN {
|
|
resp := string(h.LineBytes(0))
|
|
hist := h.History[h.PromptType]
|
|
hist[h.HistoryNum] = resp
|
|
if h.EventCallback != nil {
|
|
h.EventCallback(resp)
|
|
}
|
|
}
|
|
default:
|
|
h.BufPane.HandleEvent(event)
|
|
}
|
|
}
|
|
|
|
// DoKeyEvent executes a key event for the command bar, doing any overridden actions
|
|
func (h *InfoPane) DoKeyEvent(e KeyEvent) bool {
|
|
action, more := InfoBindings.NextEvent(e, nil)
|
|
if action != nil && !more {
|
|
action(h)
|
|
InfoBindings.ResetEvents()
|
|
|
|
return true
|
|
} else if action == nil && !more {
|
|
InfoBindings.ResetEvents()
|
|
// return false //TODO:?
|
|
}
|
|
|
|
if !more {
|
|
action, more = InfoBufBindings.NextEvent(e, nil)
|
|
if action != nil && !more {
|
|
done := action(h.BufPane)
|
|
InfoBufBindings.ResetEvents()
|
|
return done
|
|
} else if action == nil && !more {
|
|
InfoBufBindings.ResetEvents()
|
|
}
|
|
}
|
|
|
|
return more
|
|
}
|
|
|
|
// HistoryUp cycles history up
|
|
func (h *InfoPane) HistoryUp() {
|
|
h.UpHistory(h.History[h.PromptType])
|
|
}
|
|
|
|
// HistoryDown cycles history down
|
|
func (h *InfoPane) HistoryDown() {
|
|
h.DownHistory(h.History[h.PromptType])
|
|
}
|
|
|
|
// Autocomplete begins autocompletion
|
|
func (h *InfoPane) CommandComplete() {
|
|
b := h.Buf
|
|
if b.HasSuggestions {
|
|
b.CycleAutocomplete(true)
|
|
return
|
|
}
|
|
|
|
c := b.GetActiveCursor()
|
|
l := b.LineBytes(0)
|
|
l = util.SliceStart(l, c.X)
|
|
|
|
args := bytes.Split(l, []byte{' '})
|
|
cmd := string(args[0])
|
|
|
|
if h.PromptType == "Command" {
|
|
if len(args) == 1 {
|
|
b.Autocomplete(CommandComplete)
|
|
} else if action, ok := commands[cmd]; ok {
|
|
if action.completer != nil {
|
|
b.Autocomplete(action.completer)
|
|
}
|
|
}
|
|
} else {
|
|
// by default use filename autocompletion
|
|
b.Autocomplete(buffer.FileComplete)
|
|
}
|
|
}
|
|
|
|
// ExecuteCommand completes the prompt
|
|
func (h *InfoPane) ExecuteCommand() {
|
|
if !h.HasYN {
|
|
h.DonePrompt(false)
|
|
}
|
|
}
|
|
|
|
// AbortCommand cancels the prompt
|
|
func (h *InfoPane) AbortCommand() {
|
|
h.DonePrompt(true)
|
|
}
|
|
|
|
// InfoKeyActions contains the list of all possible key actions the infopane could execute
|
|
var InfoKeyActions = map[string]InfoKeyAction{
|
|
"HistoryUp": (*InfoPane).HistoryUp,
|
|
"HistoryDown": (*InfoPane).HistoryDown,
|
|
"CommandComplete": (*InfoPane).CommandComplete,
|
|
"ExecuteCommand": (*InfoPane).ExecuteCommand,
|
|
"AbortCommand": (*InfoPane).AbortCommand,
|
|
}
|