From ba42a498881de2344bb04727215597c40cb21ba2 Mon Sep 17 00:00:00 2001 From: josuah Date: Thu, 24 Nov 2016 21:00:06 +0100 Subject: [PATCH] Trying a new match function --- TODO | 5 ++--- buffer.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ input.c | 6 +++--- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/TODO b/TODO index 90bf452..58b48a6 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,3 @@ -- While the input fully match a candidate, make this candidate the - selected one. - - Treat space as 'wildchars': every word is a query to run independently and the matching words are those matching all the queries. @@ -22,6 +19,8 @@ - Async line input, with fork(): I finally understood how it basically works! + - Merge file, buffer and command list + - Option to output header title rather than the line itself, with lines counted relatively from the beginning of the header. This way, it can acts as a swiper-all: grep through multiple files, and diff --git a/buffer.c b/buffer.c index 567adff..34e6833 100644 --- a/buffer.c +++ b/buffer.c @@ -153,7 +153,12 @@ filter_lines(Buffer *buffer, Opt *opt) buffer->matching = 0; while (line) { - line->matches = line_match_input(line, buffer->input, opt); + if (!strcmp(buffer->input, line->content) && buffer->input[0]) { + buffer->current = line; + line->matches = 1; + } + + line->matches = line_match_input(line, buffer->input, opt); buffer->matching += line->matches; line = line->next; @@ -162,15 +167,58 @@ filter_lines(Buffer *buffer, Opt *opt) /* - * Check if line matches and return TRUE or FALSE + * Check if line matches and return TRUE or FALSE. + * + * This is performance critical. + * + * For each whitespace in input, or at the beginning, each next character is + * being matched in the output. */ int line_match_input(Line *line, char *input, Opt *opt) { - return (opt->complete && !strncmp(input, line->content, strlen(input))) - || (!opt->complete && strstr(line->content, input)) - || line->header - ? TRUE : FALSE; + /* input: position in the input string to match in content */ + int i = 0; + + /* current: current position in content that match first char after a + * whitespace in input */ + int c = 0; + + /* offset: position from the cursor to start matching a string */ + int o = 0; + + /* headers always match */ + if (line->header) + return TRUE; + + /* reaching the end of input means we matched the line */ + while (input[i]) { + /* seek the next potential of match in line */ + while (line->content[c] && input[i] != line->content[c]) + c++; + + /* skip all spaces and seek for next match again */ + if (input[i] == ' ') { + while (input[++i] == ' '); + + } else { + /* check if the word in input does match */ + + /* skip every matching character */ + while (input[i++] == line->content[c + o++]); + + /* check whether either input or content is over */ + if (!input[i]) { + return TRUE; + } else if (!line->content[c + o]) { + return FALSE; + } + + o = 0; + } + } + + return TRUE; } diff --git a/input.c b/input.c index d6e6ab6..e2b3547 100644 --- a/input.c +++ b/input.c @@ -116,7 +116,7 @@ action_jump(Buffer *buffer, int direction) /* * Send the selection to stdout. */ - void +void action_print_selection(Buffer *buffer, Opt *opt) { fputs("\r\033[K", stderr); @@ -138,7 +138,7 @@ action_print_selection(Buffer *buffer, Opt *opt) /* * Remove the last word from the buffer's input */ - void +void action_remove_word_input(Buffer *buffer) { size_t length = strlen(buffer->input) - 1; @@ -156,7 +156,7 @@ action_remove_word_input(Buffer *buffer) /* * Add a character to the buffer input and filter lines again. */ - void +void action_add_character(Buffer *buffer, char key, Opt *opt) { size_t length = strlen(buffer->input); -- 2.11.4.GIT