| ... | ... |
@@ -86,6 +86,14 @@ char tty_getchar(tty_t *tty) {
|
| 86 | 86 |
} |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 |
+int tty_input_ready(tty_t *tty) {
|
|
| 90 |
+ fd_set readfs; |
|
| 91 |
+ struct timeval tv = {0, 0};
|
|
| 92 |
+ FD_SET(tty->fdin, &readfs); |
|
| 93 |
+ select(tty->fdin + 1, &readfs, NULL, NULL, &tv); |
|
| 94 |
+ return FD_ISSET(tty->fdin, &readfs); |
|
| 95 |
+} |
|
| 96 |
+ |
|
| 89 | 97 |
static void tty_sgr(tty_t *tty, int code) {
|
| 90 | 98 |
tty_printf(tty, "%c%c%im", 0x1b, '[', code); |
| 91 | 99 |
} |
| ... | ... |
@@ -17,6 +17,7 @@ void tty_close(tty_t *tty); |
| 17 | 17 |
void tty_init(tty_t *tty, const char *tty_filename); |
| 18 | 18 |
void tty_getwinsz(tty_t *tty); |
| 19 | 19 |
char tty_getchar(tty_t *tty); |
| 20 |
+int tty_input_ready(tty_t *tty); |
|
| 20 | 21 |
|
| 21 | 22 |
void tty_setfg(tty_t *tty, int fg); |
| 22 | 23 |
void tty_setinvert(tty_t *tty); |
| ... | ... |
@@ -23,7 +23,7 @@ static void clear(tty_interface_t *state) {
|
| 23 | 23 |
static void draw_match(tty_interface_t *state, const char *choice, int selected) {
|
| 24 | 24 |
tty_t *tty = state->tty; |
| 25 | 25 |
options_t *options = state->options; |
| 26 |
- char *search = state->search; |
|
| 26 |
+ char *search = state->last_search; |
|
| 27 | 27 |
|
| 28 | 28 |
int n = strlen(search); |
| 29 | 29 |
size_t positions[n + 1]; |
| ... | ... |
@@ -87,7 +87,21 @@ static void draw(tty_interface_t *state) {
|
| 87 | 87 |
tty_flush(tty); |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 |
+static void update_search(tty_interface_t *state) {
|
|
| 91 |
+ choices_search(state->choices, state->search); |
|
| 92 |
+ strcpy(state->last_search, state->search); |
|
| 93 |
+} |
|
| 94 |
+ |
|
| 95 |
+void update_state(tty_interface_t *state) {
|
|
| 96 |
+ if (strcmp(state->last_search, state->search)) {
|
|
| 97 |
+ update_search(state); |
|
| 98 |
+ draw(state); |
|
| 99 |
+ } |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 90 | 102 |
static void action_emit(tty_interface_t *state) {
|
| 103 |
+ update_state(state); |
|
| 104 |
+ |
|
| 91 | 105 |
/* Reset the tty as close as possible to the previous state */ |
| 92 | 106 |
clear(state); |
| 93 | 107 |
|
| ... | ... |
@@ -124,24 +138,29 @@ static void action_del_all(tty_interface_t *state) {
|
| 124 | 138 |
} |
| 125 | 139 |
|
| 126 | 140 |
static void action_prev(tty_interface_t *state) {
|
| 141 |
+ update_state(state); |
|
| 127 | 142 |
choices_prev(state->choices); |
| 128 | 143 |
} |
| 129 | 144 |
|
| 130 | 145 |
static void action_next(tty_interface_t *state) {
|
| 146 |
+ update_state(state); |
|
| 131 | 147 |
choices_next(state->choices); |
| 132 | 148 |
} |
| 133 | 149 |
|
| 134 | 150 |
static void action_pageup(tty_interface_t *state) {
|
| 151 |
+ update_state(state); |
|
| 135 | 152 |
for(size_t i = 0; i < state->options->num_lines && state->choices->selection > 0; i++) |
| 136 | 153 |
choices_prev(state->choices); |
| 137 | 154 |
} |
| 138 | 155 |
|
| 139 | 156 |
static void action_pagedown(tty_interface_t *state) {
|
| 157 |
+ update_state(state); |
|
| 140 | 158 |
for(size_t i = 0; i < state->options->num_lines && state->choices->selection < state->choices->available-1; i++) |
| 141 | 159 |
choices_next(state->choices); |
| 142 | 160 |
} |
| 143 | 161 |
|
| 144 | 162 |
static void action_autocomplete(tty_interface_t *state) {
|
| 163 |
+ update_state(state); |
|
| 145 | 164 |
strncpy(state->search, choices_get(state->choices, state->choices->selection), SEARCH_SIZE_MAX); |
| 146 | 165 |
} |
| 147 | 166 |
|
| ... | ... |
@@ -161,16 +180,6 @@ static void append_search(tty_interface_t *state, char ch) {
|
| 161 | 180 |
} |
| 162 | 181 |
} |
| 163 | 182 |
|
| 164 |
-static void update_search(tty_interface_t *state) {
|
|
| 165 |
- choices_search(state->choices, state->search); |
|
| 166 |
- strcpy(state->last_search, state->search); |
|
| 167 |
-} |
|
| 168 |
- |
|
| 169 |
-void update_state(tty_interface_t *state) {
|
|
| 170 |
- if (strcmp(state->last_search, state->search)) |
|
| 171 |
- update_search(state); |
|
| 172 |
-} |
|
| 173 |
- |
|
| 174 | 183 |
void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices, options_t *options) {
|
| 175 | 184 |
state->tty = tty; |
| 176 | 185 |
state->choices = choices; |
| ... | ... |
@@ -216,8 +225,9 @@ static const keybinding_t keybindings[] = {{"\x7f", action_del_char}, /* DEL */
|
| 216 | 225 |
|
| 217 | 226 |
#undef KEY_CTRL |
| 218 | 227 |
|
| 219 |
-void handle_input(tty_interface_t *state) {
|
|
| 228 |
+void handle_input(tty_interface_t *state, const char *s) {
|
|
| 220 | 229 |
char *input = state->input; |
| 230 |
+ strcat(state->input, s); |
|
| 221 | 231 |
|
| 222 | 232 |
/* See if we have matched a keybinding */ |
| 223 | 233 |
for (int i = 0; keybindings[i].key; i++) {
|
| ... | ... |
@@ -243,13 +253,18 @@ void handle_input(tty_interface_t *state) {
|
| 243 | 253 |
} |
| 244 | 254 |
|
| 245 | 255 |
int tty_interface_run(tty_interface_t *state) {
|
| 246 |
- while (state->exit < 0) {
|
|
| 247 |
- draw(state); |
|
| 256 |
+ draw(state); |
|
| 257 |
+ |
|
| 258 |
+ for (;;) {
|
|
| 259 |
+ do {
|
|
| 260 |
+ char s[2] = {tty_getchar(state->tty), '\0'};
|
|
| 261 |
+ handle_input(state, s); |
|
| 248 | 262 |
|
| 249 |
- char s[2] = {tty_getchar(state->tty), '\0'};
|
|
| 250 |
- strcat(state->input, s); |
|
| 263 |
+ if (state->exit >= 0) |
|
| 264 |
+ return state->exit; |
|
| 251 | 265 |
|
| 252 |
- handle_input(state); |
|
| 266 |
+ draw(state); |
|
| 267 |
+ } while (tty_input_ready(state->tty)); |
|
| 253 | 268 |
|
| 254 | 269 |
update_state(state); |
| 255 | 270 |
} |