Browse code

Merge pull request #46 from keith/ks/arrow-keys

Support arrow key movements

John Hawthorn authored on 08/10/2017 04:33:40 • GitHub committed on 08/10/2017 04:33:40
Showing 2 changed files

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