From 5ec633b9b0400519db60253cb5846e50394218b4 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Fri, 25 Feb 2022 15:24:24 +0000 Subject: [PATCH] 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 #9843) --- src/cmdexpand.c | 73 ++++++++++++++++++++---------------- src/search.c | 2 +- src/testdir/test_cmdline.vim | 19 ++++++++++ src/version.c | 2 + 4 files changed, 63 insertions(+), 33 deletions(-) diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 909706d1de..94781f82f0 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -2633,6 +2633,7 @@ ExpandGeneric( int score = 0; int fuzzy = (fuzzystr != NULL); int funcsort = FALSE; + int match; // do this loop twice: // round == 0: count the number of matching names @@ -2647,44 +2648,52 @@ ExpandGeneric( if (*str == NUL) // skip empty strings continue; - if (vim_regexec(regmatch, str, (colnr_T)0) || - (fuzzy && ((score = fuzzy_match_str(str, fuzzystr)) != 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 (round) { - if (round) + if (escaped) + str = vim_strsave_escaped(str, (char_u *)" \t\\."); + else + str = vim_strsave(str); + if (str == NULL) { - if (escaped) - str = vim_strsave_escaped(str, (char_u *)" \t\\."); - else - str = vim_strsave(str); - if (str == NULL) - { - FreeWild(count, *matches); - if (fuzzy) - fuzmatch_str_free(fuzmatch, count); - *numMatches = 0; - *matches = NULL; - return FAIL; - } if (fuzzy) - { - fuzmatch[count].idx = count; - fuzmatch[count].str = str; - fuzmatch[count].score = score; - } - else - (*matches)[count] = str; + fuzmatch_str_free(fuzmatch, count); + else if (count > 0) + FreeWild(count, *matches); + *numMatches = 0; + *matches = NULL; + return FAIL; + } + if (fuzzy) + { + fuzmatch[count].idx = count; + fuzmatch[count].str = str; + fuzmatch[count].score = score; + } + else + (*matches)[count] = str; # ifdef FEAT_MENU - if (func == get_menu_names && str != NULL) - { - // test for separator added by get_menu_names() - str += STRLEN(str) - 1; - if (*str == '\001') - *str = '.'; - } -# endif + if (func == get_menu_names && str != NULL) + { + // test for separator added by get_menu_names() + str += STRLEN(str) - 1; + if (*str == '\001') + *str = '.'; } - ++count; +# endif } + ++count; } if (round == 0) { diff --git a/src/search.c b/src/search.c index 00a9fdfc6d..063058d326 100644 --- a/src/search.c +++ b/src/search.c @@ -5001,7 +5001,7 @@ fuzzy_match_func_sort(fuzmatch_str_T *fm, int sz) fuzzy_match_str(char_u *str, char_u *pat) { int score = 0; - int_u matchpos[256]; + int_u matchpos[MAX_FUZZY_MATCHES]; if (str == NULL || pat == NULL) return 0; diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 1ee0d718e2..73d39e39e0 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -2757,6 +2757,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 diff --git a/src/version.c b/src/version.c index 69be8cd054..94479e3ce5 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4465, /**/ 4464, /**/ -- 2.47.2