From 812186e2dce3775a1d0e5e96960a818be07e59be Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Nov 2025 12:46:37 +0800 Subject: [PATCH 1/2] vim-patch:9.1.1930: completion: 'completefuzzycollect' is too obscure Problem: completion: 'completefuzzycollect' option is too obscure Solution: Deprecate the option, but don't error out for existing scripts, behave like 'completefuzzycollect' is set when fuzzy completion is enabled (Girish Palya). fixes: vim/vim#18498 closes: vim/vim#18788 https://github.com/vim/vim/commit/33fbfe003c17ad25bf3903aaa89a55fe372086ba Remove this option completely, as it's introduced in Nvim v0.12 cycle. Co-authored-by: Girish Palya --- runtime/doc/news.txt | 4 +- runtime/doc/options.txt | 22 ----- runtime/lua/vim/_meta/options.lua | 25 ----- runtime/scripts/optwin.lua | 1 - src/nvim/insexpand.c | 129 ++++++++++--------------- src/nvim/option_vars.h | 2 - src/nvim/options.lua | 34 ------- src/nvim/optionstr.c | 1 - test/functional/ui/popupmenu_spec.lua | 5 +- test/old/testdir/gen_opt_test.vim | 6 +- test/old/testdir/test_ins_complete.vim | 38 +++++--- test/old/testdir/test_options.vim | 2 +- test/old/testdir/test_popup.vim | 3 +- 13 files changed, 84 insertions(+), 188 deletions(-) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 176f5ca3b2..b9e01e65b9 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -33,7 +33,7 @@ LSP OPTIONS -• todo +• `'completefuzzycollect'` has been removed. TREESITTER @@ -297,8 +297,6 @@ OPTIONS • 'autocomplete' enables |ins-autocompletion|. • 'autowriteall' writes all buffers upon receiving `SIGHUP`, `SIGQUIT` or `SIGTSTP`. • 'chistory' and 'lhistory' set size of the |quickfix-stack|. -• 'completefuzzycollect' enables fuzzy collection of candidates for (some) - |ins-completion| modes. • 'complete' new flags: • "F{func}" complete using given function • "F" complete using 'completefunc' diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 5a4f489519..e71bb94189 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1591,28 +1591,6 @@ A jump table for the options with a short description can be found at |Q_op|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. - *'completefuzzycollect'* *'cfc'* -'completefuzzycollect' 'cfc' string (default "") - global - A comma-separated list of strings to enable fuzzy collection for - specific |ins-completion| modes, affecting how matches are gathered - during completion. For specified modes, fuzzy matching is used to - find completion candidates instead of the standard prefix-based - matching. This option can contain the following values: - - keyword keywords in the current file |i_CTRL-X_CTRL-N| - keywords with flags ".", "w", |i_CTRL-N| |i_CTRL-P| - "b", "u", "U" and "k{dict}" in 'complete' - keywords in 'dictionary' |i_CTRL-X_CTRL-K| - - files file names |i_CTRL-X_CTRL-F| - - whole_line whole lines |i_CTRL-X_CTRL-L| - - When using the 'completeopt' "longest" option value, fuzzy collection - can identify the longest common string among the best fuzzy matches - and insert it automatically. - *'completeitemalign'* *'cia'* 'completeitemalign' 'cia' string (default "abbr,kind,menu") global diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index d69ad6b095..98a0081458 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1133,31 +1133,6 @@ vim.o.cfu = vim.o.completefunc vim.bo.completefunc = vim.o.completefunc vim.bo.cfu = vim.bo.completefunc ---- A comma-separated list of strings to enable fuzzy collection for ---- specific `ins-completion` modes, affecting how matches are gathered ---- during completion. For specified modes, fuzzy matching is used to ---- find completion candidates instead of the standard prefix-based ---- matching. This option can contain the following values: ---- ---- keyword keywords in the current file `i_CTRL-X_CTRL-N` ---- keywords with flags ".", "w", `i_CTRL-N` `i_CTRL-P` ---- "b", "u", "U" and "k{dict}" in 'complete' ---- keywords in 'dictionary' `i_CTRL-X_CTRL-K` ---- ---- files file names `i_CTRL-X_CTRL-F` ---- ---- whole_line whole lines `i_CTRL-X_CTRL-L` ---- ---- When using the 'completeopt' "longest" option value, fuzzy collection ---- can identify the longest common string among the best fuzzy matches ---- and insert it automatically. ---- ---- @type string -vim.o.completefuzzycollect = "" -vim.o.cfc = vim.o.completefuzzycollect -vim.go.completefuzzycollect = vim.o.completefuzzycollect -vim.go.cfc = vim.go.completefuzzycollect - --- A comma-separated list of strings that controls the alignment and --- display order of items in the popup menu during Insert mode --- completion. The supported values are "abbr", "kind", and "menu". diff --git a/runtime/scripts/optwin.lua b/runtime/scripts/optwin.lua index 28bdc343cc..631c5cedfa 100644 --- a/runtime/scripts/optwin.lua +++ b/runtime/scripts/optwin.lua @@ -242,7 +242,6 @@ local options_list = { { 'autocompletedelay', N_ 'delay in msec before menu appears after typing' }, { 'completeopt', N_ 'whether to use a popup menu for Insert mode completion' }, { 'completeitemalign', N_ 'popup menu item align order' }, - { 'completefuzzycollect', N_ 'use fuzzy collection for specific completion modes' }, { 'pumheight', N_ 'maximum height of the popup menu' }, { 'pumwidth', N_ 'minimum width of the popup menu' }, { 'pummaxwidth', N_ 'maximum width of the popup menu' }, diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 945325338f..88283a313b 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -225,11 +225,8 @@ static compl_T *compl_shown_match = NULL; static compl_T *compl_old_match = NULL; /// list used to store the compl_T which have the max score -/// used for completefuzzycollect static compl_T **compl_best_matches = NULL; static int compl_num_bests = 0; -/// inserted a longest when completefuzzycollect enabled -static bool compl_cfc_longest_ins = false; /// After using a cursor key selects a match in the popup menu, /// otherwise it inserts a line break. @@ -858,20 +855,6 @@ int ins_compl_add_infercase(char *str_arg, int len, bool icase, char *fname, Dir return res; } -/// Check if ctrl_x_mode has been configured in 'completefuzzycollect' -static bool cfc_has_mode(void) -{ - if (ctrl_x_mode_normal() || ctrl_x_mode_dictionary()) { - return (cfc_flags & kOptCfcFlagKeyword) != 0; - } else if (ctrl_x_mode_files()) { - return (cfc_flags & kOptCfcFlagFiles) != 0; - } else if (ctrl_x_mode_whole_line()) { - return (cfc_flags & kOptCfcFlagWholeLine) != 0; - } else { - return false; - } -} - /// free cptext static inline void free_cptext(char *const *const cptext) { @@ -882,12 +865,17 @@ static inline void free_cptext(char *const *const cptext) } } +/// Check if fuzzy matching is enabled +static bool cot_fuzzy(void) +{ + return (get_cot_flags() & kOptCotFlagFuzzy) != 0; +} + /// Returns true if matches should be sorted based on proximity to the cursor. static bool is_nearest_active(void) { - unsigned flags = get_cot_flags(); - return (compl_autocomplete || (flags & kOptCotFlagNearest)) - && !(flags & kOptCotFlagFuzzy); + return (compl_autocomplete || (get_cot_flags() & kOptCotFlagNearest)) + && !cot_fuzzy(); } /// True if a match is selected (even if it is not inserted). @@ -1024,13 +1012,12 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons // current match in the list of matches . if (compl_first_match == NULL) { match->cp_next = match->cp_prev = NULL; - } else if (cfc_has_mode() && score != FUZZY_SCORE_NONE && compl_get_longest) { + } else if (cot_fuzzy() && score != FUZZY_SCORE_NONE && compl_get_longest) { compl_T *current = compl_first_match->cp_next; compl_T *prev = compl_first_match; inserted = false; - // The direction is ignored when using longest and - // completefuzzycollect, because matches are inserted - // and sorted by score. + // The direction is ignored when using longest and fuzzy match, because + // matches are inserted and sorted by score. while (current != NULL && current != compl_first_match) { if (current->cp_score < score) { match->cp_next = current; @@ -1069,7 +1056,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons compl_curr_match = match; // Find the longest common string if still doing that. - if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0 && !cfc_has_mode() + if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0 && !cot_fuzzy() && !ins_compl_preinsert_longest()) { ins_compl_longest_match(match); } @@ -1127,7 +1114,7 @@ int ins_compl_col_range_attr(linenr_T lnum, int col) const bool has_preinsert = ins_compl_has_preinsert() || ins_compl_preinsert_longest(); int attr; - if ((get_cot_flags() & kOptCotFlagFuzzy) + if (cot_fuzzy() || (!compl_hi_on_autocompl_longest && ins_compl_preinsert_longest()) || (attr = syn_name2attr(has_preinsert ? "PreInsert" : "ComplMatchIns")) == 0) { return -1; @@ -1538,10 +1525,8 @@ static int ins_compl_build_pum(void) XFREE_CLEAR(compl_leader); } - unsigned cur_cot_flags = get_cot_flags(); - bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0 + bool compl_no_select = (get_cot_flags() & kOptCotFlagNoselect) != 0 || (compl_autocomplete && !ins_compl_has_preinsert()); - bool fuzzy_filter = (cur_cot_flags & kOptCotFlagFuzzy) != 0; compl_T *match_head = NULL, *match_tail = NULL; int *match_count = NULL; @@ -1576,14 +1561,14 @@ static int ins_compl_build_pum(void) // Apply 'smartcase' behavior during normal mode if (ctrl_x_mode_normal() && !p_inf && leader->data - && !ignorecase(leader->data) && !fuzzy_filter) { + && !ignorecase(leader->data) && !cot_fuzzy()) { comp->cp_flags &= ~CP_ICASE; } if (!match_at_original_text(comp) && (leader->data == NULL || ins_compl_equal(comp, leader->data, leader->size) - || (fuzzy_filter && comp->cp_score != FUZZY_SCORE_NONE))) { + || (cot_fuzzy() && comp->cp_score != FUZZY_SCORE_NONE))) { // Limit number of items from each source if max_items is set. bool match_limit_exceeded = false; int cur_source = comp->cp_cpt_source_idx; @@ -1605,7 +1590,7 @@ static int ins_compl_build_pum(void) } match_tail = comp; - if (!shown_match_ok && !fuzzy_filter) { + if (!shown_match_ok && !cot_fuzzy()) { if (comp == compl_shown_match || did_find_shown_match) { // This item is the shown match or this is the // first displayed item after the shown match. @@ -1618,7 +1603,7 @@ static int ins_compl_build_pum(void) shown_compl = comp; } cur = i; - } else if (fuzzy_filter) { + } else if (cot_fuzzy()) { if (i == 0) { shown_compl = comp; } @@ -1632,7 +1617,7 @@ static int ins_compl_build_pum(void) } } - if (comp == compl_shown_match && !fuzzy_filter) { + if (comp == compl_shown_match && !cot_fuzzy()) { did_find_shown_match = true; // When the original text is the shown match don't set // compl_shown_match. @@ -1655,7 +1640,7 @@ static int ins_compl_build_pum(void) return -1; } - if (fuzzy_filter && !compl_no_select && !shown_match_ok) { + if (cot_fuzzy() && !compl_no_select && !shown_match_ok) { compl_shown_match = shown_compl; shown_match_ok = true; cur = 0; @@ -1858,8 +1843,7 @@ static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, bool } spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0); } else if (count > 0) { // avoid warning for using "files" uninit - ins_compl_files(count, files, thesaurus, flags, - (cfc_has_mode() ? NULL : ®match), buf, &dir); + ins_compl_files(count, files, thesaurus, flags, ®match, buf, &dir); if (flags != DICT_EXACT) { FreeWild(count, files); } @@ -1927,10 +1911,8 @@ static void ins_compl_files(int count, char **files, bool thesaurus, int flags, regmatch_T *regmatch, char *buf, Direction *dir) FUNC_ATTR_NONNULL_ARG(2, 7) { - bool in_fuzzy_collect = cfc_has_mode(); - - char *leader = in_fuzzy_collect ? ins_compl_leader() : NULL; - int leader_len = in_fuzzy_collect ? (int)ins_compl_leader_len() : 0; + char *leader = cot_fuzzy() ? ins_compl_leader() : NULL; + int leader_len = cot_fuzzy() ? (int)ins_compl_leader_len() : 0; for (int i = 0; i < count && !got_int && !ins_compl_interrupted(); i++) { FILE *fp = os_fopen(files[i], "r"); // open dictionary file @@ -1950,7 +1932,28 @@ static void ins_compl_files(int count, char **files, bool thesaurus, int flags, // Check each line for a match. while (!got_int && !ins_compl_interrupted() && !vim_fgets(buf, LSIZE, fp)) { char *ptr = buf; - if (regmatch != NULL) { + if (cot_fuzzy() && leader_len > 0) { + char *line_end = find_line_end(ptr); + while (ptr < line_end) { + int score = 0; + int len = 0; + if (fuzzy_match_str_in_line(&ptr, leader, &len, NULL, &score)) { + char *end_ptr = ctrl_x_mode_line_or_eval() + ? find_line_end(ptr) : find_word_end(ptr); + int add_r = ins_compl_add_infercase(ptr, (int)(end_ptr - ptr), + p_ic, files[i], *dir, false, score); + if (add_r == FAIL) { + break; + } + ptr = end_ptr; // start from next word + if (compl_get_longest && ctrl_x_mode_normal() + && compl_first_match->cp_next + && score == compl_first_match->cp_next->cp_score) { + compl_num_bests++; + } + } + } + } else if (regmatch != NULL) { while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf))) { ptr = regmatch->startp[0]; ptr = ctrl_x_mode_line_or_eval() ? find_line_end(ptr) : find_word_end(ptr); @@ -1975,26 +1978,6 @@ static void ins_compl_files(int count, char **files, bool thesaurus, int flags, break; } } - } else if (in_fuzzy_collect && leader_len > 0) { - char *line_end = find_line_end(ptr); - while (ptr < line_end) { - int score = 0; - int len = 0; - if (fuzzy_match_str_in_line(&ptr, leader, &len, NULL, &score)) { - char *end_ptr = ctrl_x_mode_line_or_eval() ? find_line_end(ptr) : find_word_end(ptr); - int add_r = ins_compl_add_infercase(ptr, (int)(end_ptr - ptr), - p_ic, files[i], *dir, false, score); - if (add_r == FAIL) { - break; - } - ptr = end_ptr; // start from next word - if (compl_get_longest && ctrl_x_mode_normal() - && compl_first_match->cp_next - && score == compl_first_match->cp_next->cp_score) { - compl_num_bests++; - } - } - } } line_breakcheck(); ins_compl_check_keys(50, false); @@ -2085,7 +2068,6 @@ void ins_compl_clear(void) { compl_cont_status = 0; compl_started = false; - compl_cfc_longest_ins = false; compl_matches = 0; compl_selected_item = -1; compl_ins_end_col = 0; @@ -2302,7 +2284,7 @@ static void ins_compl_new_leader(void) if (is_cpt_func_refresh_always()) { cpt_compl_refresh(); } - if (get_cot_flags() & kOptCotFlagFuzzy) { + if (cot_fuzzy()) { ins_compl_fuzzy_sort(); } } else { @@ -4068,7 +4050,6 @@ static void fuzzy_longest_match(void) prefix = xmemdupz(prefix, (size_t)prefix_len); ins_compl_longest_insert(prefix); - compl_cfc_longest_ins = true; xfree(prefix); end: @@ -4084,7 +4065,7 @@ static void get_next_filename_completion(void) int num_matches; char *leader = ins_compl_leader(); size_t leader_len = ins_compl_leader_len(); - bool in_fuzzy_collect = (cfc_has_mode() && leader_len > 0); + bool in_fuzzy_collect = (cot_fuzzy() && leader_len > 0); bool need_collect_bests = in_fuzzy_collect && compl_get_longest; int max_score = 0; Direction dir = compl_direction; @@ -4337,9 +4318,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_ { char *ptr = NULL; int len = 0; - bool in_fuzzy_collect = !compl_status_adding() - && ((cfc_has_mode() && compl_length > 0) - || ((get_cot_flags() & kOptCotFlagFuzzy) && compl_autocomplete)); + bool in_fuzzy_collect = !compl_status_adding() && cot_fuzzy() && compl_length > 0; char *leader = ins_compl_leader(); int score = FUZZY_SCORE_NONE; const bool in_curbuf = st->ins_buf == curbuf; @@ -4819,7 +4798,7 @@ static int ins_compl_get_exp(pos_T *ini) if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval()) && (!compl_started || st.found_all)) { int status = process_next_cpt_value(&st, &type, &start_pos, - cfc_has_mode(), &may_advance_cpt_idx); + cot_fuzzy(), &may_advance_cpt_idx); if (status == INS_COMPL_CPT_END) { break; } @@ -4919,7 +4898,7 @@ static int ins_compl_get_exp(pos_T *ini) match_count = ins_compl_make_cyclic(); } - if (cfc_has_mode() && compl_get_longest && compl_num_bests > 0) { + if (cot_fuzzy() && compl_get_longest && compl_num_bests > 0) { fuzzy_longest_match(); } @@ -4941,7 +4920,7 @@ static int ins_compl_get_exp(pos_T *ini) sort_compl_match_list(cp_compare_nearest); } - if ((get_cot_flags() & kOptCotFlagFuzzy) && ins_compl_leader_len() > 0) { + if (cot_fuzzy() && ins_compl_leader_len() > 0) { ins_compl_fuzzy_sort(); } } @@ -5305,7 +5284,6 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a unsigned cur_cot_flags = get_cot_flags(); bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0 || (compl_autocomplete && !ins_compl_has_preinsert()); - bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0; while (--todo >= 0) { if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) { @@ -5371,7 +5349,7 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a if (!match_at_original_text(compl_shown_match) && leader->data != NULL && !ins_compl_equal(compl_shown_match, leader->data, leader->size) - && !(compl_fuzzy_match && compl_shown_match->cp_score != FUZZY_SCORE_NONE)) { + && !(cot_fuzzy() && compl_shown_match->cp_score != FUZZY_SCORE_NONE)) { todo++; } else { // Remember a matching item. @@ -5417,7 +5395,6 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match unsigned cur_cot_flags = get_cot_flags(); bool compl_no_insert = (cur_cot_flags & kOptCotFlagNoinsert) != 0 || (compl_autocomplete && !ins_compl_has_preinsert()); - bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0; bool compl_preinsert = ins_compl_has_preinsert(); bool has_autocomplete_delay = (compl_autocomplete && p_acl > 0); @@ -5429,7 +5406,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match if (compl_leader.data != NULL && !match_at_original_text(compl_shown_match) - && !compl_fuzzy_match) { + && !cot_fuzzy()) { // Update "compl_shown_match" to the actually shown match ins_compl_update_shown_match(); } diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h index 4a210dc14c..947350e9d2 100644 --- a/src/nvim/option_vars.h +++ b/src/nvim/option_vars.h @@ -296,8 +296,6 @@ EXTERN char *p_cpt; ///< 'complete' EXTERN OptInt p_cto; ///< 'completetimeout' EXTERN OptInt p_columns; ///< 'columns' EXTERN int p_confirm; ///< 'confirm' -EXTERN char *p_cfc; ///< 'completefuzzycollect' -EXTERN unsigned cfc_flags; ///< flags from 'completefuzzycollect' EXTERN char *p_cia; ///< 'completeitemalign' EXTERN unsigned cia_flags; ///< order flags of 'completeitemalign' EXTERN char *p_cot; ///< 'completeopt' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index b1116d860f..4bda7b3b15 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1576,40 +1576,6 @@ local options = { type = 'string', varname = 'p_cfu', }, - { - abbreviation = 'cfc', - defaults = '', - values = { 'keyword', 'files', 'whole_line' }, - flags = true, - deny_duplicates = true, - desc = [=[ - A comma-separated list of strings to enable fuzzy collection for - specific |ins-completion| modes, affecting how matches are gathered - during completion. For specified modes, fuzzy matching is used to - find completion candidates instead of the standard prefix-based - matching. This option can contain the following values: - - keyword keywords in the current file |i_CTRL-X_CTRL-N| - keywords with flags ".", "w", |i_CTRL-N| |i_CTRL-P| - "b", "u", "U" and "k{dict}" in 'complete' - keywords in 'dictionary' |i_CTRL-X_CTRL-K| - - files file names |i_CTRL-X_CTRL-F| - - whole_line whole lines |i_CTRL-X_CTRL-L| - - When using the 'completeopt' "longest" option value, fuzzy collection - can identify the longest common string among the best fuzzy matches - and insert it automatically. - ]=], - full_name = 'completefuzzycollect', - list = 'onecomma', - scope = { 'global' }, - short_desc = N_('use fuzzy collection for specific completion modes'), - type = 'string', - varname = 'p_cfc', - flags_varname = 'cfc_flags', - }, { abbreviation = 'cia', cb = 'did_set_completeitemalign', diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 8aee71cece..2301cc3fc0 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -90,7 +90,6 @@ void didset_string_options(void) check_str_opt(kOptCasemap, NULL); check_str_opt(kOptBackupcopy, NULL); check_str_opt(kOptBelloff, NULL); - check_str_opt(kOptCompletefuzzycollect, NULL); check_str_opt(kOptIsexpand, NULL); check_str_opt(kOptCompleteopt, NULL); check_str_opt(kOptSessionoptions, NULL); diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 0fb0c70e71..6d835db5ad 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -7963,11 +7963,10 @@ describe('builtin popupmenu', function() end) -- oldtest: Test_pum_completefuzzycollect() - it('completefuzzycollect', function() + it('fuzzy completion', function() exec([[ set pumwidth=13 - set completefuzzycollect=keyword,files - set completeopt=menu,menuone + set completeopt=menu,menuone,fuzzy ]]) feed('S hello helio hero h') diff --git a/test/old/testdir/gen_opt_test.vim b/test/old/testdir/gen_opt_test.vim index 54edf6e5b1..bcfd6c09df 100644 --- a/test/old/testdir/gen_opt_test.vim +++ b/test/old/testdir/gen_opt_test.vim @@ -188,9 +188,9 @@ let test_values = { \ 's', 's/tmp/dir\\\ with\\\ space/*', \ 'w,b,k/tmp/dir\\\ with\\\ space/*,s'], \ ['xxx']], - \ 'completefuzzycollect': [['', 'keyword', 'files', 'whole_line', - \ 'keyword,whole_line', 'files,whole_line', 'keyword,files,whole_line'], - \ ['xxx', 'keyword,,,whole_line,']], + "\ 'completefuzzycollect': [['', 'keyword', 'files', 'whole_line', + "\ " 'keyword,whole_line', 'files,whole_line', 'keyword,files,whole_line'], + "\ " ['xxx', 'keyword,,,whole_line,']], \ 'completeitemalign': [['abbr,kind,menu', 'menu,abbr,kind'], \ ['', 'xxx', 'abbr', 'abbr,menu', 'abbr,menu,kind,abbr', \ 'abbr1234,kind,menu']], diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 2cf1469fc5..b1a9312878 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -386,8 +386,8 @@ func Test_CompleteDone_vevent_keys() call assert_equal('foo_test', g:complete_word) call assert_equal('files', g:complete_type) - call writefile(['hello help'], 'test_case.txt', 'D') - set dictionary=test_case.txt + call writefile(['hello help'], 'Xtest_case.txt', 'D') + set dictionary=Xtest_case.txt call feedkeys("ggdGSh\\\\", 'tx') call assert_equal('hello', g:complete_word) call assert_equal('dictionary', g:complete_type) @@ -3660,6 +3660,7 @@ func Test_complete_opt_fuzzy() call feedkeys("i\=CompAnother()\\\", 'tx') call assert_equal("for", g:abbr) + %d set cot=menu,fuzzy call feedkeys("Sblue\bar\b\\\\", 'tx') call assert_equal('blue', getline('.')) @@ -3692,7 +3693,7 @@ func Test_complete_opt_fuzzy() " Issue 18488: sort after collection when "fuzzy" (unless "nosort") %d set completeopt& - set completeopt+=fuzzy,noselect completefuzzycollect=keyword + set completeopt+=fuzzy,noselect func! PrintMenuWords() let info = complete_info(["items"]) call map(info.items, {_, v -> v.word}) @@ -3705,7 +3706,7 @@ func Test_complete_opt_fuzzy() " clean up set omnifunc= bw! - set complete& completeopt& completefuzzycollect& + set complete& completeopt& autocmd! AAAAA_Group augroup! AAAAA_Group delfunc OnPumChange @@ -3720,7 +3721,7 @@ endfunc func Test_complete_fuzzy_collect() new redraw " need this to prevent NULL dereference in Nvim - set completefuzzycollect=keyword,files,whole_line + set completeopt+=fuzzy call setline(1, ['hello help hero h']) " Use "!" flag of feedkeys() so that ex_normal_busy is not set and " ins_compl_check_keys() is not skipped. @@ -3798,7 +3799,7 @@ func Test_complete_fuzzy_collect() call assert_equal('no one can save me but you', getline('.')) " issue #15526 - set completeopt=menuone,menu,noselect + set completeopt=menuone,menu,noselect,fuzzy call setline(1, ['Text', 'ToText', '']) call cursor(3, 1) call feedkeys("STe\\x\\0", 'tx!') @@ -3811,8 +3812,8 @@ func Test_complete_fuzzy_collect() call assert_equal('completefuzzycollect', getline(line('.') - 1)) " keywords in 'dictonary' - call writefile(['hello', 'think'], 'test_dict.txt', 'D') - set dict=test_dict.txt + call writefile(['hello', 'think'], 'Xtest_dict.txt', 'D') + set dict=Xtest_dict.txt call feedkeys("Sh\\\\\0", 'tx!') call assert_equal('hello', getline(line('.') - 1)) call feedkeys("Sh\\\\\\0", 'tx!') @@ -3827,16 +3828,26 @@ func Test_complete_fuzzy_collect() call feedkeys("Gofuzzy\\\\\\0", 'tx!') call assert_equal('fuzzycollect', getline('.')) + " when 'fuzzy' is not set, and 'infercase' and 'ignorecase' are set, then + " uppercase completes from lowercase words in dictonary + set completeopt& + set infercase ignorecase + call writefile(['hello'], 'Xtest_case.txt', 'D') + set dictionary=Xtest_case.txt + call feedkeys("ggdGSH\\\\", 'tx') + call assert_equal('Hello', getline('.')) + call feedkeys("ggdGSHE\\\\", 'tx') + call assert_equal('HELLO', getline('.')) + bw! bw! set dict& - set completeopt& cfc& cpt& + set completeopt& cpt& ignorecase& infercase& endfunc " Issue #18752 func Test_complete_fuzzy_collect_multiwin() new - set completefuzzycollect=keyword,files,whole_line set completeopt=fuzzy vnew @@ -3846,12 +3857,11 @@ func Test_complete_fuzzy_collect_multiwin() call assert_equal('Omnipotent', getline('.')) bw! - set completeopt& cfc& + set completeopt& endfunc func Test_cfc_with_longest() new - set completefuzzycollect=keyword,files,whole_line set completeopt=menu,menuone,longest,fuzzy " keyword @@ -3935,7 +3945,6 @@ func Test_cfc_with_longest() bw! set completeopt& - set completefuzzycollect& endfunc func Test_completefuzzycollect_with_completeslash() @@ -3945,7 +3954,7 @@ func Test_completefuzzycollect_with_completeslash() let orig_shellslash = &shellslash set cpt& new - set completefuzzycollect=files + set completeopt+=fuzzy set noshellslash " Test with completeslash unset @@ -3967,7 +3976,6 @@ func Test_completefuzzycollect_with_completeslash() " Reset and clean up let &shellslash = orig_shellslash set completeslash= - set completefuzzycollect& %bw! endfunc diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim index 77e3d6b5e4..453d684995 100644 --- a/test/old/testdir/test_options.vim +++ b/test/old/testdir/test_options.vim @@ -543,7 +543,7 @@ func Test_set_completion_string_values() endif call assert_equal('.', getcompletion('set complete=', 'cmdline')[1]) call assert_equal('menu', getcompletion('set completeopt=', 'cmdline')[1]) - call assert_equal('keyword', getcompletion('set completefuzzycollect=', 'cmdline')[0]) + " call assert_equal('keyword', getcompletion('set completefuzzycollect=', 'cmdline')[0]) if exists('+completeslash') call assert_equal('backslash', getcompletion('set completeslash=', 'cmdline')[1]) endif diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim index 61d70ceb97..07e3d8540b 100644 --- a/test/old/testdir/test_popup.vim +++ b/test/old/testdir/test_popup.vim @@ -1524,8 +1524,7 @@ endfunc func Test_pum_completefuzzycollect() CheckScreendump let lines =<< trim END - set completefuzzycollect=keyword,files - set completeopt=menu,menuone + set completeopt=menu,menuone,fuzzy END call writefile(lines, 'Xscript', 'D') let buf = RunVimInTerminal('-S Xscript', {}) From 0b888ea039546d5ddbf0b87305f0ea36d4d06997 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Nov 2025 07:44:03 +0800 Subject: [PATCH 2/2] vim-patch:b217ffb: runtime(doc): remove outdated help about 'completeopt' "fuzzy" closes: vim/vim#18815 https://github.com/vim/vim/commit/b217ffbef27c416d6c9b4b7e5a08f61f54013748 --- runtime/doc/options.txt | 7 +------ runtime/lua/vim/_meta/options.lua | 7 +------ src/nvim/options.lua | 7 +------ 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e71bb94189..9a2e06ae07 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1610,12 +1610,7 @@ A jump table for the options with a short description can be found at |Q_op|. fuzzy Enable |fuzzy-matching| for completion candidates. This allows for more flexible and intuitive matching, where characters can be skipped and matches can be found even - if the exact sequence is not typed. Note: This option - does not affect the collection of candidate list, it only - controls how completion candidates are reduced from the - list of alternatives. If you want to use |fuzzy-matching| - to gather more alternatives for your candidate list, - see 'completefuzzycollect'. + if the exact sequence is not typed. longest When 'autocomplete' is not active, only the longest common diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 98a0081458..130e296b6c 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1152,12 +1152,7 @@ vim.go.cia = vim.go.completeitemalign --- fuzzy Enable `fuzzy-matching` for completion candidates. This --- allows for more flexible and intuitive matching, where --- characters can be skipped and matches can be found even ---- if the exact sequence is not typed. Note: This option ---- does not affect the collection of candidate list, it only ---- controls how completion candidates are reduced from the ---- list of alternatives. If you want to use `fuzzy-matching` ---- to gather more alternatives for your candidate list, ---- see 'completefuzzycollect'. +--- if the exact sequence is not typed. --- --- longest --- When 'autocomplete' is not active, only the longest common diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 4bda7b3b15..ec1d5579c6 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1623,12 +1623,7 @@ local options = { fuzzy Enable |fuzzy-matching| for completion candidates. This allows for more flexible and intuitive matching, where characters can be skipped and matches can be found even - if the exact sequence is not typed. Note: This option - does not affect the collection of candidate list, it only - controls how completion candidates are reduced from the - list of alternatives. If you want to use |fuzzy-matching| - to gather more alternatives for your candidate list, - see 'completefuzzycollect'. + if the exact sequence is not typed. longest When 'autocomplete' is not active, only the longest common