From e0ce095657cc0458fa8a217d27872ec32ed814f1 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Fri, 21 Jul 2017 20:58:04 -0700 Subject: Support arrow key movements --- src/tty_interface.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- src/tty_interface.h | 1 + 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/tty_interface.c b/src/tty_interface.c index fc903e6..ab20eec 100644 --- a/src/tty_interface.c +++ b/src/tty_interface.c @@ -93,7 +93,9 @@ static void draw(tty_interface_t *state) { if (num_lines > 0) { tty_moveup(tty, num_lines); } - tty_setcol(tty, strlen(options->prompt) + strlen(state->search)); + + int length = strlen(options->prompt) + strlen(state->search); + tty_setcol(tty, length + state->offset); tty_flush(tty); } @@ -131,8 +133,15 @@ static void action_emit(tty_interface_t *state) { } static void action_del_char(tty_interface_t *state) { - if (*state->search) - state->search[strlen(state->search) - 1] = '\0'; + if (*state->search) { + int length = strlen(state->search); + int index = length + state->offset - 1; + if (index < 0) { + return; + } + + memmove(&state->search[index], &state->search[index + 1], length - index); + } } static void action_del_word(tty_interface_t *state) { @@ -161,6 +170,24 @@ static void action_next(tty_interface_t *state) { choices_next(state->choices); } +static void action_left(tty_interface_t *state) { + if ((unsigned long)abs(state->offset) < strlen(state->search)) + state->offset--; +} + +static void action_right(tty_interface_t *state) { + if (state->offset < 0) + state->offset++; +} + +static void action_beginning(tty_interface_t *state) { + state->offset = -strlen(state->search); +} + +static void action_end(tty_interface_t *state) { + state->offset = 0; +} + static void action_pageup(tty_interface_t *state) { update_state(state); 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) { char *search = state->search; size_t search_size = strlen(search); if (search_size < SEARCH_SIZE_MAX) { - search[search_size++] = ch; - search[search_size] = '\0'; + int location = state->offset + search_size; + for (int i = search_size; i >= 0; i--) { + if (i >= location) { + search[i + 1] = search[i]; + } + } + + search[location] = ch; } } @@ -201,6 +234,7 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices, state->tty = tty; state->choices = choices; state->options = options; + state->offset = 0; strcpy(state->input, ""); strcpy(state->search, ""); @@ -233,7 +267,13 @@ static const keybinding_t keybindings[] = {{"\x7f", action_del_char}, /* DEL */ {KEY_CTRL('N'), action_next}, /* C-N */ {KEY_CTRL('K'), action_prev}, /* C-J */ {KEY_CTRL('J'), action_next}, /* C-K */ + {KEY_CTRL('A'), action_beginning}, /* C-A */ + {KEY_CTRL('E'), action_end}, /* C-E */ + {"\x1bOD", action_left}, /* LEFT */ + {"\x1b[D", action_left}, /* LEFT */ + {"\x1bOC", action_right}, /* RIGHT */ + {"\x1b[C", action_right}, /* RIGHT */ {"\x1b[A", action_prev}, /* UP */ {"\x1bOA", action_prev}, /* UP */ {"\x1b[B", action_next}, /* DOWN */ diff --git a/src/tty_interface.h b/src/tty_interface.h index 438cc55..34f4e59 100644 --- a/src/tty_interface.h +++ b/src/tty_interface.h @@ -14,6 +14,7 @@ typedef struct { char search[SEARCH_SIZE_MAX + 1]; char last_search[SEARCH_SIZE_MAX + 1]; + int offset; char input[32]; /* Pending input buffer */ -- cgit v1.2.3