Browse code

Use a struct to store keybindings

John Hawthorn authored on 20/06/2016 08:45:09
Showing 2 changed files

... ...
@@ -151,10 +151,6 @@ static void append_search(tty_interface_t *state, char ch) {
151 151
 	}
152 152
 }
153 153
 
154
-#define KEY_CTRL(key) ((key) - ('@'))
155
-#define KEY_DEL 127
156
-#define KEY_ESC 27
157
-
158 154
 static void update_search(tty_interface_t *state) {
159 155
 	choices_search(state->choices, state->search);
160 156
 	strcpy(state->last_search, state->search);
... ...
@@ -170,6 +166,7 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices,
170 166
 	state->choices = choices;
171 167
 	state->options = options;
172 168
 
169
+	strcpy(state->input, "");
173 170
 	strcpy(state->search, "");
174 171
 	strcpy(state->last_search, "");
175 172
 
... ...
@@ -181,42 +178,67 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices,
181 178
 	update_search(state);
182 179
 }
183 180
 
184
-int tty_interface_run(tty_interface_t *state) {
185
-	tty_t *tty = state->tty;
181
+typedef struct {
182
+	const char *key;
183
+	void (*action)(tty_interface_t *);
184
+} keybinding_t;
185
+
186
+#define KEY_CTRL(key) ((const char[]){((key) - ('@')), '\0'})
187
+
188
+static const keybinding_t keybindings[] = {{"\x7f", action_del_char},	/* DEL */
189
+					   {KEY_CTRL('H'), action_del_char}, /* Backspace (C-H) */
190
+					   {KEY_CTRL('W'), action_del_word}, /* C-W */
191
+					   {KEY_CTRL('U'), action_del_all},  /* C-U */
192
+					   {KEY_CTRL('I'), action_autocomplete}, /* TAB (C-I ) */
193
+					   {KEY_CTRL('C'), action_exit},	 /* C-C */
194
+					   {KEY_CTRL('D'), action_exit},	 /* C-D */
195
+					   {KEY_CTRL('M'), action_emit},	 /* CR */
196
+					   {KEY_CTRL('P'), action_prev},	 /* C-P */
197
+					   {KEY_CTRL('N'), action_next},	 /* C-N */
198
+
199
+					   {"\x1b[A", action_prev}, /* UP */
200
+					   {"\x1bOA", action_prev}, /* UP */
201
+					   {"\x1b[B", action_next}, /* DOWN */
202
+					   {"\x1bOB", action_next}, /* DOWN */
203
+					   {NULL, NULL}};
204
+
205
+#undef KEY_CTRL
206
+
207
+void handle_input(tty_interface_t *state) {
208
+	char *input = state->input;
209
+
210
+	/* See if we have matched a keybinding */
211
+	for (int i = 0; keybindings[i].key; i++) {
212
+		if (!strcmp(input, keybindings[i].key)) {
213
+			keybindings[i].action(state);
214
+			strcpy(input, "");
215
+			return;
216
+		}
217
+	}
218
+
219
+	/* Check if we are in the middle of a keybinding */
220
+	for (int i = 0; keybindings[i].key; i++)
221
+		if (!strncmp(input, keybindings[i].key, strlen(input)))
222
+			return;
186 223
 
187
-	char ch;
224
+	/* No matching keybinding, add to search */
225
+	for (int i = 0; input[i]; i++)
226
+		if (isprint(input[i]))
227
+			append_search(state, input[i]);
228
+
229
+	/* We have processed the input, so clear it */
230
+	strcpy(input, "");
231
+}
232
+
233
+int tty_interface_run(tty_interface_t *state) {
188 234
 	while (state->exit < 0) {
189 235
 		draw(state);
190
-		ch = tty_getchar(tty);
191
-		if (isprint(ch)) {
192
-			append_search(state, ch);
193
-		} else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
194
-			action_del_char(state);
195
-		} else if (ch == KEY_CTRL('U')) { /* C-U */
196
-			action_del_all(state);
197
-		} else if (ch == KEY_CTRL('W')) { /* C-W */
198
-			action_del_word(state);
199
-		} else if (ch == KEY_CTRL('N')) { /* C-N */
200
-			action_next(state);
201
-		} else if (ch == KEY_CTRL('P')) { /* C-P */
202
-			action_prev(state);
203
-		} else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
204
-			action_autocomplete(state);
205
-		} else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
206
-			action_exit(state);
207
-		} else if (ch == KEY_CTRL('M')) { /* CR */
208
-			action_emit(state);
209
-		} else if (ch == KEY_ESC) { /* ESC */
210
-			ch = tty_getchar(tty);
211
-			if (ch == '[' || ch == 'O') {
212
-				ch = tty_getchar(tty);
213
-				if (ch == 'A') { /* UP ARROW */
214
-					action_prev(state);
215
-				} else if (ch == 'B') { /* DOWN ARROW */
216
-					action_next(state);
217
-				}
218
-			}
219
-		}
236
+
237
+		char s[2] = {tty_getchar(state->tty), '\0'};
238
+		strcat(state->input, s);
239
+
240
+		handle_input(state);
241
+
220 242
 		update_state(state);
221 243
 	}
222 244
 
... ...
@@ -15,6 +15,8 @@ typedef struct {
15 15
 	char search[SEARCH_SIZE_MAX + 1];
16 16
 	char last_search[SEARCH_SIZE_MAX + 1];
17 17
 
18
+	char input[32]; /* Pending input buffer */
19
+
18 20
 	int exit;
19 21
 } tty_interface_t;
20 22