X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fbindings.go;h=c14ce7240961550f3b3d53fe7a10fb06309bb820;hb=fc2566a0de9ee7e8dff4ac30a0c7cc82878e274c;hp=7f5dccdcc56cae0f28386a577d595e6a192f0ea5;hpb=8b8fffb98dbeb3051b16da05960e6a803b1d58fe;p=micro.git diff --git a/cmd/micro/bindings.go b/cmd/micro/bindings.go index 7f5dccdc..c14ce724 100644 --- a/cmd/micro/bindings.go +++ b/cmd/micro/bindings.go @@ -1,14 +1,17 @@ package main import ( + "fmt" "io/ioutil" "os" "strings" + "unicode" "github.com/flynn/json5" "github.com/zyedidia/tcell" ) +var bindingsStr map[string]string var bindings map[Key][]func(*View, bool) bool var mouseBindings map[Key][]func(*View, bool, *tcell.EventMouse) bool var helpBinding string @@ -42,6 +45,8 @@ var bindingActions = map[string]func(*View, bool) bool{ "DeleteWordLeft": (*View).DeleteWordLeft, "SelectToStartOfLine": (*View).SelectToStartOfLine, "SelectToEndOfLine": (*View).SelectToEndOfLine, + "ParagraphPrevious": (*View).ParagraphPrevious, + "ParagraphNext": (*View).ParagraphNext, "InsertNewline": (*View).InsertNewline, "InsertSpace": (*View).InsertSpace, "Backspace": (*View).Backspace, @@ -85,6 +90,7 @@ var bindingActions = map[string]func(*View, bool) bool{ "ClearStatus": (*View).ClearStatus, "ShellMode": (*View).ShellMode, "CommandMode": (*View).CommandMode, + "ToggleOverwriteMode": (*View).ToggleOverwriteMode, "Escape": (*View).Escape, "Quit": (*View).Quit, "QuitAll": (*View).QuitAll, @@ -105,6 +111,7 @@ var bindingActions = map[string]func(*View, bool) bool{ "RemoveMultiCursor": (*View).RemoveMultiCursor, "RemoveAllMultiCursors": (*View).RemoveAllMultiCursors, "SkipMultiCursor": (*View).SkipMultiCursor, + "JumpToMatchingBrace": (*View).JumpToMatchingBrace, // This was changed to InsertNewline but I don't want to break backwards compatibility "InsertEnter": (*View).InsertNewline, @@ -258,11 +265,13 @@ type Key struct { modifiers tcell.ModMask buttons tcell.ButtonMask r rune + escape string } // InitBindings initializes the keybindings for micro func InitBindings() { bindings = make(map[Key][]func(*View, bool) bool) + bindingsStr = make(map[string]string) mouseBindings = make(map[Key][]func(*View, bool, *tcell.EventMouse) bool) var parsed map[string]string @@ -314,6 +323,14 @@ modSearch: case strings.HasPrefix(k, "Shift"): k = k[5:] modifiers |= tcell.ModShift + case strings.HasPrefix(k, "\x1b"): + return Key{ + keyCode: -1, + modifiers: modifiers, + buttons: -1, + r: 0, + escape: k, + }, true default: break modSearch } @@ -324,6 +341,7 @@ modSearch: // first. if modifiers&tcell.ModCtrl != 0 { // see if the key is in bindingKeys with the Ctrl prefix. + k = string(unicode.ToUpper(rune(k[0]))) + k[1:] if code, ok := bindingKeys["Ctrl"+k]; ok { // It is, we're done. return Key{ @@ -389,6 +407,43 @@ func findMouseAction(v string) func(*View, bool, *tcell.EventMouse) bool { return action } +// TryBindKey tries to bind a key by writing to configDir/bindings.json +// This function is unused for now +func TryBindKey(k, v string) { + filename := configDir + "/bindings.json" + if _, e := os.Stat(filename); e == nil { + input, err := ioutil.ReadFile(filename) + if err != nil { + TermMessage("Error reading bindings.json file: " + err.Error()) + return + } + + conflict := -1 + lines := strings.Split(string(input), "\n") + for i, l := range lines { + parts := strings.Split(l, ":") + if len(parts) >= 2 { + if strings.Contains(parts[0], k) { + conflict = i + TermMessage("Warning: Keybinding conflict:", k, " has been overwritten") + } + } + } + + binding := fmt.Sprintf(" \"%s\": \"%s\",", k, v) + if conflict == -1 { + lines = append([]string{lines[0], binding}, lines[conflict:]...) + } else { + lines = append(append(lines[:conflict], binding), lines[conflict+1:]...) + } + txt := strings.Join(lines, "\n") + err = ioutil.WriteFile(filename, []byte(txt), 0644) + if err != nil { + TermMessage("Error") + } + } +} + // BindKey takes a key and an action and binds the two together func BindKey(k, v string) { key, ok := findKey(k) @@ -413,6 +468,7 @@ func BindKey(k, v string) { if actionNames[0] == "UnbindKey" { delete(bindings, key) delete(mouseBindings, key) + delete(bindingsStr, k) if len(actionNames) == 1 { return } @@ -423,6 +479,12 @@ func BindKey(k, v string) { for _, actionName := range actionNames { if strings.HasPrefix(actionName, "Mouse") { mouseActions = append(mouseActions, findMouseAction(actionName)) + } else if strings.HasPrefix(actionName, "command:") { + cmd := strings.SplitN(actionName, ":", 2)[1] + actions = append(actions, CommandAction(cmd)) + } else if strings.HasPrefix(actionName, "command-edit:") { + cmd := strings.SplitN(actionName, ":", 2)[1] + actions = append(actions, CommandEditAction(cmd)) } else { actions = append(actions, findAction(actionName)) } @@ -432,6 +494,7 @@ func BindKey(k, v string) { // Can't have a binding be both mouse and normal delete(mouseBindings, key) bindings[key] = actions + bindingsStr[k] = v } else if len(mouseActions) > 0 { // Can't have a binding be both mouse and normal delete(bindings, key) @@ -466,6 +529,8 @@ func DefaultBindings() map[string]string { "CtrlDown": "CursorEnd", "CtrlShiftUp": "SelectToStart", "CtrlShiftDown": "SelectToEnd", + "Alt-{": "ParagraphPrevious", + "Alt-}": "ParagraphNext", "Enter": "InsertNewline", "CtrlH": "Backspace", "Backspace": "Backspace", @@ -508,6 +573,7 @@ func DefaultBindings() map[string]string { "CtrlW": "NextSplit", "CtrlU": "ToggleMacro", "CtrlJ": "PlayMacro", + "Insert": "ToggleOverwriteMode", // Emacs-style keybindings "Alt-f": "WordRight",