summaryrefslogtreecommitdiffstats
path: root/src/cmdexpand.c
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-02-27 21:03:21 +0000
committerBram Moolenaar <Bram@vim.org>2022-02-27 21:03:21 +0000
commitafd4ae35d66b2e7732eceb5ad9f6b4ece6b7c64c (patch)
treed753eeffe7628a1b37f43b92e02aad071cde6849 /src/cmdexpand.c
parent5c52be40fbab14e050d7494d85be9039f07f7f8f (diff)
patch 8.2.4482: no fuzzy cmdline completion for user defined completionv8.2.4482
Problem: No fuzzy cmdline completion for user defined completion. Solution: Add fuzzy completion for user defined completion. (Yegappan Lakshmanan, closes #9858)
Diffstat (limited to 'src/cmdexpand.c')
-rw-r--r--src/cmdexpand.c93
1 files changed, 66 insertions, 27 deletions
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, &regmatch, numMatches, matches);
# if defined(FEAT_EVAL)
else if (xp->xp_context == EXPAND_USER_DEFINED)
- ret = ExpandUserDefined(xp, &regmatch, matches, numMatches);
+ ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
# endif
else
ret = ExpandOther(pat, xp, &regmatch, 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;
}