Merge pull request #36714 from zeertzjq/vim-9.1.1930

vim-patch:9.1.1930: completion: 'completefuzzycollect' is too obscure
This commit is contained in:
zeertzjq
2025-11-28 08:18:29 +08:00
committed by GitHub
13 changed files with 87 additions and 206 deletions

View File

@@ -33,7 +33,7 @@ LSP
OPTIONS OPTIONS
todo `'completefuzzycollect'` has been removed.
TREESITTER TREESITTER
@@ -297,8 +297,6 @@ OPTIONS
• 'autocomplete' enables |ins-autocompletion|. • 'autocomplete' enables |ins-autocompletion|.
• 'autowriteall' writes all buffers upon receiving `SIGHUP`, `SIGQUIT` or `SIGTSTP`. • 'autowriteall' writes all buffers upon receiving `SIGHUP`, `SIGQUIT` or `SIGTSTP`.
• 'chistory' and 'lhistory' set size of the |quickfix-stack|. • 'chistory' and 'lhistory' set size of the |quickfix-stack|.
• 'completefuzzycollect' enables fuzzy collection of candidates for (some)
|ins-completion| modes.
• 'complete' new flags: • 'complete' new flags:
• "F{func}" complete using given function • "F{func}" complete using given function
• "F" complete using 'completefunc' • "F" complete using 'completefunc'

View File

@@ -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 This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons. 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'*
'completeitemalign' 'cia' string (default "abbr,kind,menu") 'completeitemalign' 'cia' string (default "abbr,kind,menu")
global global
@@ -1632,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 fuzzy Enable |fuzzy-matching| for completion candidates. This
allows for more flexible and intuitive matching, where allows for more flexible and intuitive matching, where
characters can be skipped and matches can be found even characters can be skipped and matches can be found even
if the exact sequence is not typed. Note: This option if the exact sequence is not typed.
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'.
longest longest
When 'autocomplete' is not active, only the longest common When 'autocomplete' is not active, only the longest common

View File

@@ -1133,31 +1133,6 @@ vim.o.cfu = vim.o.completefunc
vim.bo.completefunc = vim.o.completefunc vim.bo.completefunc = vim.o.completefunc
vim.bo.cfu = vim.bo.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 --- A comma-separated list of strings that controls the alignment and
--- display order of items in the popup menu during Insert mode --- display order of items in the popup menu during Insert mode
--- completion. The supported values are "abbr", "kind", and "menu". --- completion. The supported values are "abbr", "kind", and "menu".
@@ -1177,12 +1152,7 @@ vim.go.cia = vim.go.completeitemalign
--- fuzzy Enable `fuzzy-matching` for completion candidates. This --- fuzzy Enable `fuzzy-matching` for completion candidates. This
--- allows for more flexible and intuitive matching, where --- allows for more flexible and intuitive matching, where
--- characters can be skipped and matches can be found even --- characters can be skipped and matches can be found even
--- if the exact sequence is not typed. Note: This option --- if the exact sequence is not typed.
--- 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'.
--- ---
--- longest --- longest
--- When 'autocomplete' is not active, only the longest common --- When 'autocomplete' is not active, only the longest common

View File

