aboutsummaryrefslogtreecommitdiff
path: root/config/bindings.go
blob: c10b68f68585c39ea7396aa18b4d47f8ac0ae69e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
package config

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"strings"

	"github.com/gdamore/tcell"
)

type KeyStroke struct {
	Key  tcell.Key
	Rune rune
}

type Binding struct {
	Output []KeyStroke
	Input  []KeyStroke
}

type KeyBindings []*Binding

const (
	BINDING_FOUND = iota
	BINDING_INCOMPLETE
	BINDING_NOT_FOUND
)

type BindingSearchResult int

func NewKeyBindings() *KeyBindings {
	return &KeyBindings{}
}

func (bindings *KeyBindings) Add(binding *Binding) {
	// TODO: Search for conflicts?
	*bindings = append(*bindings, binding)
}

func (bindings *KeyBindings) GetBinding(
	input []KeyStroke) (BindingSearchResult, []KeyStroke) {

	incomplete := false
	// TODO: This could probably be a sorted list to speed things up
	// TODO: Deal with bindings that share a prefix
	for _, binding := range *bindings {
		if len(binding.Input) < len(input) {
			continue
		}
		for i, stroke := range input {
			if stroke != binding.Input[i] {
				goto next
			}
		}
		if len(binding.Input) != len(input) {
			incomplete = true
		} else {
			return BINDING_FOUND, binding.Output
		}
	next:
	}
	if incomplete {
		return BINDING_INCOMPLETE, nil
	}
	return BINDING_NOT_FOUND, nil
}

var (
	keyNames map[string]tcell.Key
)

func ParseKeyStrokes(keystrokes string) ([]KeyStroke, error) {
	var strokes []KeyStroke
	buf := bytes.NewBufferString(keystrokes)
	for {
		tok, _, err := buf.ReadRune()
		if err == io.EOF {
			break
		} else if err != nil {
			return nil, err
		}
		// TODO: make it possible to bind to < or > themselves (and default to
		// switching accounts)
		switch tok {
		case '<':
			name, err := buf.ReadString(byte('>'))
			if err == io.EOF {
				return nil, errors.New("Expecting '>'")
			} else if err != nil {
				return nil, err
			} else if name == ">" {
				return nil, errors.New("Expected a key name")
			}
			name = name[:len(name)-1]
			if key, ok := keyNames[strings.ToLower(name)]; ok {
				strokes = append(strokes, KeyStroke{
					Key: key,
				})
			} else {
				return nil, errors.New(fmt.Sprintf("Unknown key '%s'", name))
			}
		case '>':
			return nil, errors.New("Found '>' without '<'")
		default:
			strokes = append(strokes, KeyStroke{
				Key:  tcell.KeyRune,
				Rune: tok,
			})
		}
	}
	return strokes, nil
}

func ParseBinding(input, output string) (*Binding, error) {
	in, err := ParseKeyStrokes(input)
	if err != nil {
		return nil, err
	}
	out, err := ParseKeyStrokes(output)
	if err != nil {
		return nil, err
	}
	return &Binding{
		Input:  in,
		Output: out,
	}, nil
}

