diff src/search.c @ 35737:f70b7cac8073 v9.1.0598

patch 9.1.0598: fuzzy completion does not work with default completion Commit: https://github.com/vim/vim/commit/8159fb18a92e9a9f5e35201bd92bf651f4d5835c Author: glepnir <glephunter@gmail.com> Date: Wed Jul 17 20:32:54 2024 +0200 patch 9.1.0598: fuzzy completion does not work with default completion Problem: fuzzy completion does not work with default completion Solution: Make it work (glepnir) closes: #15193 Signed-off-by: glepnir <glephunter@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Wed, 17 Jul 2024 20:45:03 +0200
parents 5c89a485e597
children c92a560e6f52
line wrap: on
line diff
--- a/src/search.c
+++ b/src/search.c
@@ -53,6 +53,7 @@ static int fuzzy_match_str_compare(const
 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
@@ -5140,6 +5141,169 @@ fuzzy_match_str_with_pos(char_u *str UNU
 }
 
 /*
+ * 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;
+
+    do {
+	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;
+	}
+
+	// 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 (fuzzy_match_str(*ptr, pattern) > 0)
+		    {
+			found_new_match = TRUE;
+			*pos = current_pos;
+			*len = 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