diff --git a/src/insexpand.c b/src/insexpand.c index 40ba818668..6f3845e097 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -1560,24 +1560,41 @@ theend: } /* - * Set fuzzy score. + * Set fuzzy score for completion matches. */ static void set_fuzzy_score(void) { compl_T *compl; + char_u *pattern; + int use_leader; - if (!compl_first_match - || compl_leader.string == NULL || compl_leader.length == 0) + if (compl_first_match == NULL) return; - (void)get_leader_for_startcol(NULL, TRUE); // Clear the cache + /* Determine the pattern to match against */ + use_leader = (compl_leader.string != NULL && compl_leader.length > 0); + if (!use_leader) + { + if (compl_orig_text.string == NULL || compl_orig_text.length == 0) + return; + pattern = compl_orig_text.string; + } + else + { + /* Clear the leader cache once before the loop */ + (void)get_leader_for_startcol(NULL, TRUE); + pattern = NULL; /* Will be computed per-completion */ + } + /* Score all completion matches */ compl = compl_first_match; do { - compl->cp_score = fuzzy_match_str(compl->cp_str.string, - get_leader_for_startcol(compl, TRUE)->string); + if (use_leader) + pattern = get_leader_for_startcol(compl, TRUE)->string; + + compl->cp_score = fuzzy_match_str(compl->cp_str.string, pattern); compl = compl->cp_next; } while (compl != NULL && !is_first_match(compl)); } @@ -2471,6 +2488,30 @@ ins_compl_has_autocomplete(void) return curbuf->b_p_ac >= 0 ? curbuf->b_p_ac : p_ac; } +/* + * Cacluate fuzzy score and sort completion matches unless sorting is disabled. + */ + static void +ins_compl_fuzzy_sort(void) +{ + int cur_cot_flags = get_cot_flags(); + + // set the fuzzy score in cp_score + set_fuzzy_score(); + // Sort the matches linked list based on fuzzy score + if (!(cur_cot_flags & COT_NOSORT)) + { + sort_compl_match_list(cp_compare_fuzzy); + if ((cur_cot_flags & (COT_NOINSERT | COT_NOSELECT)) == COT_NOINSERT + && compl_first_match) + { + compl_shown_match = compl_first_match; + if (compl_shows_dir_forward() && !compl_autocomplete) + compl_shown_match = compl_first_match->cp_next; + } + } +} + /* * Called after changing "compl_leader". * Show the popup menu with a different set of matches. @@ -2479,7 +2520,6 @@ ins_compl_has_autocomplete(void) static void ins_compl_new_leader(void) { - int cur_cot_flags = get_cot_flags(); int save_w_wrow = curwin->w_wrow; int save_w_leftcol = curwin->w_leftcol; @@ -2499,6 +2539,8 @@ ins_compl_new_leader(void) ins_compl_set_original_text(compl_leader.string, compl_leader.length); if (is_cpt_func_refresh_always()) cpt_compl_refresh(); + if (get_cot_flags() & COT_FUZZY) + ins_compl_fuzzy_sort(); } else { @@ -2529,24 +2571,6 @@ ins_compl_new_leader(void) compl_restarting = FALSE; } - // When 'cot' contains "fuzzy" set the cp_score and maybe sort - if (cur_cot_flags & COT_FUZZY) - { - set_fuzzy_score(); - // Sort the matches linked list based on fuzzy score - if (!(cur_cot_flags & COT_NOSORT)) - { - sort_compl_match_list(cp_compare_fuzzy); - if ((cur_cot_flags & (COT_NOINSERT | COT_NOSELECT)) == COT_NOINSERT - && compl_first_match) - { - compl_shown_match = compl_first_match; - if (compl_shows_dir_forward() && !compl_autocomplete) - compl_shown_match = compl_first_match->cp_next; - } - } - } - compl_enter_selects = !compl_used_match && compl_selected_item != -1; // Show the popup menu with a different set of matches. @@ -5677,6 +5701,9 @@ ins_compl_get_exp(pos_T *ini) if (is_nearest_active() && !ins_compl_has_preinsert()) sort_compl_match_list(cp_compare_nearest); + if ((get_cot_flags() & COT_FUZZY) && ins_compl_leader_len() > 0) + ins_compl_fuzzy_sort(); + return match_count; } @@ -6436,7 +6463,9 @@ ins_compl_check_keys(int frequency, int in_compl_func) check_elapsed_time(); } - if (compl_pending && !got_int && !(cot_flags & COT_NOINSERT) + if (compl_pending + && !got_int + && !(cot_flags & (COT_NOINSERT | COT_FUZZY)) && (!compl_autocomplete || ins_compl_has_preinsert())) { // Insert the first match immediately and advance compl_shown_match, diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index a340d476e6..23c84b28b1 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -3531,9 +3531,9 @@ func Test_complete_opt_fuzzy() set cot=menu,fuzzy call feedkeys("Sblue\bar\b\\\\", 'tx') - call assert_equal('bar', getline('.')) - call feedkeys("Sb\\\\", 'tx') call assert_equal('blue', getline('.')) + call feedkeys("Sb\\\\", 'tx') + call assert_equal('bar', getline('.')) call feedkeys("Sb\\\\\", 'tx') call assert_equal('b', getline('.')) @@ -3558,15 +3558,29 @@ func Test_complete_opt_fuzzy() call feedkeys("S\\c\", 'tx') call assert_equal('cp_str', getline('.')) + " Issue 18488: sort after collection when "fuzzy" (unless "nosort") + %d + set completeopt& + set completeopt+=fuzzy,noselect completefuzzycollect=keyword + func! PrintMenuWords() + let info = complete_info(["items"]) + call map(info.items, {_, v -> v.word}) + return info + endfunc + call setline(1, ['func1', 'xfunc', 'func2']) + call feedkeys("Gof\\=PrintMenuWords()\\0", 'tx') + call assert_equal('f{''items'': [''func1'', ''func2'', ''xfunc'']}', getline('.')) + " clean up set omnifunc= bw! - set complete& completeopt& + set complete& completeopt& completefuzzycollect& autocmd! AAAAA_Group augroup! AAAAA_Group delfunc OnPumChange delfunc Omni_test delfunc Comp + delfunc PrintMenuWords unlet g:item unlet g:word unlet g:abbr @@ -4734,18 +4748,6 @@ func Test_nearest_cpt_option() call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) exe "normal! 2jof\\=PrintMenuWords()\" call assert_equal('fo{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(4)) - - " No effect if 'fuzzy' is present - set completeopt& - set completeopt+=fuzzy,nearest - %d - call setline(1, ["foo", "fo", "foobarbaz", "foobar"]) - exe "normal! of\\=PrintMenuWords()\" - call assert_equal('fo{''matches'': [''fo'', ''foobarbaz'', ''foobar'', ''foo''], ''selected'': 0}', getline(2)) - %d - call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) - exe "normal! 2jof\\=PrintMenuWords()\" - call assert_equal('foobar{''matches'': [''foobarbaz'', ''fo'', ''foo'', ''foobar''], ''selected'': 3}', getline(4)) bw! set completeopt& diff --git a/src/version.c b/src/version.c index 0b342a2b1c..f7466e4932 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1833, /**/ 1832, /**/