From c0c18efcd3aec716969938a163304b00e3e16b09 Mon Sep 17 00:00:00 2001 From: Anton Lindqvist Date: Sat, 23 Sep 2017 09:08:05 +0200 Subject: [PATCH] Low-hanging optimization If the user didn't add more characters to the query all choices have to be reconsidered as potential matches. In the opposite scenario, there's no point in reconsidered all choices again since the ones that didn't match the previous query will clearly not match the current one due to the fact that previous query is a left-most substring of the current one. --- pick.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pick.c b/pick.c index d6d350d5..626fdcf0 100644 --- a/pick.c +++ b/pick.c @@ -70,7 +70,7 @@ struct choice { static int choicecmp(const void *, const void *); static void delete_between(char *, size_t, size_t, size_t); static char *eager_strpbrk(const char *, const char *); -static void filter_choices(void); +static void filter_choices(size_t); static char *get_choices(void); static enum key get_key(const char **); static void handle_sigwinch(int); @@ -302,14 +302,28 @@ selected_choice(void) size_t selection = 0; size_t yscroll = 0; int dofilter = 1; + int query_grew = 0; cursor_position = query_length; for (;;) { + /* + * If the user didn't add more characters to the query all + * choices have to be reconsidered as potential matches. + * In the opposite scenario, there's no point in reconsidered + * all choices again since the ones that didn't match the + * previous query will clearly not match the current one due to + * the fact that previous query is a left-most substring of the + * current one. + */ + if (!query_grew) + choices_count = choices.length; + query_grew = 0; if (dofilter) { filter_choices(choices_count); dofilter = selection = yscroll = 0; } + tty_putp(cursor_invisible, 0); tty_putp(carriage_return, 1); /* move cursor to first column */ if (cursor_position >= tty_columns) @@ -517,7 +531,7 @@ selected_choice(void) cursor_position += length; query_length += length; query[query_length] = '\0'; - dofilter = 1; + dofilter = query_grew = 1; break; case UNKNOWN: break; @@ -528,16 +542,17 @@ selected_choice(void) /* * Filter choices using the current query while there is no new user input * available. + * The first nchoices number of choices will be filtered. */ void -filter_choices(void) +filter_choices(size_t nchoices) { struct choice *c; struct pollfd pfd; size_t i, match_length; int nready; - for (i = 0; i < choices.length; i++) { + for (i = 0; i < nchoices; i++) { c = &choices.v[i]; if (min_match(c->string, 0, &c->match_start, &c->match_end) == INT_MAX) { @@ -566,7 +581,7 @@ filter_choices(void) } } - qsort(choices.v, choices.length, sizeof(struct choice), choicecmp); + qsort(choices.v, nchoices, sizeof(struct choice), choicecmp); } int