Browse code

Support arrow key movements

Keith Smiley authored on 22/07/2017 03:58:04
Showing 2 changed files

... ...
@@ -93,7 +93,9 @@ static void draw(tty_interface_t *state) {
93 93
 	if (num_lines > 0) {
94 94
 		tty_moveup(tty, num_lines);
95 95
 	}
96
-	tty_setcol(tty, strlen(options->prompt) + strlen(state->search));
96
+
97
+	int length = strlen(options->prompt) + strlen(state->search);
98
+	tty_setcol(tty, length + state->offset);
97 99
 	tty_flush(tty);
98 100
 }
99 101
 
... ...
@@ -131,8 +133,15 @@ static void action_emit(tty_interface_t *state) {
131 133
 }
132 134
 
133 135
 static void action_del_char(tty_interface_t *state) {
134
-	if (*state->search)
135
-		state->search[strlen(state->search) - 1] = '\0';
136
+	if (*state->search) {
137
+		int length = strlen(state->search);
138
+		int index = length + state->offset - 1;
139
+		if (index < 0) {
140
+			return;
141
+		}
142
+
143
+		memmove(&state->search[index], &state->search[index + 1], length - index);
144
+	}
136 145
 }
137 146
 
138 147
 static void action_del_word(tty_interface_t *state) {
... ...
@@ -161,6 +170,24 @@ static void action_next(tty_interface_t *state) {
161 170
 	choices_next(state->choices);
162 171
 }
163 172
 
173
+static void action_left(tty_interface_t *state) {
174
+	if ((unsigned long)abs(state->offset) < strlen(state->search))
175
+		state->offset--;
176
+}
177
+
178
+static void action_right(tty_interface_t *state) {
179
+	if (state->offset < 0)
180
+		state->offset++;
181
+}
182
+
183
+static void action_beginning(tty_interface_t *state) {
184
+	state->offset = -strlen(state->search);
185
+}
186
+
187
+static void action_end(tty_interface_t *state) {
188
+	state->offset = 0;
189
+}
190
+
164 191
 static void action_pageup(tty_interface_t *state) {
165 192
 	update_state(state);
166 193
 	for(size_t i = 0; i < state->options->num_lines && state->choices->selection > 0; i++)
... ...
@@ -192,8 +219,14 @@ static void append_search(tty_interface_t *state, char ch) {
192 219
 	char *search = state->search;
193 220
 	size_t search_size = strlen(search);
194 221
 	if (search_size < SEARCH_SIZE_MAX) {
195
-		search[search_size++] = ch;
196
-		search[search_size] = '\0';
222
+		int location = state->offset + search_size;
223
+		for (int i = search_size; i >= 0; i--) {
224
+			if (i >= location) {
225
+				search[i + 1] = search[i];
226
+			}
227
+		}
228
+
229
+		search[location] = ch;
197 230
 	}
198 231
 }
199 232
 
... ...
@@ -201,6 +234,7 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices,
201 234
 	state->tty = tty;
202 235
 	state->choices = choices;
203 236
 	state->options = options;
237
+	state->offset = 0;
204 238
 
205 239
 	strcpy(state->input, "");
206 240
 	strcpy(state->search, "");
... ...
@@ -233,7 +267,13 @@ static const keybinding_t keybindings[] = {{"\x7f", action_del_char},	/* DEL */
233 267
 					   {KEY_CTRL('N'), action_next},	 /* C-N */
234 268
 					   {KEY_CTRL('K'), action_prev},	 /* C-J */
235 269
 					   {KEY_CTRL('J'), action_next},	 /* C-K */
270
+					   {KEY_CTRL('A'), action_beginning},    /* C-A */
271
+					   {KEY_CTRL('E'), action_end},		 /* C-E */
236 272
 
273
+					   {"\x1bOD", action_left}, /* LEFT */
274
+					   {"\x1b[D", action_left}, /* LEFT */
275
+					   {"\x1bOC", action_right}, /* RIGHT */
276
+					   {"\x1b[C", action_right}, /* RIGHT */
237 277
 					   {"\x1b[A", action_prev}, /* UP */
238 278
 					   {"\x1bOA", action_prev}, /* UP */
239 279
 					   {"\x1b[B", action_next}, /* DOWN */
... ...
@@ -14,6 +14,7 @@ typedef struct {
14 14
 
15 15
 	char search[SEARCH_SIZE_MAX + 1];
16 16
 	char last_search[SEARCH_SIZE_MAX + 1];
17
+	int offset;
17 18
 
18 19
 	char input[32]; /* Pending input buffer */
19 20