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
"DeleteWordLeft": (*View).DeleteWordLeft,
"SelectToStartOfLine": (*View).SelectToStartOfLine,
"SelectToEndOfLine": (*View).SelectToEndOfLine,
+ "ParagraphPrevious": (*View).ParagraphPrevious,
+ "ParagraphNext": (*View).ParagraphNext,
"InsertNewline": (*View).InsertNewline,
"InsertSpace": (*View).InsertSpace,
"Backspace": (*View).Backspace,
"ClearStatus": (*View).ClearStatus,
"ShellMode": (*View).ShellMode,
"CommandMode": (*View).CommandMode,
+ "ToggleOverwriteMode": (*View).ToggleOverwriteMode,
"Escape": (*View).Escape,
"Quit": (*View).Quit,
"QuitAll": (*View).QuitAll,
"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,
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
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
}
// 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{
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)
if actionNames[0] == "UnbindKey" {
delete(bindings, key)
delete(mouseBindings, key)
+ delete(bindingsStr, k)
if len(actionNames) == 1 {
return
}
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))
}
// 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)
"CtrlDown": "CursorEnd",
"CtrlShiftUp": "SelectToStart",
"CtrlShiftDown": "SelectToEnd",
+ "Alt-{": "ParagraphPrevious",
+ "Alt-}": "ParagraphNext",
"Enter": "InsertNewline",
"CtrlH": "Backspace",
"Backspace": "Backspace",
"CtrlW": "NextSplit",
"CtrlU": "ToggleMacro",
"CtrlJ": "PlayMacro",
+ "Insert": "ToggleOverwriteMode",
// Emacs-style keybindings
"Alt-f": "WordRight",