Support arrow key movements
| ... | ... |
@@ -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 */
|