From 0c689fec8e7e1c9eb0bcdf84949160cd7caf3fb6 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sun, 27 Feb 2022 04:36:04 +0000 Subject: [PATCH] vim-patch:8.2.4465: fuzzy completion does not order matches properly Problem: Fuzzy completion does not order matches properly. Solution: Do not use regular expression match. (Yegappan Lakshmanan, closes vim/vim#9843) https://github.com/vim/vim/commit/5ec633b9b0400519db60253cb5846e50394218b4 Nvim's ExpandGeneric() was refactored to eliminate looping for "round", so the patch has been adapted. fuzzy_match_str() change was already applied earlier. In Test_wildoptions_fuzzy(), test for NvimParenthesis over MatchParen for :syntax list, as the fuzzy matching algorithm prefers the former (even in Vim). Co-authored-by: Yegappan Lakshmanan --- src/nvim/cmdexpand.c | 63 +++++++++++++++++++------------ src/nvim/testdir/test_cmdline.vim | 23 ++++++++++- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index f18869bb1c..566a17b82b 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2765,8 +2765,14 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, char ***matches, i if (*str == NUL) { // skip empty strings continue; } - if (vim_regexec(regmatch, str, (colnr_T)0) - || (fuzzy && fuzzy_match_str(str, fuzzystr) != 0)) { + + bool match; + if (!fuzzy) { + match = vim_regexec(regmatch, str, (colnr_T)0); + } else { + match = fuzzy_match_str(str, fuzzystr) != 0; + } + if (match) { count++; } } @@ -2792,28 +2798,37 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, char ***matches, i if (*str == NUL) { // Skip empty strings. continue; } - int score; - if (vim_regexec(regmatch, str, (colnr_T)0) - || (fuzzy && ((score = fuzzy_match_str(str, fuzzystr)) != 0))) { - if (escaped) { - str = vim_strsave_escaped(str, " \t\\."); - } else { - str = xstrdup(str); - } - if (fuzzy) { - fuzmatch[count].idx = (int)count; - fuzmatch[count].str = str; - fuzmatch[count].score = score; - } else { - (*matches)[count] = str; - } - count++; - if (func == get_menu_names) { - // Test for separator added by get_menu_names(). - str += strlen(str) - 1; - if (*str == '\001') { - *str = '.'; - } + + bool match; + int score = 0; + if (!fuzzy) { + match = vim_regexec(regmatch, str, (colnr_T)0); + } else { + score = fuzzy_match_str(str, fuzzystr); + match = (score != 0); + } + if (!match) { + continue; + } + + if (escaped) { + str = vim_strsave_escaped(str, " \t\\."); + } else { + str = xstrdup(str); + } + if (fuzzy) { + fuzmatch[count].idx = (int)count; + fuzmatch[count].str = str; + fuzmatch[count].score = score; + } else { + (*matches)[count] = str; + } + count++; + if (func == get_menu_names) { + // Test for separator added by get_menu_names(). + str += strlen(str) - 1; + if (*str == '\001') { + *str = '.'; } } } diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index e068685164..f5726c093b 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -2941,7 +2941,9 @@ func Test_wildoptions_fuzzy() call assert_equal('"syntax list mpar', @:) set wildoptions=fuzzy call feedkeys(":syntax list mpar\\\"\", 'tx') - call assert_equal('"syntax list MatchParen', @:) + " Fuzzy match favours NvimParenthesis over MatchParen + " call assert_equal('"syntax list MatchParen', @:) + call assert_equal('"syntax list NvimParenthesis', @:) " :syntime suboptions fuzzy completion if has('profile') @@ -2968,6 +2970,25 @@ func Test_wildoptions_fuzzy() call feedkeys(":let SVar\\\"\", 'tx') call assert_equal('"let SomeVariable', @:) + " Test for sorting the results by the best match + %bw! + command T123format : + command T123goformat : + command T123TestFOrmat : + command T123fendoff : + command T123state : + command T123FendingOff : + set wildoptions=fuzzy + call feedkeys(":T123fo\\\"\", 'tx') + call assert_equal('"T123format T123TestFOrmat T123FendingOff T123goformat T123fendoff', @:) + delcommand T123format + delcommand T123goformat + delcommand T123TestFOrmat + delcommand T123fendoff + delcommand T123state + delcommand T123FendingOff + %bw + set wildoptions& %bw! endfunc