package main type Keymap struct { motions map[string]Motion operators map[string]Operator actions map[string]Action // standalone actions: i.e., 'i', 'a' } func NewNormalKeymap() *Keymap { return &Keymap{ motions: map[string]Motion{ "j": MoveDown{1}, "k": MoveUp{1}, "h": MoveLeft{1}, "l": MoveRight{1}, "G": MoveToBottom{}, "gg": MoveToTop{}, // multi-key example // "w": MoveWord{1}, // "b": MoveWordBack{1}, "0": MoveToLineStart{}, "$": MoveToLineEnd{}, }, operators: map[string]Operator{ // "d": DeleteOp{}, // "c": ChangeOp{}, // "y": YankOp{}, }, actions: map[string]Action{ "i": EnterInsert{}, "a": EnterInsertAfter{}, "I": EnterInsertLineStart{}, "A": EnterInsertLineEnd{}, "o": OpenLineBelow{}, "O": OpenLineAbove{}, "x": DeleteChar{1}, // "p": Paste{}, // "u": Undo{}, // "ctrl+r": Redo{}, "ctrl+c": Quit{}, }, } } // Lookup returns what type of binding a key is func (km *Keymap) Lookup(key string) (kind string, value any) { if m, ok := km.motions[key]; ok { return "motion", m } if o, ok := km.operators[key]; ok { return "operator", o } if a, ok := km.actions[key]; ok { return "action", a } return "", nil } // HasPrefix returns true if any binding starts with this prefix func (km *Keymap) HasPrefix(prefix string) bool { for key := range km.motions { if len(key) > len(prefix) && key[:len(prefix)] == prefix { return true } } for key := range km.operators { if len(key) > len(prefix) && key[:len(prefix)] == prefix { return true } } for key := range km.actions { if len(key) > len(prefix) && key[:len(prefix)] == prefix { return true } } return false }