summaryrefslogtreecommitdiffstats
path: root/src/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c172
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, &current_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