diff options
Diffstat (limited to 'src/search.c')
-rw-r--r-- | src/search.c | 172 |
1 files changed, 170 insertions, 2 deletions
diff --git a/src/search.c b/src/search.c index 0b39d90..e5936d8 100644 --- a/src/search.c +++ b/src/search.c @@ -53,6 +53,7 @@ static int fuzzy_match_str_compare(const void *s1, const void *s2); static void fuzzy_match_str_sort(fuzmatch_str_T *fm, int sz); static int fuzzy_match_func_compare(const void *s1, const void *s2); static void fuzzy_match_func_sort(fuzmatch_str_T *fm, int sz); +static int fuzzy_match_str_in_line(char_u **ptr, char_u *pat, int *len, pos_T *current_pos); #define SEARCH_STAT_DEF_TIMEOUT 40L #define SEARCH_STAT_DEF_MAX_COUNT 99 @@ -1547,6 +1548,7 @@ do_search( { vim_free(msgbuf); msgbuf = r; + msgbuflen = STRLEN(msgbuf); // move reversed text to beginning of buffer while (*r != NUL && *r == ' ') r++; @@ -5106,11 +5108,11 @@ fuzzy_match_str_with_pos(char_u *str UNUSED, char_u *pat UNUSED) int j = 0; if (str == NULL || pat == NULL) - return NULL; + return NULL; match_positions = ALLOC_ONE(garray_T); if (match_positions == NULL) - return NULL; + return NULL; ga_init2(match_positions, sizeof(int_u), 10); if (!fuzzy_match(str, pat, FALSE, &score, matches, MAX_FUZZY_MATCHES) @@ -5140,6 +5142,172 @@ fuzzy_match_str_with_pos(char_u *str UNUSED, char_u *pat UNUSED) } /* + * This function searches for a fuzzy match of the pattern `pat` within the + * line pointed to by `*ptr`. It splits the line into words, performs fuzzy + * matching on each word, and returns the length and position of the first + * matched word. + */ + static int +fuzzy_match_str_in_line(char_u **ptr, char_u *pat, int *len, pos_T *current_pos) +{ + char_u *str = *ptr; + char_u *strBegin = str; + char_u *end = NULL; + char_u *start = NULL; + int found = FALSE; + int result; + char save_end; + + if (str == NULL || pat == NULL) + return found; + + while (*str != NUL) + { + // Skip non-word characters + start = find_word_start(str); + if (*start == NUL) + break; + end = find_word_end(start); + + // Extract the word from start to end + save_end = *end; + *end = NUL; + + // Perform fuzzy match + result = fuzzy_match_str(start, pat); + *end = save_end; + + if (result > 0) + { + *len = (int)(end - start); + current_pos->col += (int)(end - strBegin); + found = TRUE; + *ptr = start; + break; + } + + // Move to the end of the current word for the next iteration + str = end; + // Ensure we continue searching after the current word + while (*str != NUL && !vim_iswordp(str)) + MB_PTR_ADV(str); + } + + return found; +} + +/* + * Search for the next fuzzy match in the specified buffer. + * This function attempts to find the next occurrence of the given pattern + * in the buffer, starting from the current position. It handles line wrapping + * and direction of search. + * + * Return TRUE if a match is found, otherwise FALSE. + */ + int +search_for_fuzzy_match( + buf_T *buf, + pos_T *pos, + char_u *pattern, + int dir, + pos_T *start_pos, + int *len, + char_u **ptr, + int whole_line) +{ + pos_T current_pos = *pos; + pos_T circly_end; + int found_new_match = FAIL; + int looped_around = FALSE; + + if (whole_line) + current_pos.lnum += dir; + + if (buf == curbuf) + circly_end = *start_pos; + else + { + circly_end.lnum = buf->b_ml.ml_line_count; + circly_end.col = 0; + circly_end.coladd = 0; + } + + do { + + // Check if looped around and back to start position + if (looped_around && EQUAL_POS(current_pos, circly_end)) + break; + + // Ensure current_pos is valid + if (current_pos.lnum >= 1 && current_pos.lnum <= buf->b_ml.ml_line_count) + { + // Get the current line buffer + *ptr = ml_get_buf(buf, current_pos.lnum, FALSE); + // If ptr is end of line is reached, move to next line + // or previous line based on direction + if (**ptr != NUL) + { + if (!whole_line) + { + *ptr += current_pos.col; + // Try to find a fuzzy match in the current line starting from current position + found_new_match = fuzzy_match_str_in_line(ptr, pattern, len, ¤t_pos); + if (found_new_match) + { + *pos = current_pos; + break; + } + else if (looped_around && current_pos.lnum == circly_end.lnum) + break; + } + else + { + if (fuzzy_match_str(*ptr, pattern) > 0) + { + found_new_match = TRUE; + *pos = current_pos; + *len = (int)STRLEN(*ptr); + break; + } + } + } + } + + // Move to the next line or previous line based on direction + if (dir == FORWARD) + { + if (++current_pos.lnum > buf->b_ml.ml_line_count) + { + if (p_ws) + { + current_pos.lnum = 1; + looped_around = TRUE; + } + else + break; + } + } + else + { + if (--current_pos.lnum < 1) + { + if (p_ws) + { + current_pos.lnum = buf->b_ml.ml_line_count; + looped_around = TRUE; + } + else + break; + + } + } + current_pos.col = 0; + } while (TRUE); + + return found_new_match; +} + +/* * Free an array of fuzzy string matches "fuzmatch[count]". */ void |