1// Copyright 2014 The gocui Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package gocui
6
7import (
8 "strings"
9
10 "github.com/awesome-gocui/termbox-go"
11)
12
13// Key represents special keys or keys combinations.
14type Key termbox.Key
15
16// Modifier allows to define special keys combinations. They can be used
17// in combination with Keys or Runes when a new keybinding is defined.
18type Modifier termbox.Modifier
19
20// Keybidings are used to link a given key-press event with a handler.
21type keybinding struct {
22 viewName string
23 key Key
24 ch rune
25 mod Modifier
26 handler func(*Gui, *View) error
27}
28
29// Parse takes the input string and extracts the keybinding.
30// Returns a Key / rune, a Modifier and an error.
31func Parse(input string) (interface{}, Modifier, error) {
32 if len(input) == 1 {
33 _, r, err := getKey(rune(input[0]))
34 if err != nil {
35 return nil, ModNone, err
36 }
37 return r, ModNone, nil
38 }
39
40 var modifier Modifier
41 cleaned := make([]string, 0)
42
43 tokens := strings.Split(input, "+")
44 for _, t := range tokens {
45 normalized := strings.Title(strings.ToLower(t))
46 if t == "Alt" {
47 modifier = ModAlt
48 continue
49 }
50 cleaned = append(cleaned, normalized)
51 }
52
53 key, exist := translate[strings.Join(cleaned, "")]
54 if !exist {
55 return nil, ModNone, ErrNoSuchKeybind
56 }
57
58 return key, modifier, nil
59}
60
61// ParseAll takes an array of strings and returns a map of all keybindings.
62func ParseAll(input []string) (map[interface{}]Modifier, error) {
63 ret := make(map[interface{}]Modifier)
64 for _, i := range input {
65 k, m, err := Parse(i)
66 if err != nil {
67 return ret, err
68 }
69 ret[k] = m
70 }
71 return ret, nil
72}
73
74// MustParse takes the input string and returns a Key / rune and a Modifier.
75// It will panic if any error occured.
76func MustParse(input string) (interface{}, Modifier) {
77 k, m, err := Parse(input)
78 if err != nil {
79 panic(err)
80 }
81 return k, m
82}
83
84// MustParseAll takes an array of strings and returns a map of all keybindings.
85// It will panic if any error occured.
86func MustParseAll(input []string) map[interface{}]Modifier {
87 result, err := ParseAll(input)
88 if err != nil {
89 panic(err)
90 }
91 return result
92}
93
94// newKeybinding returns a new Keybinding object.
95func newKeybinding(viewname string, key Key, ch rune, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) {
96 kb = &keybinding{
97 viewName: viewname,
98 key: key,
99 ch: ch,
100 mod: mod,
101 handler: handler,
102 }
103 return kb
104}
105
106// matchKeypress returns if the keybinding matches the keypress.
107func (kb *keybinding) matchKeypress(key Key, ch rune, mod Modifier) bool {
108 return kb.key == key && kb.ch == ch && kb.mod == mod
109}
110
111// matchView returns if the keybinding matches the current view.
112func (kb *keybinding) matchView(v *View) bool {
113 // if the user is typing in a field, ignore char keys
114 if v == nil || (v.Editable && kb.ch != 0) {
115 return false
116 }
117 return kb.viewName == v.name
118}
119
120// translations for strings to keys
121var translate = map[string]Key{
122 "F1": KeyF1,
123 "F2": KeyF2,
124 "F3": KeyF3,
125 "F4": KeyF4,
126 "F5": KeyF5,
127 "F6": KeyF6,
128 "F7": KeyF7,
129 "F8": KeyF8,
130 "F9": KeyF9,
131 "F10": KeyF10,
132 "F11": KeyF11,
133 "F12": KeyF12,
134 "Insert": KeyInsert,
135 "Delete": KeyDelete,
136 "Home": KeyHome,
137 "End": KeyEnd,
138 "Pgup": KeyPgup,
139 "Pgdn": KeyPgdn,
140 "ArrowUp": KeyArrowUp,
141 "ArrowDown": KeyArrowDown,
142 "ArrowLeft": KeyArrowLeft,
143 "ArrowRight": KeyArrowRight,
144 "CtrlTilde": KeyCtrlTilde,
145 "Ctrl2": KeyCtrl2,
146 "CtrlSpace": KeyCtrlSpace,
147 "CtrlA": KeyCtrlA,
148 "CtrlB": KeyCtrlB,
149 "CtrlC": KeyCtrlC,
150 "CtrlD": KeyCtrlD,
151 "CtrlE": KeyCtrlE,
152 "CtrlF": KeyCtrlF,
153 "CtrlG": KeyCtrlG,
154 "Backspace": KeyBackspace,
155 "CtrlH": KeyCtrlH,
156 "Tab": KeyTab,
157 "CtrlI": KeyCtrlI,
158 "CtrlJ": KeyCtrlJ,
159 "CtrlK": KeyCtrlK,
160 "CtrlL": KeyCtrlL,
161 "Enter": KeyEnter,
162 "CtrlM": KeyCtrlM,
163 "CtrlN": KeyCtrlN,
164 "CtrlO": KeyCtrlO,
165 "CtrlP": KeyCtrlP,
166 "CtrlQ": KeyCtrlQ,
167 "CtrlR": KeyCtrlR,
168 "CtrlS": KeyCtrlS,
169 "CtrlT": KeyCtrlT,
170 "CtrlU": KeyCtrlU,
171 "CtrlV": KeyCtrlV,
172 "CtrlW": KeyCtrlW,
173 "CtrlX": KeyCtrlX,
174 "CtrlY": KeyCtrlY,
175 "CtrlZ": KeyCtrlZ,
176 "Esc": KeyEsc,
177 "CtrlLsqBracket": KeyCtrlLsqBracket,
178 "Ctrl3": KeyCtrl3,
179 "Ctrl4": KeyCtrl4,
180 "CtrlBackslash": KeyCtrlBackslash,
181 "Ctrl5": KeyCtrl5,
182 "CtrlRsqBracket": KeyCtrlRsqBracket,
183 "Ctrl6": KeyCtrl6,
184 "Ctrl7": KeyCtrl7,
185 "CtrlSlash": KeyCtrlSlash,
186 "CtrlUnderscore": KeyCtrlUnderscore,
187 "Space": KeySpace,
188 "Backspace2": KeyBackspace2,
189 "Ctrl8": KeyCtrl8,
190 "Mouseleft": MouseLeft,
191 "Mousemiddle": MouseMiddle,
192 "Mouseright": MouseRight,
193 "Mouserelease": MouseRelease,
194 "MousewheelUp": MouseWheelUp,
195 "MousewheelDown": MouseWheelDown,
196}
197
198// Special keys.
199const (
200 KeyF1 Key = Key(termbox.KeyF1)
201 KeyF2 = Key(termbox.KeyF2)
202 KeyF3 = Key(termbox.KeyF3)
203 KeyF4 = Key(termbox.KeyF4)
204 KeyF5 = Key(termbox.KeyF5)
205 KeyF6 = Key(termbox.KeyF6)
206 KeyF7 = Key(termbox.KeyF7)
207 KeyF8 = Key(termbox.KeyF8)
208 KeyF9 = Key(termbox.KeyF9)
209 KeyF10 = Key(termbox.KeyF10)
210 KeyF11 = Key(termbox.KeyF11)
211 KeyF12 = Key(termbox.KeyF12)
212 KeyInsert = Key(termbox.KeyInsert)
213 KeyDelete = Key(termbox.KeyDelete)
214 KeyHome = Key(termbox.KeyHome)
215 KeyEnd = Key(termbox.KeyEnd)
216 KeyPgup = Key(termbox.KeyPgup)
217 KeyPgdn = Key(termbox.KeyPgdn)
218 KeyArrowUp = Key(termbox.KeyArrowUp)
219 KeyArrowDown = Key(termbox.KeyArrowDown)
220 KeyArrowLeft = Key(termbox.KeyArrowLeft)
221 KeyArrowRight = Key(termbox.KeyArrowRight)
222
223 MouseLeft = Key(termbox.MouseLeft)
224 MouseMiddle = Key(termbox.MouseMiddle)
225 MouseRight = Key(termbox.MouseRight)
226 MouseRelease = Key(termbox.MouseRelease)
227 MouseWheelUp = Key(termbox.MouseWheelUp)
228 MouseWheelDown = Key(termbox.MouseWheelDown)
229)
230
231// Keys combinations.
232const (
233 KeyCtrlTilde Key = Key(termbox.KeyCtrlTilde)
234 KeyCtrl2 = Key(termbox.KeyCtrl2)
235 KeyCtrlSpace = Key(termbox.KeyCtrlSpace)
236 KeyCtrlA = Key(termbox.KeyCtrlA)
237 KeyCtrlB = Key(termbox.KeyCtrlB)
238 KeyCtrlC = Key(termbox.KeyCtrlC)
239 KeyCtrlD = Key(termbox.KeyCtrlD)
240 KeyCtrlE = Key(termbox.KeyCtrlE)
241 KeyCtrlF = Key(termbox.KeyCtrlF)
242 KeyCtrlG = Key(termbox.KeyCtrlG)
243 KeyBackspace = Key(termbox.KeyBackspace)
244 KeyCtrlH = Key(termbox.KeyCtrlH)
245 KeyTab = Key(termbox.KeyTab)
246 KeyCtrlI = Key(termbox.KeyCtrlI)
247 KeyCtrlJ = Key(termbox.KeyCtrlJ)
248 KeyCtrlK = Key(termbox.KeyCtrlK)
249 KeyCtrlL = Key(termbox.KeyCtrlL)
250 KeyEnter = Key(termbox.KeyEnter)
251 KeyCtrlM = Key(termbox.KeyCtrlM)
252 KeyCtrlN = Key(termbox.KeyCtrlN)
253 KeyCtrlO = Key(termbox.KeyCtrlO)
254 KeyCtrlP = Key(termbox.KeyCtrlP)
255 KeyCtrlQ = Key(termbox.KeyCtrlQ)
256 KeyCtrlR = Key(termbox.KeyCtrlR)
257 KeyCtrlS = Key(termbox.KeyCtrlS)
258 KeyCtrlT = Key(termbox.KeyCtrlT)
259 KeyCtrlU = Key(termbox.KeyCtrlU)
260 KeyCtrlV = Key(termbox.KeyCtrlV)
261 KeyCtrlW = Key(termbox.KeyCtrlW)
262 KeyCtrlX = Key(termbox.KeyCtrlX)
263 KeyCtrlY = Key(termbox.KeyCtrlY)
264 KeyCtrlZ = Key(termbox.KeyCtrlZ)
265 KeyEsc = Key(termbox.KeyEsc)
266 KeyCtrlLsqBracket = Key(termbox.KeyCtrlLsqBracket)
267 KeyCtrl3 = Key(termbox.KeyCtrl3)
268 KeyCtrl4 = Key(termbox.KeyCtrl4)
269 KeyCtrlBackslash = Key(termbox.KeyCtrlBackslash)
270 KeyCtrl5 = Key(termbox.KeyCtrl5)
271 KeyCtrlRsqBracket = Key(termbox.KeyCtrlRsqBracket)
272 KeyCtrl6 = Key(termbox.KeyCtrl6)
273 KeyCtrl7 = Key(termbox.KeyCtrl7)
274 KeyCtrlSlash = Key(termbox.KeyCtrlSlash)
275 KeyCtrlUnderscore = Key(termbox.KeyCtrlUnderscore)
276 KeySpace = Key(termbox.KeySpace)
277 KeyBackspace2 = Key(termbox.KeyBackspace2)
278 KeyCtrl8 = Key(termbox.KeyCtrl8)
279)
280
281// Modifiers.
282const (
283 ModNone Modifier = Modifier(0)
284 ModAlt = Modifier(termbox.ModAlt)
285)