@@ -242,7 +242,6 @@ local options_list = {
{ 'autocompletedelay', N_ 'delay in msec before menu appears after typing' }, { 'autocompletedelay', N_ 'delay in msec before menu appears after typing' },
{ 'completeopt', N_ 'whether to use a popup menu for Insert mode completion' }, { 'completeopt', N_ 'whether to use a popup menu for Insert mode completion' },
{ 'completeitemalign', N_ 'popup menu item align order' }, { 'completeitemalign', N_ 'popup menu item align order' },
{ 'completefuzzycollect', N_ 'use fuzzy collection for specific completion modes' },
{ 'pumheight', N_ 'maximum height of the popup menu' }, { 'pumheight', N_ 'maximum height of the popup menu' },
{ 'pumwidth', N_ 'minimum width of the popup menu' }, { 'pumwidth', N_ 'minimum width of the popup menu' },
{ 'pummaxwidth', N_ 'maximum width of the popup menu' }, { 'pummaxwidth', N_ 'maximum width of the popup menu' },

View File

@@ -225,11 +225,8 @@ static compl_T *compl_shown_match = NULL;
static compl_T *compl_old_match = NULL; static compl_T *compl_old_match = NULL;
/// list used to store the compl_T which have the max score /// list used to store the compl_T which have the max score
/// used for completefuzzycollect
static compl_T **compl_best_matches = NULL; static compl_T **compl_best_matches = NULL;
static int compl_num_bests = 0; static int compl_num_bests = 0;
/// inserted a longest when completefuzzycollect enabled
static bool compl_cfc_longest_ins = false;
/// After using a cursor key <Enter> selects a match in the popup menu, /// After using a cursor key <Enter> selects a match in the popup menu,
/// otherwise it inserts a line break. /// 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; 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 /// free cptext
static inline void free_cptext(char *const *const 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. /// Returns true if matches should be sorted based on proximity to the cursor.
static bool is_nearest_active(void) static bool is_nearest_active(void)
{ {
unsigned flags = get_cot_flags(); return (compl_autocomplete || (get_cot_flags() & kOptCotFlagNearest))
return (compl_autocomplete || (flags & kOptCotFlagNearest)) && !cot_fuzzy();
&& !(flags & kOptCotFlagFuzzy);
} }
/// True if a match is selected (even if it is not inserted). /// 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 . // current match in the list of matches .
if (compl_first_match == NULL) { if (compl_first_match == NULL) {
match->cp_next = match->cp_prev = 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 *current = compl_first_match->cp_next;
compl_T *prev = compl_first_match; compl_T *prev = compl_first_match;
inserted = false; inserted = false;
// The direction is ignored when using longest and // The direction is ignored when using longest and fuzzy match, because
// completefuzzycollect, because matches are inserted // matches are inserted and sorted by score.
// and sorted by score.
while (current != NULL && current != compl_first_match) { while (current != NULL && current != compl_first_match) {
if (current->cp_score < score) { if (current->cp_score < score) {
match->cp_next = current; 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; compl_curr_match = match;
// Find the longest common string if still doing that. // 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_preinsert_longest()) {
ins_compl_longest_match(match); 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(); const bool has_preinsert = ins_compl_has_preinsert() || ins_compl_preinsert_longest();
int attr; int attr;
if ((get_cot_flags() & kOptCotFlagFuzzy) if (cot_fuzzy()
|| (!compl_hi_on_autocompl_longest && ins_compl_preinsert_longest()) || (!compl_hi_on_autocompl_longest && ins_compl_preinsert_longest())
|| (attr = syn_name2attr(has_preinsert ? "PreInsert" : "ComplMatchIns")) == 0) { || (attr = syn_name2attr(has_preinsert ? "PreInsert" : "ComplMatchIns")) == 0) {
return -1; return -1;
@@ -1538,10 +1525,8 @@ static int ins_compl_build_pum(void)
XFREE_CLEAR(compl_leader); XFREE_CLEAR(compl_leader);
} }
unsigned cur_cot_flags = get_cot_flags(); bool compl_no_select = (get_cot_flags() & kOptCotFlagNoselect) != 0
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0
|| (compl_autocomplete && !ins_compl_has_preinsert()); || (compl_autocomplete && !ins_compl_has_preinsert());
bool fuzzy_filter = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
compl_T *match_head = NULL, *match_tail = NULL; compl_T *match_head = NULL, *match_tail = NULL;
int *match_count = NULL; int *match_count = NULL;
@@ -1576,14 +1561,14 @@ static int ins_compl_build_pum(void)
// Apply 'smartcase' behavior during normal mode // Apply 'smartcase' behavior during normal mode
if (ctrl_x_mode_normal() && !p_inf && leader->data if (ctrl_x_mode_normal() && !p_inf && leader->data
&& !ignorecase(leader->data) && !fuzzy_filter) { && !ignorecase(leader->data) && !cot_fuzzy()) {
comp->cp_flags &= ~CP_ICASE; comp->cp_flags &= ~CP_ICASE;
} }
if (!match_at_original_text(comp) if (!match_at_original_text(comp)
&& (leader->data == NULL && (leader->data == NULL
|| ins_compl_equal(comp, leader->data, leader->size) || 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. // Limit number of items from each source if max_items is set.
bool match_limit_exceeded = false; bool match_limit_exceeded = false;
int cur_source = comp->cp_cpt_source_idx; int cur_source = comp->cp_cpt_source_idx;
@@ -1605,7 +1590,7 @@ static int ins_compl_build_pum(void)
} }
match_tail = comp; match_tail = comp;
if (!shown_match_ok && !fuzzy_filter) { if (!shown_match_ok && !cot_fuzzy()) {
if (comp == compl_shown_match || did_find_shown_match) { if (comp == compl_shown_match || did_find_shown_match) {
// This item is the shown match or this is the // This item is the shown match or this is the
// first displayed item after the shown match. // first displayed item after the shown match.
@@ -1618,7 +1603,7 @@ static int ins_compl_build_pum(void)
shown_compl = comp; shown_compl = comp;
} }
cur = i; cur = i;
} else if (fuzzy_filter) { } else if (cot_fuzzy()) {
if (i == 0) { if (i == 0) {
shown_compl = comp; 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; did_find_shown_match = true;
// When the original text is the shown match don't set // When the original text is the shown match don't set
// compl_shown_match. // compl_shown_match.
@@ -1655,7 +1640,7 @@ static int ins_compl_build_pum(void)
return -1; 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; compl_shown_match = shown_compl;
shown_match_ok = true; shown_match_ok = true;
cur = 0; 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); spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
} else if (count > 0) { // avoid warning for using "files" uninit } else if (count > 0) { // avoid warning for using "files" uninit
ins_compl_files(count, files, thesaurus, flags, ins_compl_files(count, files, thesaurus, flags, &regmatch, buf, &dir);
(cfc_has_mode() ? NULL : &regmatch), buf, &dir);
if (flags != DICT_EXACT) { if (flags != DICT_EXACT) {
FreeWild(count, files); 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) regmatch_T *regmatch, char *buf, Direction *dir)
FUNC_ATTR_NONNULL_ARG(2, 7) FUNC_ATTR_NONNULL_ARG(2, 7)
{ {
bool in_fuzzy_collect = cfc_has_mode(); char *leader = cot_fuzzy() ? ins_compl_leader() : NULL;
int leader_len = cot_fuzzy() ? (int)ins_compl_leader_len() : 0;
char *leader = in_fuzzy_collect ? ins_compl_leader() : NULL;
int leader_len = in_fuzzy_collect ? (int)ins_compl_leader_len() : 0;
for (int i = 0; i < count && !got_int && !ins_compl_interrupted(); i++) { for (int i = 0; i < count && !got_int && !ins_compl_interrupted(); i++) {
FILE *fp = os_fopen(files[i], "r"); // open dictionary file 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. // Check each line for a match.
while (!got_int && !ins_compl_interrupted() && !vim_fgets(buf, LSIZE, fp)) { while (!got_int && !ins_compl_interrupted() && !vim_fgets(buf, LSIZE, fp)) {
char *ptr = buf; 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))) { while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf))) {
ptr = regmatch->startp[0]; ptr = regmatch->startp[0];
ptr = ctrl_x_mode_line_or_eval() ? find_line_end(ptr) : find_word_end(ptr); 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; 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(); line_breakcheck();
ins_compl_check_keys(50, false); ins_compl_check_keys(50, false);
@@ -2085,7 +2068,6 @@ void ins_compl_clear(void)
{ {
compl_cont_status = 0; compl_cont_status = 0;
compl_started = false; compl_started = false;
compl_cfc_longest_ins = false;
compl_matches = 0; compl_matches = 0;
compl_selected_item = -1; compl_selected_item = -1;
compl_ins_end_col = 0; compl_ins_end_col = 0;
@@ -2302,7 +2284,7 @@ static void ins_compl_new_leader(void)
if (is_cpt_func_refresh_always()) { if (is_cpt_func_refresh_always()) {
cpt_compl_refresh(); cpt_compl_refresh();
} }
if (get_cot_flags() & kOptCotFlagFuzzy) { if (cot_fuzzy()) {
ins_compl_fuzzy_sort(); ins_compl_fuzzy_sort();
} }
} else { } else {
@@ -4068,7 +4050,6 @@ static void fuzzy_longest_match(void)
prefix = xmemdupz(prefix, (size_t)prefix_len); prefix = xmemdupz(prefix, (size_t)prefix_len);
ins_compl_longest_insert(prefix); ins_compl_longest_insert(prefix);
compl_cfc_longest_ins = true;
xfree(prefix); xfree(prefix);
end: end:
@@ -4084,7 +4065,7 @@ static void get_next_filename_completion(void)
int num_matches; int num_matches;
char *leader = ins_compl_leader(); char *leader = ins_compl_leader();
size_t leader_len = ins_compl_leader_len(); 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; bool need_collect_bests = in_fuzzy_collect && compl_get_longest;
int max_score = 0; int max_score = 0;
Direction dir = compl_direction; 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; char *ptr = NULL;
int len = 0; int len = 0;
bool in_fuzzy_collect = !compl_status_adding() bool in_fuzzy_collect = !compl_status_adding() && cot_fuzzy() && compl_length > 0;
&& ((cfc_has_mode() && compl_length > 0)
|| ((get_cot_flags() & kOptCotFlagFuzzy) && compl_autocomplete));
char *leader = ins_compl_leader(); char *leader = ins_compl_leader();
int score = FUZZY_SCORE_NONE; int score = FUZZY_SCORE_NONE;
const bool in_curbuf = st->ins_buf == curbuf; 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()) if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
&& (!compl_started || st.found_all)) { && (!compl_started || st.found_all)) {
int status = process_next_cpt_value(&st, &type, &start_pos, 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) { if (status == INS_COMPL_CPT_END) {
break; break;
} }
@@ -4919,7 +4898,7 @@ static int ins_compl_get_exp(pos_T *ini)
match_count = ins_compl_make_cyclic(); 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(); fuzzy_longest_match();
} }
@@ -4941,7 +4920,7 @@ static int ins_compl_get_exp(pos_T *ini)
sort_compl_match_list(cp_compare_nearest); 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(); 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(); unsigned cur_cot_flags = get_cot_flags();
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0 bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0
|| (compl_autocomplete && !ins_compl_has_preinsert()); || (compl_autocomplete && !ins_compl_has_preinsert());
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
while (--todo >= 0) { while (--todo >= 0) {
if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) { 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) if (!match_at_original_text(compl_shown_match)
&& leader->data != NULL && leader->data != NULL
&& !ins_compl_equal(compl_shown_match, leader->data, leader->size) && !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++; todo++;
} else { } else {
// Remember a matching item. // 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(); unsigned cur_cot_flags = get_cot_flags();
bool compl_no_insert = (cur_cot_flags & kOptCotFlagNoinsert) != 0 bool compl_no_insert = (cur_cot_flags & kOptCotFlagNoinsert) != 0
|| (compl_autocomplete && !ins_compl_has_preinsert()); || (compl_autocomplete && !ins_compl_has_preinsert());
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
bool compl_preinsert = ins_compl_has_preinsert(); bool compl_preinsert = ins_compl_has_preinsert();
bool has_autocomplete_delay = (compl_autocomplete && p_acl > 0); 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 if (compl_leader.data != NULL
&& !match_at_original_text(compl_shown_match) && !match_at_original_text(compl_shown_match)
&& !compl_fuzzy_match) { && !cot_fuzzy()) {
// Update "compl_shown_match" to the actually shown match // Update "compl_shown_match" to the actually shown match
ins_compl_update_shown_match(); ins_compl_update_shown_match();
} }

View File

@@ -296,8 +296,6 @@ EXTERN char *p_cpt; ///< 'complete'
EXTERN OptInt p_cto; ///< 'completetimeout' EXTERN OptInt p_cto; ///< 'completetimeout'
EXTERN OptInt p_columns; ///< 'columns' EXTERN OptInt p_columns; ///< 'columns'
EXTERN int p_confirm; ///< 'confirm' EXTERN int p_confirm; ///< 'confirm'
EXTERN char *p_cfc; ///< 'completefuzzycollect'
EXTERN unsigned cfc_flags; ///< flags from 'completefuzzycollect'
EXTERN char *p_cia; ///< 'completeitemalign' EXTERN char *p_cia; ///< 'completeitemalign'
EXTERN unsigned cia_flags; ///< order flags of 'completeitemalign' EXTERN unsigned cia_flags; ///< order flags of 'completeitemalign'
EXTERN char *p_cot; ///< 'completeopt' EXTERN char *p_cot; ///< 'completeopt'

View File

@@ -1576,40 +1576,6 @@ local options = {
type = 'string', type = 'string',
varname = 'p_cfu', 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', abbreviation = 'cia',
cb = 'did_set_completeitemalign', cb = 'did_set_completeitemalign',
@@ -1657,12 +1623,7 @@ local options = {
fuzzy Enable |fuzzy-matching| for completion candidates. This fuzzy Enable |fuzzy-matching| for completion candidates. This
allows for more flexible and intuitive matching, where allows for more flexible and intuitive matching, where
characters can be skipped and matches can be found even characters can be skipped and matches can be found even
if the exact sequence is not typed. Note: This option if the exact sequence is not typed.
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'.
longest longest
When 'autocomplete' is not active, only the longest common When 'autocomplete' is not active, only the longest common

View File

@@ -90,7 +90,6 @@ void didset_string_options(void)
check_str_opt(kOptCasemap, NULL); check_str_opt(kOptCasemap, NULL);
check_str_opt(kOptBackupcopy, NULL); check_str_opt(kOptBackupcopy, NULL);
check_str_opt(kOptBelloff, NULL); check_str_opt(kOptBelloff, NULL);
check_str_opt(kOptCompletefuzzycollect, NULL);
check_str_opt(kOptIsexpand, NULL); check_str_opt(kOptIsexpand, NULL);
check_str_opt(kOptCompleteopt, NULL); check_str_opt(kOptCompleteopt, NULL);
check_str_opt(kOptSessionoptions, NULL); check_str_opt(kOptSessionoptions, NULL);

View File

@@ -7963,11 +7963,10 @@ describe('builtin popupmenu', function()
end) end)
-- oldtest: Test_pum_completefuzzycollect() -- oldtest: Test_pum_completefuzzycollect()
it('completefuzzycollect', function() it('fuzzy completion', function()
exec([[ exec([[
set pumwidth=13 set pumwidth=13
set completefuzzycollect=keyword,files set completeopt=menu,menuone,fuzzy
set completeopt=menu,menuone
]]) ]])
feed('S hello helio hero h<C-X><C-P>') feed('S hello helio hero h<C-X><C-P>')

View File

@@ -188,9 +188,9 @@ let test_values = {
\ 's', 's/tmp/dir\\\ with\\\ space/*', \ 's', 's/tmp/dir\\\ with\\\ space/*',
\ 'w,b,k/tmp/dir\\\ with\\\ space/*,s'], \ 'w,b,k/tmp/dir\\\ with\\\ space/*,s'],
\ ['xxx']], \ ['xxx']],
\ 'completefuzzycollect': [['', 'keyword', 'files', 'whole_line', "\ 'completefuzzycollect': [['', 'keyword', 'files', 'whole_line',
\ 'keyword,whole_line', 'files,whole_line', 'keyword,files,whole_line'], "\ " 'keyword,whole_line', 'files,whole_line', 'keyword,files,whole_line'],
\ ['xxx', 'keyword,,,whole_line,']], "\ " ['xxx', 'keyword,,,whole_line,']],
\ 'completeitemalign': [['abbr,kind,menu', 'menu,abbr,kind'], \ 'completeitemalign': [['abbr,kind,menu', 'menu,abbr,kind'],
\ ['', 'xxx', 'abbr', 'abbr,menu', 'abbr,menu,kind,abbr', \ ['', 'xxx', 'abbr', 'abbr,menu', 'abbr,menu,kind,abbr',
\ 'abbr1234,kind,menu']], \ 'abbr1234,kind,menu']],

View File

@@ -386,8 +386,8 @@ func Test_CompleteDone_vevent_keys()
call assert_equal('foo_test', g:complete_word) call assert_equal('foo_test', g:complete_word)
call assert_equal('files', g:complete_type) call assert_equal('files', g:complete_type)
call writefile(['hello help'], 'test_case.txt', 'D') call writefile(['hello help'], 'Xtest_case.txt', 'D')
set dictionary=test_case.txt set dictionary=Xtest_case.txt
call feedkeys("ggdGSh\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx') call feedkeys("ggdGSh\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx')
call assert_equal('hello', g:complete_word) call assert_equal('hello', g:complete_word)
call assert_equal('dictionary', g:complete_type) call assert_equal('dictionary', g:complete_type)
@@ -3660,6 +3660,7 @@ func Test_complete_opt_fuzzy()
call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx') call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx')
call assert_equal("for", g:abbr) call assert_equal("for", g:abbr)
%d
set cot=menu,fuzzy set cot=menu,fuzzy
call feedkeys("Sblue\<CR>bar\<CR>b\<C-X>\<C-P>\<C-Y>\<ESC>", 'tx') call feedkeys("Sblue\<CR>bar\<CR>b\<C-X>\<C-P>\<C-Y>\<ESC>", 'tx')
call assert_equal('blue', getline('.')) call assert_equal('blue', getline('.'))
@@ -3692,7 +3693,7 @@ func Test_complete_opt_fuzzy()
" Issue 18488: sort after collection when "fuzzy" (unless "nosort") " Issue 18488: sort after collection when "fuzzy" (unless "nosort")
%d %d
set completeopt& set completeopt&
set completeopt+=fuzzy,noselect completefuzzycollect=keyword set completeopt+=fuzzy,noselect
func! PrintMenuWords() func! PrintMenuWords()
let info = complete_info(["items"]) let info = complete_info(["items"])
call map(info.items, {_, v -> v.word}) call map(info.items, {_, v -> v.word})
@@ -3705,7 +3706,7 @@ func Test_complete_opt_fuzzy()
" clean up " clean up
set omnifunc= set omnifunc=
bw! bw!
set complete& completeopt& completefuzzycollect& set complete& completeopt&
autocmd! AAAAA_Group autocmd! AAAAA_Group
augroup! AAAAA_Group augroup! AAAAA_Group
delfunc OnPumChange delfunc OnPumChange
@@ -3720,7 +3721,7 @@ endfunc
func Test_complete_fuzzy_collect() func Test_complete_fuzzy_collect()
new new
redraw " need this to prevent NULL dereference in Nvim 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']) call setline(1, ['hello help hero h'])
" Use "!" flag of feedkeys() so that ex_normal_busy is not set and " Use "!" flag of feedkeys() so that ex_normal_busy is not set and
" ins_compl_check_keys() is not skipped. " 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('.')) call assert_equal('no one can save me but you', getline('.'))
" issue #15526 " issue #15526
set completeopt=menuone,menu,noselect set completeopt=menuone,menu,noselect,fuzzy
call setline(1, ['Text', 'ToText', '']) call setline(1, ['Text', 'ToText', ''])
call cursor(3, 1) call cursor(3, 1)
call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!') call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!')
@@ -3811,8 +3812,8 @@ func Test_complete_fuzzy_collect()
call assert_equal('completefuzzycollect', getline(line('.') - 1)) call assert_equal('completefuzzycollect', getline(line('.') - 1))
" keywords in 'dictonary' " keywords in 'dictonary'
call writefile(['hello', 'think'], 'test_dict.txt', 'D') call writefile(['hello', 'think'], 'Xtest_dict.txt', 'D')
set dict=test_dict.txt set dict=Xtest_dict.txt
call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<CR>\<Esc>0", 'tx!') call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<CR>\<Esc>0", 'tx!')
call assert_equal('hello', getline(line('.') - 1)) call assert_equal('hello', getline(line('.') - 1))
call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!') call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!')
@@ -3827,16 +3828,26 @@ func Test_complete_fuzzy_collect()
call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-Y>\<Esc>0", 'tx!') call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-Y>\<Esc>0", 'tx!')
call assert_equal('fuzzycollect', getline('.')) 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\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx')
call assert_equal('Hello', getline('.'))
call feedkeys("ggdGSHE\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx')
call assert_equal('HELLO', getline('.'))
bw! bw!
bw! bw!
set dict& set dict&
set completeopt& cfc& cpt& set completeopt& cpt& ignorecase& infercase&
endfunc endfunc
" Issue #18752 " Issue #18752
func Test_complete_fuzzy_collect_multiwin() func Test_complete_fuzzy_collect_multiwin()
new new
set completefuzzycollect=keyword,files,whole_line
set completeopt=fuzzy set completeopt=fuzzy
vnew vnew
@@ -3846,12 +3857,11 @@ func Test_complete_fuzzy_collect_multiwin()
call assert_equal('Omnipotent', getline('.')) call assert_equal('Omnipotent', getline('.'))
bw! bw!
set completeopt& cfc& set completeopt&
endfunc endfunc
func Test_cfc_with_longest() func Test_cfc_with_longest()
new new
set completefuzzycollect=keyword,files,whole_line
set completeopt=menu,menuone,longest,fuzzy set completeopt=menu,menuone,longest,fuzzy
" keyword " keyword
@@ -3935,7 +3945,6 @@ func Test_cfc_with_longest()
bw! bw!
set completeopt& set completeopt&
set completefuzzycollect&
endfunc endfunc
func Test_completefuzzycollect_with_completeslash() func Test_completefuzzycollect_with_completeslash()
@@ -3945,7 +3954,7 @@ func Test_completefuzzycollect_with_completeslash()
let orig_shellslash = &shellslash let orig_shellslash = &shellslash
set cpt& set cpt&
new new
set completefuzzycollect=files set completeopt+=fuzzy
set noshellslash set noshellslash
" Test with completeslash unset " Test with completeslash unset
@@ -3967,7 +3976,6 @@ func Test_completefuzzycollect_with_completeslash()
" Reset and clean up " Reset and clean up
let &shellslash = orig_shellslash let &shellslash = orig_shellslash
set completeslash= set completeslash=
set completefuzzycollect&
%bw! %bw!
endfunc endfunc

View File

@@ -543,7 +543,7 @@ func Test_set_completion_string_values()
endif endif
call assert_equal('.', getcompletion('set complete=', 'cmdline')[1]) call assert_equal('.', getcompletion('set complete=', 'cmdline')[1])
call assert_equal('menu', getcompletion('set completeopt=', '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') if exists('+completeslash')
call assert_equal('backslash', getcompletion('set completeslash=', 'cmdline')[1]) call assert_equal('backslash', getcompletion('set completeslash=', 'cmdline')[1])
endif endif

View File

@@ -1524,8 +1524,7 @@ endfunc
func Test_pum_completefuzzycollect() func Test_pum_completefuzzycollect()
CheckScreendump CheckScreendump
let lines =<< trim END let lines =<< trim END
set completefuzzycollect=keyword,files set completeopt=menu,menuone,fuzzy
set completeopt=menu,menuone
END END
call writefile(lines, 'Xscript', 'D') call writefile(lines, 'Xscript', 'D')
let buf = RunVimInTerminal('-S Xscript', {}) let buf = RunVimInTerminal('-S Xscript', {})