summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2018-09-09 21:02:45 -0700
committerJohn Hawthorn <john@hawthorn.email>2018-09-09 21:02:45 -0700
commit97ec6364e25070c73bf3331363a30aa61cfd21c9 (patch)
tree4b8fcb442655f8646145e6890e747ffbdf49fe0e /src
parent22579efc0ad4386e888e08c485f9268619c1934d (diff)
parentbaa0d7ece4eb8401a61a0bebdb5264bf805a34c2 (diff)
Merge branch 'abort_on_escape'
Diffstat (limited to 'src')
-rw-r--r--src/tty.c5
-rw-r--r--src/tty.h2
-rw-r--r--src/tty_interface.c56
-rw-r--r--src/tty_interface.h1
4 files changed, 47 insertions, 17 deletions
diff --git a/src/tty.c b/src/tty.c
index a8f014e..b5b942c 100644
--- a/src/tty.c
+++ b/src/tty.c
@@ -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);
diff --git a/src/tty.h b/src/tty.h
index e7672b6..aca40d9 100644
--- a/src/tty.h
+++ b/src/tty.h
@@ -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;