func init() {
	keyNames = make(map[string]tcell.Key)
	keyNames["up"] = tcell.KeyUp
	keyNames["down"] = tcell.KeyDown
	keyNames["right"] = tcell.KeyRight
	keyNames["left"] = tcell.KeyLeft
	keyNames["upleft"] = tcell.KeyUpLeft
	keyNames["upright"] = tcell.KeyUpRight
	keyNames["downleft"] = tcell.KeyDownLeft
	keyNames["downright"] = tcell.KeyDownRight
	keyNames["center"] = tcell.KeyCenter
	keyNames["pgup"] = tcell.KeyPgUp
	keyNames["pgdn"] = tcell.KeyPgDn
	keyNames["home"] = tcell.KeyHome
	keyNames["end"] = tcell.KeyEnd
	keyNames["insert"] = tcell.KeyInsert
	keyNames["delete"] = tcell.KeyDelete
	keyNames["help"] = tcell.KeyHelp
	keyNames["exit"] = tcell.KeyExit
	keyNames["clear"] = tcell.KeyClear
	keyNames["cancel"] = tcell.KeyCancel
	keyNames["print"] = tcell.KeyPrint
	keyNames["pause"] = tcell.KeyPause
	keyNames["backtab"] = tcell.KeyBacktab
	keyNames["f1"] = tcell.KeyF1
	keyNames["f2"] = tcell.KeyF2
	keyNames["f3"] = tcell.KeyF3
	keyNames["f4"] = tcell.KeyF4
	keyNames["f5"] = tcell.KeyF5
	keyNames["f6"] = tcell.KeyF6
	keyNames["f7"] = tcell.KeyF7
	keyNames["f8"] = tcell.KeyF8
	keyNames["f9"] = tcell.KeyF9
	keyNames["f10"] = tcell.KeyF10
	keyNames["f11"] = tcell.KeyF11
	keyNames["f12"] = tcell.KeyF12
	keyNames["f13"] = tcell.KeyF13
	keyNames["f14"] = tcell.KeyF14
	keyNames["f15"] = tcell.KeyF15
	keyNames["f16"] = tcell.KeyF16
	keyNames["f17"] = tcell.KeyF17
	keyNames["f18"] = tcell.KeyF18
	keyNames["f19"] = tcell.KeyF19
	keyNames["f20"] = tcell.KeyF20
	keyNames["f21"] = tcell.KeyF21
	keyNames["f22"] = tcell.KeyF22
	keyNames["f23"] = tcell.KeyF23
	keyNames["f24"] = tcell.KeyF24
	keyNames["f25"] = tcell.KeyF25
	keyNames["f26"] = tcell.KeyF26
	keyNames["f27"] = tcell.KeyF27
	keyNames["f28"] = tcell.KeyF28
	keyNames["f29"] = tcell.KeyF29
	keyNames["f30"] = tcell.KeyF30
	keyNames["f31"] = tcell.KeyF31
	keyNames["f32"] = tcell.KeyF32
	keyNames["f33"] = tcell.KeyF33
	keyNames["f34"] = tcell.KeyF34
	keyNames["f35"] = tcell.KeyF35
	keyNames["f36"] = tcell.KeyF36
	keyNames["f37"] = tcell.KeyF37
	keyNames["f38"] = tcell.KeyF38
	keyNames["f39"] = tcell.KeyF39
	keyNames["f40"] = tcell.KeyF40
	keyNames["f41"] = tcell.KeyF41
	keyNames["f42"] = tcell.KeyF42
	keyNames["f43"] = tcell.KeyF43
	keyNames["f44"] = tcell.KeyF44
	keyNames["f45"] = tcell.KeyF45
	keyNames["f46"] = tcell.KeyF46
	keyNames["f47"] = tcell.KeyF47
	keyNames["f48"] = tcell.KeyF48
	keyNames["f49"] = tcell.KeyF49
	keyNames["f50"] = tcell.KeyF50
	keyNames["f51"] = tcell.KeyF51
	keyNames["f52"] = tcell.KeyF52
	keyNames["f53"] = tcell.KeyF53
	keyNames["f54"] = tcell.KeyF54
	keyNames["f55"] = tcell.KeyF55
	keyNames["f56"] = tcell.KeyF56
	keyNames["f57"] = tcell.KeyF57
	keyNames["f58"] = tcell.KeyF58
	keyNames["f59"] = tcell.KeyF59
	keyNames["f60"] = tcell.KeyF60
	keyNames["f61"] = tcell.KeyF61
	keyNames["f62"] = tcell.KeyF62
	keyNames["f63"] = tcell.KeyF63
	keyNames["f64"] = tcell.KeyF64
	keyNames["c-space"] = tcell.KeyCtrlSpace
	keyNames["c-a"] = tcell.KeyCtrlA
	keyNames["c-b"] = tcell.KeyCtrlB
	keyNames["c-c"] = tcell.KeyCtrlC
	keyNames["c-d"] = tcell.KeyCtrlD
	keyNames["c-e"] = tcell.KeyCtrlE
	keyNames["c-f"] = tcell.KeyCtrlF
	keyNames["c-g"] = tcell.KeyCtrlG
	keyNames["c-h"] = tcell.KeyCtrlH
	keyNames["c-i"] = tcell.KeyCtrlI
	keyNames["c-j"] = tcell.KeyCtrlJ
	keyNames["c-k"] = tcell.KeyCtrlK
	keyNames["c-l"] = tcell.KeyCtrlL
	keyNames["c-m"] = tcell.KeyCtrlM
	keyNames["c-n"] = tcell.KeyCtrlN
	keyNames["c-o"] = tcell.KeyCtrlO
	keyNames["c-p"] = tcell.KeyCtrlP
	keyNames["c-q"] = tcell.KeyCtrlQ
	keyNames["c-r"] = tcell.KeyCtrlR
	keyNames["c-s"] = tcell.KeyCtrlS
	keyNames["c-t"] = tcell.KeyCtrlT
	keyNames["c-u"] = tcell.KeyCtrlU
	keyNames["c-v"] = tcell.KeyCtrlV
	keyNames["c-w"] = tcell.KeyCtrlW
	keyNames["c-x"] = tcell.KeyCtrlX
	keyNames["c-y"] = tcell.KeyCtrlY
	keyNames["c-z"] = tcell.KeyCtrlZ
	keyNames["c-]"] = tcell.KeyCtrlLeftSq
	keyNames["c-\\"] = tcell.KeyCtrlBackslash
	keyNames["c-["] = tcell.KeyCtrlRightSq
	keyNames["c-^"] = tcell.KeyCtrlCarat
	keyNames["c-_"] = tcell.KeyCtrlUnderscore
	keyNames["NUL"] = tcell.KeyNUL
	keyNames["SOH"] = tcell.KeySOH
	keyNames["STX"] = tcell.KeySTX
	keyNames["ETX"] = tcell.KeyETX
	keyNames["EOT"] = tcell.KeyEOT
	keyNames["ENQ"] = tcell.KeyENQ
	keyNames["ACK"] = tcell.KeyACK
	keyNames["BEL"] = tcell.KeyBEL
	keyNames["BS"] = tcell.KeyBS
	keyNames["TAB"] = tcell.KeyTAB
	keyNames["LF"] = tcell.KeyLF
	keyNames["VT"] = tcell.KeyVT
	keyNames["FF"] = tcell.KeyFF
	keyNames["CR"] = tcell.KeyCR
	keyNames["SO"] = tcell.KeySO
	keyNames["SI"] = tcell.KeySI
	keyNames["DLE"] = tcell.KeyDLE
	keyNames["DC1"] = tcell.KeyDC1
	keyNames["DC2"] = tcell.KeyDC2
	keyNames["DC3"] = tcell.KeyDC3
	keyNames["DC4"] = tcell.KeyDC4
	keyNames["NAK"] = tcell.KeyNAK
	keyNames["SYN"] = tcell.KeySYN
	keyNames["ETB"] = tcell.KeyETB
	keyNames["CAN"] = tcell.KeyCAN
	keyNames["EM"] = tcell.KeyEM
	keyNames["SUB"] = tcell.KeySUB
	keyNames["ESC"] = tcell.KeyESC
	keyNames["FS"] = tcell.KeyFS
	keyNames["GS"] = tcell.KeyGS
	keyNames["RS"] = tcell.KeyRS
	keyNames["US"] = tcell.KeyUS
	keyNames["DEL"] = tcell.KeyDEL
}