github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/edit/key.go (about) 1 package edit 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Key represents a single keyboard input, typically assembled from a escape 9 // sequence. 10 type Key struct { 11 Rune rune 12 Mod Mod 13 } 14 15 // Predefined special Key values. 16 var ( 17 // Default is used in the key binding table to indicate default binding. 18 Default = Key{DefaultBindingRune, 0} 19 ) 20 21 // Mod represents a modifier key. 22 type Mod byte 23 24 // Values for Mod. 25 const ( 26 // Shift is the shift modifier. It is only applied to special keys (e.g. 27 // Shift-F1). For instance 'A' and '@' which are typically entered with the 28 // shift key pressed, are not considered to be shift-modified. 29 Shift Mod = 1 << iota 30 // Alt is the alt modifier, traditionally known as the meta modifier. 31 Alt 32 Ctrl 33 ) 34 35 func (k Key) String() (s string) { 36 if k.Mod&Ctrl != 0 { 37 s += "Ctrl-" 38 } 39 if k.Mod&Alt != 0 { 40 s += "Alt-" 41 } 42 if k.Mod&Shift != 0 { 43 s += "Shift-" 44 } 45 if k.Rune > 0 { 46 if name, ok := keyNames[k.Rune]; ok { 47 s += name 48 } else { 49 s += string(k.Rune) 50 } 51 } else { 52 i := int(-k.Rune) 53 if i >= len(functionKeyNames) { 54 s += fmt.Sprintf("(bad function key %d)", i) 55 } else { 56 s += functionKeyNames[-k.Rune] 57 } 58 } 59 return 60 } 61 62 // modifierByName maps a name to an modifier. It is used for parsing keys where 63 // the modifier string is first turned to lower case, so that all of C, c, 64 // CTRL, Ctrl and ctrl can represent the Ctrl modifier. 65 var modifierByName = map[string]Mod{ 66 "s": Shift, "shift": Shift, 67 "a": Alt, "alt": Alt, 68 "m": Alt, "meta": Alt, 69 "c": Ctrl, "ctrl": Ctrl, 70 } 71 72 // parseKey parses a key. The syntax is: 73 // 74 // Key = { Mod ('+' | '-') } BareKey 75 // 76 // BareKey = FunctionKeyName | SingleRune 77 func parseKey(s string) (Key, error) { 78 var k Key 79 // parse modifiers 80 for { 81 i := strings.IndexAny(s, "+-") 82 if i == -1 { 83 break 84 } 85 modname := strings.ToLower(s[:i]) 86 mod, ok := modifierByName[modname] 87 if !ok { 88 return Key{}, fmt.Errorf("bad modifier: %q", modname) 89 } 90 k.Mod |= mod 91 s = s[i+1:] 92 } 93 94 if len(s) == 1 { 95 k.Rune = rune(s[0]) 96 return k, nil 97 } 98 99 for r, name := range keyNames { 100 if s == name { 101 k.Rune = r 102 return k, nil 103 } 104 } 105 106 for i, name := range functionKeyNames[1:] { 107 if s == name { 108 k.Rune = rune(-i - 1) 109 return k, nil 110 } 111 } 112 113 return Key{}, fmt.Errorf("bad key: %q", s) 114 } 115 116 // Special negative runes to represent function keys, used in the Rune field of 117 // the Key struct. 118 const ( 119 F1 rune = -iota - 1 120 F2 121 F3 122 F4 123 F5 124 F6 125 F7 126 F8 127 F9 128 F10 129 F11 130 F12 131 132 Up 133 Down 134 Right 135 Left 136 137 Home 138 Insert 139 Delete 140 End 141 PageUp 142 PageDown 143 144 DefaultBindingRune // A special value used in DefaultBinding 145 146 // Some function key names are just aliases for their ASCII representation 147 148 Tab = '\t' 149 Enter = '\n' 150 Backspace = 0x7f 151 ) 152 153 var functionKeyNames = [...]string{ 154 "(Invalid)", 155 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", 156 "Up", "Down", "Right", "Left", 157 "Home", "Insert", "Delete", "End", "PageUp", "PageDown", "default", 158 } 159 160 var keyNames = map[rune]string{ 161 Tab: "Tab", Enter: "Enter", Backspace: "Backspace", 162 }