Allow configuration for info/term bindings

This commit exposes the separate infopane bindings to configuration
from the user. This also adds support for separate bindings in the
terminal emulator view. Default bindings are provided, but can also
be rebound in bindings.json.
This commit is contained in:
Zachary Yedidia
2020-07-01 17:11:07 -04:00
parent 2363a4019b
commit bbd6f559ab
7 changed files with 533 additions and 408 deletions

View File

@@ -16,6 +16,12 @@ import (
"github.com/zyedidia/tcell" "github.com/zyedidia/tcell"
) )
var Binder = map[string]func(e Event, action string){
"info": InfoMapEvent,
"buffer": BufMapEvent,
"terminal": TermMapEvent,
}
func createBindingsIfNotExist(fname string) { func createBindingsIfNotExist(fname string) {
if _, e := os.Stat(fname); os.IsNotExist(e) { if _, e := os.Stat(fname); os.IsNotExist(e) {
ioutil.WriteFile(fname, []byte("{}"), 0644) ioutil.WriteFile(fname, []byte("{}"), 0644)
@@ -24,10 +30,9 @@ func createBindingsIfNotExist(fname string) {
// InitBindings intializes the bindings map by reading from bindings.json // InitBindings intializes the bindings map by reading from bindings.json
func InitBindings() { func InitBindings() {
config.Bindings = DefaultBindings() config.Bindings = DefaultBindings("buffer")
var parsed map[string]string var parsed map[string]interface{}
defaults := DefaultBindings()
filename := filepath.Join(config.ConfigDir, "bindings.json") filename := filepath.Join(config.ConfigDir, "bindings.json")
createBindingsIfNotExist(filename) createBindingsIfNotExist(filename)
@@ -45,55 +50,52 @@ func InitBindings() {
} }
} }
for k, v := range defaults { for p, bind := range Binder {
BindKey(k, v) defaults := DefaultBindings(p)
for k, v := range defaults {
BindKey(k, v, bind)
}
} }
for k, v := range parsed { for k, v := range parsed {
BindKey(k, v) switch val := v.(type) {
} case string:
BindKey(k, val, Binder["buffer"])
defaultInfos := DefaultInfoBindings() case map[string]interface{}:
for k, v := range defaultInfos { bind := Binder[k]
BindInfoKey(k, v) for e, a := range val {
s, ok := a.(string)
if !ok {
screen.TermMessage("Error reading bindings.json: non-string and non-map entry", k)
} else {
BindKey(e, s, bind)
}
}
default:
screen.TermMessage("Error reading bindings.json: non-string and non-map entry", k)
}
} }
} }
func BindInfoKey(k, v string) { func BindKey(k, v string, bind func(e Event, a string)) {
event, err := findEvent(k) event, err := findEvent(k)
if err != nil { if err != nil {
screen.TermMessage(err) screen.TermMessage(err)
} }
switch e := event.(type) { bind(event, v)
case KeyEvent:
InfoMapKey(e, v)
case KeySequenceEvent:
InfoMapKey(e, v)
case MouseEvent:
InfoMapMouse(e, v)
case RawEvent:
InfoMapKey(e, v)
}
}
func BindKey(k, v string) { // switch e := event.(type) {
event, err := findEvent(k) // case KeyEvent:
if err != nil { // InfoMapKey(e, v)
screen.TermMessage(err) // case KeySequenceEvent:
} // InfoMapKey(e, v)
// case MouseEvent:
switch e := event.(type) { // InfoMapMouse(e, v)
case KeyEvent: // case RawEvent:
BufMapKey(e, v) // InfoMapKey(e, v)
case KeySequenceEvent: // }
BufMapKey(e, v)
case MouseEvent:
BufMapMouse(e, v)
case RawEvent:
BufMapKey(e, v)
}
config.Bindings[k] = v
} }
var r = regexp.MustCompile("<(.+?)>") var r = regexp.MustCompile("<(.+?)>")
@@ -276,7 +278,7 @@ func TryBindKey(k, v string, overwrite bool) (bool, error) {
parsed[k] = v parsed[k] = v
} }
BindKey(k, v) BindKey(k, v, Binder["buffer"])
txt, _ := json.MarshalIndent(parsed, "", " ") txt, _ := json.MarshalIndent(parsed, "", " ")
return true, ioutil.WriteFile(filename, append(txt, '\n'), 0644) return true, ioutil.WriteFile(filename, append(txt, '\n'), 0644)
@@ -316,9 +318,9 @@ func UnbindKey(k string) error {
} }
} }
defaults := DefaultBindings() defaults := DefaultBindings("buffer")
if a, ok := defaults[k]; ok { if a, ok := defaults[k]; ok {
BindKey(k, a) BindKey(k, a, Binder["buffer"])
} else if _, ok := config.Bindings[k]; ok { } else if _, ok := config.Bindings[k]; ok {
BufUnmap(key) BufUnmap(key)
delete(config.Bindings, k) delete(config.Bindings, k)

View File

@@ -1,7 +1,6 @@
package action package action
import ( import (
"log"
"strings" "strings"
"time" "time"
@@ -61,8 +60,17 @@ func LuaAction(fn string) func(*BufPane) bool {
} }
} }
// BufMapKey maps a key event to an action // BufMapKey maps an event to an action
func BufMapKey(k Event, action string) { func BufMapEvent(k Event, action string) {
switch e := k.(type) {
case KeyEvent, KeySequenceEvent, RawEvent:
bufMapKey(e, action)
case MouseEvent:
bufMapMouse(e, action)
}
}
func bufMapKey(k Event, action string) {
var actionfns []func(*BufPane) bool var actionfns []func(*BufPane) bool
var names []string var names []string
var types []byte var types []byte
@@ -145,13 +153,13 @@ func BufMapKey(k Event, action string) {
} }
// BufMapMouse maps a mouse event to an action // BufMapMouse maps a mouse event to an action
func BufMapMouse(k MouseEvent, action string) { func bufMapMouse(k MouseEvent, action string) {
if f, ok := BufMouseActions[action]; ok { if f, ok := BufMouseActions[action]; ok {
BufBindings.RegisterMouseBinding(k, BufMouseActionGeneral(f)) BufBindings.RegisterMouseBinding(k, BufMouseActionGeneral(f))
} else { } else {
// TODO // TODO
// delete(BufMouseBindings, k) // delete(BufMouseBindings, k)
BufMapKey(k, action) bufMapKey(k, action)
} }
} }
@@ -423,14 +431,14 @@ func (h *BufPane) Bindings() *KeyTree {
func (h *BufPane) DoKeyEvent(e Event) bool { func (h *BufPane) DoKeyEvent(e Event) bool {
binds := h.Bindings() binds := h.Bindings()
action, more := binds.NextEvent(e, nil) action, more := binds.NextEvent(e, nil)
log.Println("Next event", e, more)
if action != nil && !more { if action != nil && !more {
action(h) action(h)
binds.ResetEvents() binds.ResetEvents()
return true
} else if action == nil && !more { } else if action == nil && !more {
binds.ResetEvents() binds.ResetEvents()
} }
return false return more
} }
func (h *BufPane) execAction(action func(*BufPane) bool, name string, cursor int) bool { func (h *BufPane) execAction(action func(*BufPane) bool, name string, cursor int) bool {

View File

@@ -0,0 +1,21 @@
package action
var termdefaults = map[string]string{
"<Ctrl-q><Ctrl-q>": "Exit",
"<Ctrl-e><Ctrl-e>": "CommandMode",
"<Ctrl-w><Ctrl-w>": "NextSplit",
}
// DefaultBindings returns a map containing micro's default keybindings
func DefaultBindings(pane string) map[string]string {
switch pane {
case "info":
return infodefaults
case "buffer":
return bufdefaults
case "terminal":
return termdefaults
default:
return map[string]string{}
}
}

View File

@@ -1,184 +1,179 @@
package action package action
// DefaultBindings returns a map containing micro's default keybindings var bufdefaults = map[string]string{
func DefaultBindings() map[string]string { "Up": "CursorUp",
return map[string]string{ "Down": "CursorDown",
"Up": "CursorUp", "Right": "CursorRight",
"Down": "CursorDown", "Left": "CursorLeft",
"Right": "CursorRight", "ShiftUp": "SelectUp",
"Left": "CursorLeft", "ShiftDown": "SelectDown",
"ShiftUp": "SelectUp", "ShiftLeft": "SelectLeft",
"ShiftDown": "SelectDown", "ShiftRight": "SelectRight",
"ShiftLeft": "SelectLeft", "AltLeft": "WordLeft",
"ShiftRight": "SelectRight", "AltRight": "WordRight",
"AltLeft": "WordLeft", "AltUp": "MoveLinesUp",
"AltRight": "WordRight", "AltDown": "MoveLinesDown",
"AltUp": "MoveLinesUp", "AltShiftRight": "SelectWordRight",
"AltDown": "MoveLinesDown", "AltShiftLeft": "SelectWordLeft",
"AltShiftRight": "SelectWordRight", "CtrlLeft": "StartOfTextToggle",
"AltShiftLeft": "SelectWordLeft", "CtrlRight": "EndOfLine",
"CtrlLeft": "StartOfTextToggle", "CtrlShiftLeft": "SelectToStartOfTextToggle",
"CtrlRight": "EndOfLine", "ShiftHome": "SelectToStartOfTextToggle",
"CtrlShiftLeft": "SelectToStartOfTextToggle", "CtrlShiftRight": "SelectToEndOfLine",
"ShiftHome": "SelectToStartOfTextToggle", "ShiftEnd": "SelectToEndOfLine",
"CtrlShiftRight": "SelectToEndOfLine", "CtrlUp": "CursorStart",
"ShiftEnd": "SelectToEndOfLine", "CtrlDown": "CursorEnd",
"CtrlUp": "CursorStart", "CtrlShiftUp": "SelectToStart",
"CtrlDown": "CursorEnd", "CtrlShiftDown": "SelectToEnd",
"CtrlShiftUp": "SelectToStart", "Alt-{": "ParagraphPrevious",
"CtrlShiftDown": "SelectToEnd", "Alt-}": "ParagraphNext",
"Alt-{": "ParagraphPrevious", "Enter": "InsertNewline",
"Alt-}": "ParagraphNext", "CtrlH": "Backspace",
"Enter": "InsertNewline", "Backspace": "Backspace",
"CtrlH": "Backspace", "OldBackspace": "Backspace",
"Backspace": "Backspace", "Alt-CtrlH": "DeleteWordLeft",
"OldBackspace": "Backspace", "Alt-Backspace": "DeleteWordLeft",
"Alt-CtrlH": "DeleteWordLeft", "Tab": "Autocomplete|IndentSelection|InsertTab",
"Alt-Backspace": "DeleteWordLeft", "Backtab": "CycleAutocompleteBack|OutdentSelection|OutdentLine",
"Tab": "Autocomplete|IndentSelection|InsertTab", "Ctrl-o": "OpenFile",
"Backtab": "CycleAutocompleteBack|OutdentSelection|OutdentLine", "Ctrl-s": "Save",
"Ctrl-o": "OpenFile", "Ctrl-f": "Find",
"Ctrl-s": "Save", "Ctrl-n": "FindNext",
"Ctrl-f": "Find", "Ctrl-p": "FindPrevious",
"Ctrl-n": "FindNext", "Ctrl-z": "Undo",
"Ctrl-p": "FindPrevious", "Ctrl-y": "Redo",
"Ctrl-z": "Undo", "Ctrl-c": "CopyLine|Copy",
"Ctrl-y": "Redo", "Ctrl-x": "Cut",
"Ctrl-c": "CopyLine|Copy", "Ctrl-k": "CutLine",
"Ctrl-x": "Cut", "Ctrl-d": "DuplicateLine",
"Ctrl-k": "CutLine", "Ctrl-v": "Paste",
"Ctrl-d": "DuplicateLine", "Ctrl-a": "SelectAll",
"Ctrl-v": "Paste", "Ctrl-t": "AddTab",
"Ctrl-a": "SelectAll", "Alt-,": "PreviousTab",
"Ctrl-t": "AddTab", "Alt-.": "NextTab",
"Alt-,": "PreviousTab", "Home": "StartOfTextToggle",
"Alt-.": "NextTab", "End": "EndOfLine",
"Home": "StartOfTextToggle", "CtrlHome": "CursorStart",
"End": "EndOfLine", "CtrlEnd": "CursorEnd",
"CtrlHome": "CursorStart", "PageUp": "CursorPageUp",
"CtrlEnd": "CursorEnd", "PageDown": "CursorPageDown",
"PageUp": "CursorPageUp", "CtrlPageUp": "PreviousTab",
"PageDown": "CursorPageDown", "CtrlPageDown": "NextTab",
"CtrlPageUp": "PreviousTab", "Ctrl-g": "ToggleHelp",
"CtrlPageDown": "NextTab", "Alt-g": "ToggleKeyMenu",
"Ctrl-g": "ToggleHelp", "Ctrl-r": "ToggleRuler",
"Alt-g": "ToggleKeyMenu", "Ctrl-l": "command-edit:goto ",
"Ctrl-r": "ToggleRuler", "Delete": "Delete",
"Ctrl-l": "command-edit:goto ", "Ctrl-b": "ShellMode",
"Delete": "Delete", "Ctrl-q": "Quit",
"Ctrl-b": "ShellMode", "Ctrl-e": "CommandMode",
"Ctrl-q": "Quit", "Ctrl-w": "NextSplit",
"Ctrl-e": "CommandMode", "Ctrl-u": "ToggleMacro",
"Ctrl-w": "NextSplit", "Ctrl-j": "PlayMacro",
"Ctrl-u": "ToggleMacro", "Insert": "ToggleOverwriteMode",
"Ctrl-j": "PlayMacro",
"Insert": "ToggleOverwriteMode",
// Emacs-style keybindings // Emacs-style keybindings
"Alt-f": "WordRight", "Alt-f": "WordRight",
"Alt-b": "WordLeft", "Alt-b": "WordLeft",
"Alt-a": "StartOfText", "Alt-a": "StartOfText",
"Alt-e": "EndOfLine", "Alt-e": "EndOfLine",
// "Alt-p": "CursorUp", // "Alt-p": "CursorUp",
// "Alt-n": "CursorDown", // "Alt-n": "CursorDown",
// Integration with file managers // Integration with file managers
"F2": "Save", "F2": "Save",
"F3": "Find", "F3": "Find",
"F4": "Quit", "F4": "Quit",
"F7": "Find", "F7": "Find",
"F10": "Quit", "F10": "Quit",
"Esc": "Escape,Deselect,ClearInfo,RemoveAllMultiCursors", "Esc": "Escape,Deselect,ClearInfo,RemoveAllMultiCursors",
// Mouse bindings // Mouse bindings
"MouseWheelUp": "ScrollUp", "MouseWheelUp": "ScrollUp",
"MouseWheelDown": "ScrollDown", "MouseWheelDown": "ScrollDown",
"MouseLeft": "MousePress", "MouseLeft": "MousePress",
"MouseMiddle": "PastePrimary", "MouseMiddle": "PastePrimary",
"Ctrl-MouseLeft": "MouseMultiCursor", "Ctrl-MouseLeft": "MouseMultiCursor",
"Alt-n": "SpawnMultiCursor", "Alt-n": "SpawnMultiCursor",
"AltShiftUp": "SpawnMultiCursorUp", "AltShiftUp": "SpawnMultiCursorUp",
"AltShiftDown": "SpawnMultiCursorDown", "AltShiftDown": "SpawnMultiCursorDown",
"Alt-m": "SpawnMultiCursorSelect", "Alt-m": "SpawnMultiCursorSelect",
"Alt-p": "RemoveMultiCursor", "Alt-p": "RemoveMultiCursor",
"Alt-c": "RemoveAllMultiCursors", "Alt-c": "RemoveAllMultiCursors",
"Alt-x": "SkipMultiCursor", "Alt-x": "SkipMultiCursor",
}
} }
func DefaultInfoBindings() map[string]string { var infodefaults = map[string]string{
return map[string]string{ "Up": "HistoryUp",
"Up": "HistoryUp", "Down": "HistoryDown",
"Down": "HistoryDown", "Right": "CursorRight",
"Right": "CursorRight", "Left": "CursorLeft",
"Left": "CursorLeft", "ShiftUp": "SelectUp",
"ShiftUp": "SelectUp", "ShiftDown": "SelectDown",
"ShiftDown": "SelectDown", "ShiftLeft": "SelectLeft",
"ShiftLeft": "SelectLeft", "ShiftRight": "SelectRight",
"ShiftRight": "SelectRight", "AltLeft": "WordLeft",
"AltLeft": "WordLeft", "AltRight": "WordRight",
"AltRight": "WordRight", "AltUp": "CursorStart",
"AltUp": "CursorStart", "AltDown": "CursorEnd",
"AltDown": "CursorEnd", "AltShiftRight": "SelectWordRight",
"AltShiftRight": "SelectWordRight", "AltShiftLeft": "SelectWordLeft",
"AltShiftLeft": "SelectWordLeft", "CtrlLeft": "StartOfTextToggle",
"CtrlLeft": "StartOfTextToggle", "CtrlRight": "EndOfLine",
"CtrlRight": "EndOfLine", "CtrlShiftLeft": "SelectToStartOfTextToggle",
"CtrlShiftLeft": "SelectToStartOfTextToggle", "ShiftHome": "SelectToStartOfTextToggle",
"ShiftHome": "SelectToStartOfTextToggle", "CtrlShiftRight": "SelectToEndOfLine",
"CtrlShiftRight": "SelectToEndOfLine", "ShiftEnd": "SelectToEndOfLine",
"ShiftEnd": "SelectToEndOfLine", "CtrlUp": "CursorStart",
"CtrlUp": "CursorStart", "CtrlDown": "CursorEnd",
"CtrlDown": "CursorEnd", "CtrlShiftUp": "SelectToStart",
"CtrlShiftUp": "SelectToStart", "CtrlShiftDown": "SelectToEnd",
"CtrlShiftDown": "SelectToEnd", "Enter": "ExecuteCommand",
"Enter": "ExecuteCommand", "CtrlH": "Backspace",
"CtrlH": "Backspace", "Backspace": "Backspace",
"Backspace": "Backspace", "OldBackspace": "Backspace",
"OldBackspace": "Backspace", "Alt-CtrlH": "DeleteWordLeft",
"Alt-CtrlH": "DeleteWordLeft", "Alt-Backspace": "DeleteWordLeft",
"Alt-Backspace": "DeleteWordLeft", "Tab": "CommandComplete",
"Tab": "CommandComplete", "Backtab": "CycleAutocompleteBack",
"Backtab": "CycleAutocompleteBack", "Ctrl-z": "Undo",
"Ctrl-z": "Undo", "Ctrl-y": "Redo",
"Ctrl-y": "Redo", "Ctrl-c": "CopyLine|Copy",
"Ctrl-c": "CopyLine|Copy", "Ctrl-x": "Cut",
"Ctrl-x": "Cut", "Ctrl-k": "CutLine",
"Ctrl-k": "CutLine", "Ctrl-v": "Paste",
"Ctrl-v": "Paste", "Home": "StartOfTextToggle",
"Home": "StartOfTextToggle", "End": "EndOfLine",
"End": "EndOfLine", "CtrlHome": "CursorStart",
"CtrlHome": "CursorStart", "CtrlEnd": "CursorEnd",
"CtrlEnd": "CursorEnd", "Delete": "Delete",
"Delete": "Delete", "Ctrl-q": "AbortCommand",
"Ctrl-q": "AbortCommand", "Ctrl-e": "EndOfLine",
"Ctrl-e": "EndOfLine", "Ctrl-a": "StartOfLine",
"Ctrl-a": "StartOfLine", "Ctrl-w": "DeleteWordLeft",
"Ctrl-w": "DeleteWordLeft", "Insert": "ToggleOverwriteMode",
"Insert": "ToggleOverwriteMode", "Ctrl-b": "WordLeft",
"Ctrl-b": "WordLeft", "Ctrl-f": "WordRight",
"Ctrl-f": "WordRight", "Ctrl-d": "DeleteWordLeft",
"Ctrl-d": "DeleteWordLeft", "Ctrl-m": "ExecuteCommand",
"Ctrl-m": "ExecuteCommand", "Ctrl-n": "HistoryDown",
"Ctrl-n": "HistoryDown", "Ctrl-p": "HistoryUp",
"Ctrl-p": "HistoryUp", "Ctrl-u": "SelectToStart",
"Ctrl-u": "SelectToStart",
// Emacs-style keybindings // Emacs-style keybindings
"Alt-f": "WordRight", "Alt-f": "WordRight",
"Alt-b": "WordLeft", "Alt-b": "WordLeft",
"Alt-a": "StartOfText", "Alt-a": "StartOfText",
"Alt-e": "EndOfLine", "Alt-e": "EndOfLine",
// Integration with file managers // Integration with file managers
"F10": "AbortCommand", "F10": "AbortCommand",
"Esc": "AbortCommand", "Esc": "AbortCommand",
// Mouse bindings // Mouse bindings
"MouseWheelUp": "HistoryUp", "MouseWheelUp": "HistoryUp",
"MouseWheelDown": "HistoryDown", "MouseWheelDown": "HistoryDown",
"MouseLeft": "MousePress", "MouseLeft": "MousePress",
"MouseMiddle": "PastePrimary", "MouseMiddle": "PastePrimary",
}
} }

View File

@@ -2,185 +2,180 @@
package action package action
// DefaultBindings returns a map containing micro's default keybindings var bufdefaults = map[string]string{
func DefaultBindings() map[string]string { "Up": "CursorUp",
return map[string]string{ "Down": "CursorDown",
"Up": "CursorUp", "Right": "CursorRight",
"Down": "CursorDown", "Left": "CursorLeft",
"Right": "CursorRight", "ShiftUp": "SelectUp",
"Left": "CursorLeft", "ShiftDown": "SelectDown",
"ShiftUp": "SelectUp", "ShiftLeft": "SelectLeft",
"ShiftDown": "SelectDown", "ShiftRight": "SelectRight",
"ShiftLeft": "SelectLeft", "CtrlLeft": "WordLeft",
"ShiftRight": "SelectRight", "CtrlRight": "WordRight",
"CtrlLeft": "WordLeft", "AltUp": "MoveLinesUp",
"CtrlRight": "WordRight", "AltDown": "MoveLinesDown",
"AltUp": "MoveLinesUp", "CtrlShiftRight": "SelectWordRight",
"AltDown": "MoveLinesDown", "CtrlShiftLeft": "SelectWordLeft",
"CtrlShiftRight": "SelectWordRight", "AltLeft": "StartOfTextToggle",
"CtrlShiftLeft": "SelectWordLeft", "AltRight": "EndOfLine",
"AltLeft": "StartOfTextToggle", "AltShiftLeft": "SelectToStartOfTextToggle",
"AltRight": "EndOfLine", "ShiftHome": "SelectToStartOfTextToggle",
"AltShiftLeft": "SelectToStartOfTextToggle", "AltShiftRight": "SelectToEndOfLine",
"ShiftHome": "SelectToStartOfTextToggle", "ShiftEnd": "SelectToEndOfLine",
"AltShiftRight": "SelectToEndOfLine", "CtrlUp": "CursorStart",
"ShiftEnd": "SelectToEndOfLine", "CtrlDown": "CursorEnd",
"CtrlUp": "CursorStart", "CtrlShiftUp": "SelectToStart",
"CtrlDown": "CursorEnd", "CtrlShiftDown": "SelectToEnd",
"CtrlShiftUp": "SelectToStart", "Alt-{": "ParagraphPrevious",
"CtrlShiftDown": "SelectToEnd", "Alt-}": "ParagraphNext",
"Alt-{": "ParagraphPrevious", "Enter": "InsertNewline",
"Alt-}": "ParagraphNext", "CtrlH": "Backspace",
"Enter": "InsertNewline", "Backspace": "Backspace",
"CtrlH": "Backspace", "OldBackspace": "Backspace",
"Backspace": "Backspace", "Alt-CtrlH": "DeleteWordLeft",
"OldBackspace": "Backspace", "Alt-Backspace": "DeleteWordLeft",
"Alt-CtrlH": "DeleteWordLeft", "Tab": "Autocomplete|IndentSelection|InsertTab",
"Alt-Backspace": "DeleteWordLeft", "Backtab": "CycleAutocompleteBack|OutdentSelection|OutdentLine",
"Tab": "Autocomplete|IndentSelection|InsertTab", "Ctrl-o": "OpenFile",
"Backtab": "CycleAutocompleteBack|OutdentSelection|OutdentLine", "Ctrl-s": "Save",
"Ctrl-o": "OpenFile", "Ctrl-f": "Find",
"Ctrl-s": "Save", "Ctrl-n": "FindNext",
"Ctrl-f": "Find", "Ctrl-p": "FindPrevious",
"Ctrl-n": "FindNext", "Ctrl-z": "Undo",
"Ctrl-p": "FindPrevious", "Ctrl-y": "Redo",
"Ctrl-z": "Undo", "Ctrl-c": "CopyLine|Copy",
"Ctrl-y": "Redo", "Ctrl-x": "Cut",
"Ctrl-c": "CopyLine|Copy", "Ctrl-k": "CutLine",
"Ctrl-x": "Cut", "Ctrl-d": "DuplicateLine",
"Ctrl-k": "CutLine", "Ctrl-v": "Paste",
"Ctrl-d": "DuplicateLine", "Ctrl-a": "SelectAll",
"Ctrl-v": "Paste", "Ctrl-t": "AddTab",
"Ctrl-a": "SelectAll", "Alt-,": "PreviousTab",
"Ctrl-t": "AddTab", "Alt-.": "NextTab",
"Alt-,": "PreviousTab", "Home": "StartOfTextToggle",
"Alt-.": "NextTab", "End": "EndOfLine",
"Home": "StartOfTextToggle", "CtrlHome": "CursorStart",
"End": "EndOfLine", "CtrlEnd": "CursorEnd",
"CtrlHome": "CursorStart", "PageUp": "CursorPageUp",
"CtrlEnd": "CursorEnd", "PageDown": "CursorPageDown",
"PageUp": "CursorPageUp", "CtrlPageUp": "PreviousTab",
"PageDown": "CursorPageDown", "CtrlPageDown": "NextTab",
"CtrlPageUp": "PreviousTab", "Ctrl-g": "ToggleHelp",
"CtrlPageDown": "NextTab", "Alt-g": "ToggleKeyMenu",
"Ctrl-g": "ToggleHelp", "Ctrl-r": "ToggleRuler",
"Alt-g": "ToggleKeyMenu", "Ctrl-l": "command-edit:goto ",
"Ctrl-r": "ToggleRuler", "Delete": "Delete",
"Ctrl-l": "command-edit:goto ", "Ctrl-b": "ShellMode",
"Delete": "Delete", "Ctrl-q": "Quit",
"Ctrl-b": "ShellMode", "Ctrl-e": "CommandMode",
"Ctrl-q": "Quit", "Ctrl-w": "NextSplit",
"Ctrl-e": "CommandMode", "Ctrl-u": "ToggleMacro",
"Ctrl-w": "NextSplit", "Ctrl-j": "PlayMacro",
"Ctrl-u": "ToggleMacro", "Insert": "ToggleOverwriteMode",
"Ctrl-j": "PlayMacro",
"Insert": "ToggleOverwriteMode",
// Emacs-style keybindings // Emacs-style keybindings
"Alt-f": "WordRight", "Alt-f": "WordRight",
"Alt-b": "WordLeft", "Alt-b": "WordLeft",
"Alt-a": "StartOfText", "Alt-a": "StartOfText",
"Alt-e": "EndOfLine", "Alt-e": "EndOfLine",
// "Alt-p": "CursorUp", // "Alt-p": "CursorUp",
// "Alt-n": "CursorDown", // "Alt-n": "CursorDown",
// Integration with file managers // Integration with file managers
"F2": "Save", "F2": "Save",
"F3": "Find", "F3": "Find",
"F4": "Quit", "F4": "Quit",
"F7": "Find", "F7": "Find",
"F10": "Quit", "F10": "Quit",
"Esc": "Escape,Deselect,ClearInfo,RemoveAllMultiCursors", "Esc": "Escape,Deselect,ClearInfo,RemoveAllMultiCursors",
// Mouse bindings // Mouse bindings
"MouseWheelUp": "ScrollUp", "MouseWheelUp": "ScrollUp",
"MouseWheelDown": "ScrollDown", "MouseWheelDown": "ScrollDown",
"MouseLeft": "MousePress", "MouseLeft": "MousePress",
"MouseMiddle": "PastePrimary", "MouseMiddle": "PastePrimary",
"Ctrl-MouseLeft": "MouseMultiCursor", "Ctrl-MouseLeft": "MouseMultiCursor",
"Alt-n": "SpawnMultiCursor", "Alt-n": "SpawnMultiCursor",
"Alt-m": "SpawnMultiCursorSelect", "Alt-m": "SpawnMultiCursorSelect",
"AltShiftUp": "SpawnMultiCursorUp", "AltShiftUp": "SpawnMultiCursorUp",
"AltShiftDown": "SpawnMultiCursorDown", "AltShiftDown": "SpawnMultiCursorDown",
"Alt-p": "RemoveMultiCursor", "Alt-p": "RemoveMultiCursor",
"Alt-c": "RemoveAllMultiCursors", "Alt-c": "RemoveAllMultiCursors",
"Alt-x": "SkipMultiCursor", "Alt-x": "SkipMultiCursor",
}
} }
func DefaultInfoBindings() map[string]string { var infodefaults = map[string]string{
return map[string]string{ "Up": "HistoryUp",
"Up": "HistoryUp", "Down": "HistoryDown",
"Down": "HistoryDown", "Right": "CursorRight",
"Right": "CursorRight", "Left": "CursorLeft",
"Left": "CursorLeft", "ShiftUp": "SelectUp",
"ShiftUp": "SelectUp", "ShiftDown": "SelectDown",
"ShiftDown": "SelectDown", "ShiftLeft": "SelectLeft",
"ShiftLeft": "SelectLeft", "ShiftRight": "SelectRight",
"ShiftRight": "SelectRight", "AltLeft": "StartOfTextToggle",
"AltLeft": "StartOfTextToggle", "AltRight": "EndOfLine",
"AltRight": "EndOfLine", "AltUp": "CursorStart",
"AltUp": "CursorStart", "AltDown": "CursorEnd",
"AltDown": "CursorEnd", "AltShiftRight": "SelectWordRight",
"AltShiftRight": "SelectWordRight", "AltShiftLeft": "SelectWordLeft",
"AltShiftLeft": "SelectWordLeft", "CtrlLeft": "WordLeft",
"CtrlLeft": "WordLeft", "CtrlRight": "WordRight",
"CtrlRight": "WordRight", "CtrlShiftLeft": "SelectToStartOfTextToggle",
"CtrlShiftLeft": "SelectToStartOfTextToggle", "ShiftHome": "SelectToStartOfTextToggle",
"ShiftHome": "SelectToStartOfTextToggle", "CtrlShiftRight": "SelectToEndOfLine",
"CtrlShiftRight": "SelectToEndOfLine", "ShiftEnd": "SelectToEndOfLine",
"ShiftEnd": "SelectToEndOfLine", "CtrlUp": "CursorStart",
"CtrlUp": "CursorStart", "CtrlDown": "CursorEnd",
"CtrlDown": "CursorEnd", "CtrlShiftUp": "SelectToStart",
"CtrlShiftUp": "SelectToStart", "CtrlShiftDown": "SelectToEnd",
"CtrlShiftDown": "SelectToEnd", "Enter": "ExecuteCommand",
"Enter": "ExecuteCommand", "CtrlH": "Backspace",
"CtrlH": "Backspace", "Backspace": "Backspace",
"Backspace": "Backspace", "OldBackspace": "Backspace",
"OldBackspace": "Backspace", "Alt-CtrlH": "DeleteWordLeft",
"Alt-CtrlH": "DeleteWordLeft", "Alt-Backspace": "DeleteWordLeft",
"Alt-Backspace": "DeleteWordLeft", "Tab": "CommandComplete",
"Tab": "CommandComplete", "Backtab": "CycleAutocompleteBack",
"Backtab": "CycleAutocompleteBack", "Ctrl-z": "Undo",
"Ctrl-z": "Undo", "Ctrl-y": "Redo",
"Ctrl-y": "Redo", "Ctrl-c": "CopyLine|Copy",
"Ctrl-c": "CopyLine|Copy", "Ctrl-x": "Cut",
"Ctrl-x": "Cut", "Ctrl-k": "CutLine",
"Ctrl-k": "CutLine", "Ctrl-v": "Paste",
"Ctrl-v": "Paste", "Home": "StartOfTextToggle",
"Home": "StartOfTextToggle", "End": "EndOfLine",
"End": "EndOfLine", "CtrlHome": "CursorStart",
"CtrlHome": "CursorStart", "CtrlEnd": "CursorEnd",
"CtrlEnd": "CursorEnd", "Delete": "Delete",
"Delete": "Delete", "Ctrl-q": "AbortCommand",
"Ctrl-q": "AbortCommand", "Ctrl-e": "EndOfLine",
"Ctrl-e": "EndOfLine", "Ctrl-a": "StartOfLine",
"Ctrl-a": "StartOfLine", "Ctrl-w": "DeleteWordLeft",
"Ctrl-w": "DeleteWordLeft", "Insert": "ToggleOverwriteMode",
"Insert": "ToggleOverwriteMode", "Ctrl-b": "WordLeft",
"Ctrl-b": "WordLeft", "Ctrl-f": "WordRight",
"Ctrl-f": "WordRight", "Ctrl-d": "DeleteWordLeft",
"Ctrl-d": "DeleteWordLeft", "Ctrl-m": "ExecuteCommand",
"Ctrl-m": "ExecuteCommand", "Ctrl-n": "HistoryDown",
"Ctrl-n": "HistoryDown", "Ctrl-p": "HistoryUp",
"Ctrl-p": "HistoryUp", "Ctrl-u": "SelectToStart",
"Ctrl-u": "SelectToStart",
// Emacs-style keybindings // Emacs-style keybindings
"Alt-f": "WordRight", "Alt-f": "WordRight",
"Alt-b": "WordLeft", "Alt-b": "WordLeft",
"Alt-a": "StartOfText", "Alt-a": "StartOfText",
"Alt-e": "EndOfLine", "Alt-e": "EndOfLine",
// Integration with file managers // Integration with file managers
"F10": "AbortCommand", "F10": "AbortCommand",
"Esc": "AbortCommand", "Esc": "AbortCommand",
// Mouse bindings // Mouse bindings
"MouseWheelUp": "HistoryUp", "MouseWheelUp": "HistoryUp",
"MouseWheelDown": "HistoryDown", "MouseWheelDown": "HistoryDown",
"MouseLeft": "MousePress", "MouseLeft": "MousePress",
"MouseMiddle": "PastePrimary", "MouseMiddle": "PastePrimary",
}
} }

View File

@@ -20,7 +20,16 @@ func init() {
InfoBufBindings = NewKeyTree() InfoBufBindings = NewKeyTree()
} }
func InfoMapKey(k Event, action string) { func InfoMapEvent(k Event, action string) {
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 { if f, ok := InfoKeyActions[action]; ok {
InfoBindings.RegisterKeyBinding(k, InfoKeyActionGeneral(f)) InfoBindings.RegisterKeyBinding(k, InfoKeyActionGeneral(f))
} else if f, ok := BufKeyActions[action]; ok { } else if f, ok := BufKeyActions[action]; ok {
@@ -28,18 +37,19 @@ func InfoMapKey(k Event, action string) {
} }
} }
func InfoMapMouse(k MouseEvent, action string) { func infoMapMouse(k MouseEvent, action string) {
// TODO: map mouse
if f, ok := BufMouseActions[action]; ok { if f, ok := BufMouseActions[action]; ok {
InfoBufBindings.RegisterMouseBinding(k, BufMouseActionGeneral(f)) InfoBufBindings.RegisterMouseBinding(k, BufMouseActionGeneral(f))
} else { } else {
InfoMapKey(k, action) infoMapKey(k, action)
} }
} }
func InfoKeyActionGeneral(a InfoKeyAction) PaneKeyAction { func InfoKeyActionGeneral(a InfoKeyAction) PaneKeyAction {
return func(p Pane) bool { return func(p Pane) bool {
a(p.(*InfoPane)) a(p.(*InfoPane))
return false return true
} }
} }
@@ -107,7 +117,6 @@ func (h *InfoPane) HandleEvent(event tcell.Event) {
// DoKeyEvent executes a key event for the command bar, doing any overridden actions // DoKeyEvent executes a key event for the command bar, doing any overridden actions
func (h *InfoPane) DoKeyEvent(e KeyEvent) bool { func (h *InfoPane) DoKeyEvent(e KeyEvent) bool {
done := false
action, more := InfoBindings.NextEvent(e, nil) action, more := InfoBindings.NextEvent(e, nil)
if action != nil && !more { if action != nil && !more {
action(h) action(h)
@@ -119,15 +128,18 @@ func (h *InfoPane) DoKeyEvent(e KeyEvent) bool {
// return false //TODO:? // return false //TODO:?
} }
action, more = InfoBufBindings.NextEvent(e, nil) if !more {
if action != nil && !more { action, more = InfoBufBindings.NextEvent(e, nil)
done = action(h.BufPane) if action != nil && !more {
InfoBufBindings.ResetEvents() done := action(h.BufPane)
} else if action == nil && !more { InfoBufBindings.ResetEvents()
InfoBufBindings.ResetEvents() return done
} else if action == nil && !more {
InfoBufBindings.ResetEvents()
}
} }
return done return more
} }
// HistoryUp cycles history up // HistoryUp cycles history up
@@ -181,7 +193,7 @@ func (h *InfoPane) AbortCommand() {
h.DonePrompt(true) h.DonePrompt(true)
} }
// BufKeyActions contains the list of all possible key actions the bufhandler could execute // InfoKeyActions contains the list of all possible key actions the infopane could execute
var InfoKeyActions = map[string]InfoKeyAction{ var InfoKeyActions = map[string]InfoKeyAction{
"HistoryUp": (*InfoPane).HistoryUp, "HistoryUp": (*InfoPane).HistoryUp,
"HistoryDown": (*InfoPane).HistoryDown, "HistoryDown": (*InfoPane).HistoryDown,

View File

@@ -12,6 +12,41 @@ import (
"github.com/zyedidia/terminal" "github.com/zyedidia/terminal"
) )
type TermKeyAction func(*TermPane)
var TermBindings *KeyTree
func init() {
TermBindings = NewKeyTree()
}
func TermKeyActionGeneral(a TermKeyAction) PaneKeyAction {
return func(p Pane) bool {
a(p.(*TermPane))
return true
}
}
func TermMapEvent(k Event, action string) {
switch e := k.(type) {
case KeyEvent, KeySequenceEvent, RawEvent:
termMapKey(e, action)
case MouseEvent:
termMapMouse(e, action)
}
}
func termMapKey(k Event, action string) {
if f, ok := TermKeyActions[action]; ok {
TermBindings.RegisterKeyBinding(k, TermKeyActionGeneral(f))
}
}
func termMapMouse(k MouseEvent, action string) {
// TODO: map mouse
termMapKey(k, action)
}
type TermPane struct { type TermPane struct {
*shell.Terminal *shell.Terminal
display.Window display.Window
@@ -53,6 +88,7 @@ func (t *TermPane) Tab() *Tab {
func (t *TermPane) Close() {} func (t *TermPane) Close() {}
// Quit closes this termpane
func (t *TermPane) Quit() { func (t *TermPane) Quit() {
t.Close() t.Close()
if len(MainTab().Panes) > 1 { if len(MainTab().Panes) > 1 {
@@ -66,6 +102,7 @@ func (t *TermPane) Quit() {
} }
} }
// Unsplit removes this split
func (t *TermPane) Unsplit() { func (t *TermPane) Unsplit() {
n := MainTab().GetNode(t.id) n := MainTab().GetNode(t.id)
n.Unsplit() n.Unsplit()
@@ -81,6 +118,26 @@ func (t *TermPane) Unsplit() {
// copy-paste // copy-paste
func (t *TermPane) HandleEvent(event tcell.Event) { func (t *TermPane) HandleEvent(event tcell.Event) {
if e, ok := event.(*tcell.EventKey); ok { if e, ok := event.(*tcell.EventKey); ok {
ke := KeyEvent{
code: e.Key(),
mod: e.Modifiers(),
r: e.Rune(),
}
action, more := TermBindings.NextEvent(ke, nil)
if !more {
if action != nil {
action(t)
TermBindings.ResetEvents()
return
}
TermBindings.ResetEvents()
}
if more {
return
}
if t.Status == shell.TTDone { if t.Status == shell.TTDone {
switch e.Key() { switch e.Key() {
case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter: case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter:
@@ -134,6 +191,41 @@ func (t *TermPane) HandleEvent(event tcell.Event) {
} }
} }
// Exit closes the termpane
func (t *TermPane) Exit() {
t.Terminal.Close()
t.Quit()
}
// CommandMode opens the termpane's command mode
func (t *TermPane) CommandMode() {
InfoBar.Prompt("> ", "", "TerminalCommand", nil, func(resp string, canceled bool) {
if !canceled {
t.HandleCommand(resp)
}
})
}
// NextSplit moves to the next split
func (t *TermPane) NextSplit() {
a := t.tab.active
if a < len(t.tab.Panes)-1 {
a++
} else {
a = 0
}
t.tab.SetActive(a)
}
// HandleCommand handles a command for the term pane
func (t *TermPane) HandleCommand(input string) { func (t *TermPane) HandleCommand(input string) {
InfoBar.Error("Commands are unsupported in term for now") InfoBar.Error("Commands are unsupported in term for now")
} }
// TermKeyActions contains the list of all possible key actions the termpane could execute
var TermKeyActions = map[string]TermKeyAction{
"Exit": (*TermPane).Exit,
"CommandMode": (*TermPane).CommandMode,
"NextSplit": (*TermPane).NextSplit,
}