From afd4ae35d66b2e7732eceb5ad9f6b4ece6b7c64c Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 27 Feb 2022 21:03:21 +0000 Subject: patch 8.2.4482: no fuzzy cmdline completion for user defined completion Problem: No fuzzy cmdline completion for user defined completion. Solution: Add fuzzy completion for user defined completion. (Yegappan Lakshmanan, closes #9858) --- src/cmdexpand.c | 93 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 27 deletions(-) (limited to 'src/cmdexpand.c') diff --git a/src/cmdexpand.c b/src/cmdexpand.c index e9db8cfc95..fee9f66099 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -16,15 +16,14 @@ static int cmd_showtail; // Only show path tail in lists ? static void set_expand_context(expand_T *xp); -static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, +static int ExpandGeneric(char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches, - char_u *((*func)(expand_T *, int)), int escaped, - char_u *fuzzystr); + char_u *((*func)(expand_T *, int)), int escaped); static int ExpandFromContext(expand_T *xp, char_u *, char_u ***, int *, int); static int expand_showtail(expand_T *xp); static int expand_shellcmd(char_u *filepat, char_u ***matches, int *numMatches, int flagsarg); #if defined(FEAT_EVAL) -static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches); +static int ExpandUserDefined(char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches); static int ExpandUserList(expand_T *xp, char_u ***matches, int *numMatches); #endif @@ -62,13 +61,13 @@ cmdline_fuzzy_completion_supported(expand_T *xp) && xp->xp_context != EXPAND_SHELLCMD && xp->xp_context != EXPAND_TAGS && xp->xp_context != EXPAND_TAGS_LISTFILES - && xp->xp_context != EXPAND_USER_DEFINED && xp->xp_context != EXPAND_USER_LIST); } /* * Returns TRUE if fuzzy completion for cmdline completion is enabled and - * 'fuzzystr' is not empty. + * 'fuzzystr' is not empty. If search pattern is empty, then don't use fuzzy + * matching. */ int cmdline_fuzzy_complete(char_u *fuzzystr) @@ -2444,16 +2443,10 @@ ExpandOther( { if (xp->xp_context == tab[i].context) { - // Use fuzzy matching if 'wildoptions' has 'fuzzy'. - // If no search pattern is supplied, then don't use fuzzy - // matching and return all the found items. - int fuzzy = cmdline_fuzzy_complete(pat); - if (tab[i].ic) rmp->rm_ic = TRUE; - ret = ExpandGeneric(xp, rmp, matches, numMatches, - tab[i].func, tab[i].escaped, - fuzzy ? pat : NULL); + ret = ExpandGeneric(pat, xp, rmp, matches, numMatches, + tab[i].func, tab[i].escaped); break; } } @@ -2604,7 +2597,7 @@ ExpandFromContext( ret = ExpandMappings(pat, ®match, numMatches, matches); # if defined(FEAT_EVAL) else if (xp->xp_context == EXPAND_USER_DEFINED) - ret = ExpandUserDefined(xp, ®match, matches, numMatches); + ret = ExpandUserDefined(pat, xp, ®match, matches, numMatches); # endif else ret = ExpandOther(pat, xp, ®match, matches, numMatches); @@ -2630,14 +2623,14 @@ ExpandFromContext( */ static int ExpandGeneric( + char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches, char_u *((*func)(expand_T *, int)), // returns a string from the list - int escaped, - char_u *fuzzystr) + int escaped) { int i; int count = 0; @@ -2645,10 +2638,12 @@ ExpandGeneric( char_u *str; fuzmatch_str_T *fuzmatch = NULL; int score = 0; - int fuzzy = (fuzzystr != NULL); + int fuzzy; int funcsort = FALSE; int match; + fuzzy = cmdline_fuzzy_complete(pat); + // do this loop twice: // round == 0: count the number of matching names // round == 1: copy the matching names into allocated memory @@ -2666,7 +2661,7 @@ ExpandGeneric( match = vim_regexec(regmatch, str, (colnr_T)0); else { - score = fuzzy_match_str(str, fuzzystr); + score = fuzzy_match_str(str, pat); match = (score != 0); } @@ -2976,10 +2971,12 @@ call_user_expand_func( } /* - * Expand names with a function defined by the user. + * Expand names with a function defined by the user (EXPAND_USER_DEFINED and + * EXPAND_USER_LIST). */ static int ExpandUserDefined( + char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, @@ -2990,7 +2987,12 @@ ExpandUserDefined( char_u *e; int keep; garray_T ga; - int skip; + int fuzzy; + int match; + int score; + int count = 0; + + fuzzy = cmdline_fuzzy_complete(pat); *matches = NULL; *numMatches = 0; @@ -2998,7 +3000,11 @@ ExpandUserDefined( if (retstr == NULL) return FAIL; - ga_init2(&ga, sizeof(char *), 3); + if (!fuzzy) + ga_init2(&ga, sizeof(char *), 3); + else + ga_init2(&ga, sizeof(fuzmatch_str_T), 3); + for (s = retstr; *s != NUL; s = e) { e = vim_strchr(s, '\n'); @@ -3007,23 +3013,56 @@ ExpandUserDefined( keep = *e; *e = NUL; - skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0; + if (xp->xp_pattern[0] || fuzzy) + { + if (!fuzzy) + match = vim_regexec(regmatch, s, (colnr_T)0); + else + { + score = fuzzy_match_str(s, pat); + match = (score != 0); + } + } + else + match = TRUE; // match everything + *e = keep; - if (!skip) + if (match) { if (ga_grow(&ga, 1) == FAIL) break; - ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s); + if (!fuzzy) + ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s); + else + { + fuzmatch_str_T *fuzmatch = + &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len]; + fuzmatch->idx = count; + fuzmatch->str = vim_strnsave(s, e - s); + fuzmatch->score = score; + } ++ga.ga_len; + count++; } if (*e != NUL) ++e; } vim_free(retstr); - *matches = ga.ga_data; - *numMatches = ga.ga_len; + + if (!fuzzy) + { + *matches = ga.ga_data; + *numMatches = ga.ga_len; + } + else + { + if (fuzzymatches_to_strmatches(ga.ga_data, matches, count, + FALSE) == FAIL) + return FAIL; + *numMatches = count; + } return OK; } -- cgit v1.2.3