package action import ( "bytes" "strings" "github.com/zyedidia/micro/internal/display" "github.com/zyedidia/micro/internal/info" "github.com/zyedidia/micro/internal/util" "github.com/zyedidia/tcell" ) type InfoKeyAction func(*InfoPane) 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) 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: e.Modifiers(), r: e.Rune(), } done := h.DoKeyEvent(ke) hasYN := h.HasYN if e.Key() == tcell.KeyRune && hasYN { if e.Rune() == 'y' && hasYN { h.YNResp = true h.DonePrompt(false) } else if 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) } } case *tcell.EventMouse: h.BufPane.HandleEvent(event) } } // DoKeyEvent executes a key event for the command bar, doing any overridden actions func (h *InfoPane) DoKeyEvent(e KeyEvent) bool { done := false if action, ok := BufKeyBindings[e]; ok { estr := BufKeyStrings[e] for _, s := range InfoNones { if s == estr { return false } } for s, a := range InfoOverrides { // TODO this is a hack and really we should have support // for having binding overrides for different buffers if strings.HasPrefix(estr, s) { done = true a(h) break } } if !done { done = action(h.BufPane) } } return done } // InfoNones is a list of actions that should have no effect when executed // by an infohandler var InfoNones = []string{ "Save", "SaveAll", "SaveAs", "Find", "FindNext", "FindPrevious", "Center", "DuplicateLine", "MoveLinesUp", "MoveLinesDown", "OpenFile", "Start", "End", "PageUp", "PageDown", "SelectPageUp", "SelectPageDown", "HalfPageUp", "HalfPageDown", "ToggleHelp", "ToggleKeyMenu", "ToggleDiffGutter", "ToggleRuler", "JumpLine", "ClearStatus", "ShellMode", "CommandMode", "AddTab", "PreviousTab", "NextTab", "NextSplit", "PreviousSplit", "Unsplit", "VSplit", "HSplit", "ToggleMacro", "PlayMacro", "Suspend", "ScrollUp", "ScrollDown", "SpawnMultiCursor", "SpawnMultiCursorSelect", "RemoveMultiCursor", "RemoveAllMultiCursors", "SkipMultiCursor", } // InfoOverrides is the list of actions which have been overridden // by the infohandler var InfoOverrides = map[string]InfoKeyAction{ "CursorUp": (*InfoPane).CursorUp, "CursorDown": (*InfoPane).CursorDown, "InsertNewline": (*InfoPane).InsertNewline, "Autocomplete": (*InfoPane).Autocomplete, "Escape": (*InfoPane).Escape, "Quit": (*InfoPane).Quit, "QuitAll": (*InfoPane).QuitAll, } // CursorUp cycles history up func (h *InfoPane) CursorUp() { h.UpHistory(h.History[h.PromptType]) } // CursorDown cycles history down func (h *InfoPane) CursorDown() { h.DownHistory(h.History[h.PromptType]) } // Autocomplete begins autocompletion func (h *InfoPane) Autocomplete() { 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 len(args) == 1 { b.Autocomplete(CommandComplete) } else { if action, ok := commands[cmd]; ok { if action.completer != nil { b.Autocomplete(action.completer) } } } } // InsertNewline completes the prompt func (h *InfoPane) InsertNewline() { if !h.HasYN { h.DonePrompt(false) } } // Quit cancels the prompt func (h *InfoPane) Quit() { h.DonePrompt(true) } // QuitAll cancels the prompt func (h *InfoPane) QuitAll() { h.DonePrompt(true) } // Escape cancels the prompt func (h *InfoPane) Escape() { h.DonePrompt(true) }