diff options
author | John Hawthorn <john@hawthorn.email> | 2018-09-09 21:02:45 -0700 |
---|---|---|
committer | John Hawthorn <john@hawthorn.email> | 2018-09-09 21:02:45 -0700 |
commit | 97ec6364e25070c73bf3331363a30aa61cfd21c9 (patch) | |
tree | 4b8fcb442655f8646145e6890e747ffbdf49fe0e /src | |
parent | 22579efc0ad4386e888e08c485f9268619c1934d (diff) | |
parent | baa0d7ece4eb8401a61a0bebdb5264bf805a34c2 (diff) |
Merge branch 'abort_on_escape'
Diffstat (limited to 'src')
-rw-r--r-- | src/tty.c | 5 | ||||
-rw-r--r-- | src/tty.h | 2 | ||||
-rw-r--r-- | src/tty_interface.c | 56 | ||||
-rw-r--r-- | src/tty_interface.h | 1 |
4 files changed, 47 insertions, 17 deletions
@@ -87,9 +87,10 @@ char tty_getchar(tty_t *tty) { } } -int tty_input_ready(tty_t *tty) { +int tty_input_ready(tty_t *tty, int pending) { fd_set readfs; - struct timeval tv = {0, 0}; + struct timeval tv = {0, pending ? 500000 : 0}; + FD_ZERO(&readfs); FD_SET(tty->fdin, &readfs); select(tty->fdin + 1, &readfs, NULL, NULL, &tv); return FD_ISSET(tty->fdin, &readfs); @@ -17,7 +17,7 @@ void tty_close(tty_t *tty); void tty_init(tty_t *tty, const char *tty_filename); void tty_getwinsz(tty_t *tty); char tty_getchar(tty_t *tty); -int tty_input_ready(tty_t *tty); +int tty_input_ready(tty_t *tty, int pending); void tty_setfg(tty_t *tty, int fg); void tty_setinvert(tty_t *tty); diff --git a/src/tty_interface.c b/src/tty_interface.c index 9b9ba40..f6aeef0 100644 --- a/src/tty_interface.c +++ b/src/tty_interface.c @@ -257,6 +257,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->ambiguous_key_pending = 0; strcpy(state->input, ""); strcpy(state->search, ""); @@ -279,7 +280,9 @@ typedef struct { #define KEY_CTRL(key) ((const char[]){((key) - ('@')), '\0'}) -static const keybinding_t keybindings[] = {{"\x7f", action_del_char}, /* DEL */ +static const keybinding_t keybindings[] = {{"\x1b", action_exit}, /* ESC */ + {"\x7f", action_del_char}, /* DEL */ + {KEY_CTRL('H'), action_del_char}, /* Backspace (C-H) */ {KEY_CTRL('W'), action_del_word}, /* C-W */ {KEY_CTRL('U'), action_del_all}, /* C-U */ @@ -314,23 +317,40 @@ static const keybinding_t keybindings[] = {{"\x7f", action_del_char}, /* DEL */ #undef KEY_CTRL -static void handle_input(tty_interface_t *state, const char *s) { +static void handle_input(tty_interface_t *state, const char *s, int handle_ambiguous_key) { + state->ambiguous_key_pending = 0; + char *input = state->input; strcat(state->input, s); - /* See if we have matched a keybinding */ + /* Figure out if we have completed a keybinding and whether we're in the + * middle of one (both can happen, because of Esc). */ + int found_keybinding = -1; + int in_middle = 0; for (int i = 0; keybindings[i].key; i++) { - if (!strcmp(input, keybindings[i].key)) { - keybindings[i].action(state); - strcpy(input, ""); - return; - } + if (!strcmp(input, keybindings[i].key)) + found_keybinding = i; + else if (!strncmp(input, keybindings[i].key, strlen(state->input))) + in_middle = 1; } - /* Check if we are in the middle of a keybinding */ - for (int i = 0; keybindings[i].key; i++) - if (!strncmp(input, keybindings[i].key, strlen(input))) - return; + /* If we have an unambiguous keybinding, run it. */ + if (found_keybinding != -1 && (!in_middle || handle_ambiguous_key)) { + keybindings[found_keybinding].action(state); + strcpy(input, ""); + return; + } + + /* We could have a complete keybinding, or could be in the middle of one. + * We'll need to wait a few milliseconds to find out. */ + if (found_keybinding != -1 && in_middle) { + state->ambiguous_key_pending = 1; + return; + } + + /* Wait for more if we are in the middle of a keybinding */ + if (in_middle) + return; /* No matching keybinding, add to search */ for (int i = 0; input[i]; i++) @@ -347,13 +367,21 @@ int tty_interface_run(tty_interface_t *state) { for (;;) { do { char s[2] = {tty_getchar(state->tty), '\0'}; - handle_input(state, s); + handle_input(state, s, 0); if (state->exit >= 0) return state->exit; draw(state); - } while (tty_input_ready(state->tty)); + } while (tty_input_ready(state->tty, state->ambiguous_key_pending)); + + if (state->ambiguous_key_pending) { + char s[1] = ""; + handle_input(state, s, 1); + + if (state->exit >= 0) + return state->exit; + } update_state(state); } diff --git a/src/tty_interface.h b/src/tty_interface.h index 9572c3f..64af0b4 100644 --- a/src/tty_interface.h +++ b/src/tty_interface.h @@ -16,6 +16,7 @@ typedef struct { char last_search[SEARCH_SIZE_MAX + 1]; size_t cursor; + int ambiguous_key_pending; char input[32]; /* Pending input buffer */ int exit; |