summaryrefslogtreecommitdiffstats
path: root/src/search.c
diff options
context:
space:
mode:
authorYasuhiro Matsumoto <mattn.jp@gmail.com>2022-04-16 12:35:35 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-16 12:35:35 +0100
commit9029a6e9931eede1d44f613687a2c01b9fe514ec (patch)
treeaacb7d7a0207d4ba70e62c9debe24d3e2590e43f /src/search.c
parent693ccd11606b59eb0f81c6c1948679e61ada4022 (diff)
patch 8.2.4760: using matchfuzzy() on a long list can take a whilev8.2.4760
Problem: Using matchfuzzy() on a long list can take a while. Solution: Add a limit to the number of matches. (Yasuhiro Matsumoto, closes #10189)
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/search.c b/src/search.c
index 470bde2146..42b66671c3 100644
--- a/src/search.c
+++ b/src/search.c
@@ -4648,19 +4648,21 @@ fuzzy_match_in_list(
char_u *key,
callback_T *item_cb,
int retmatchpos,
- list_T *fmatchlist)
+ list_T *fmatchlist,
+ long max_matches)
{
long len;
fuzzyItem_T *ptrs;
listitem_T *li;
long i = 0;
- int found_match = FALSE;
+ long found_match = 0;
int_u matches[MAX_FUZZY_MATCHES];
len = list_len(items);
if (len == 0)
return;
+ // TODO: when using a limit use that instead of "len"
ptrs = ALLOC_CLEAR_MULT(fuzzyItem_T, len);
if (ptrs == NULL)
return;
@@ -4675,6 +4677,15 @@ fuzzy_match_in_list(
ptrs[i].idx = i;
ptrs[i].item = li;
ptrs[i].score = SCORE_NONE;
+
+ // TODO: instead of putting all items in ptrs[] should only add
+ // matching items there.
+ if (max_matches > 0 && found_match >= max_matches)
+ {
+ i++;
+ continue;
+ }
+
itemstr = NULL;
rettv.v_type = VAR_UNKNOWN;
if (li->li_tv.v_type == VAR_STRING) // list of strings
@@ -4736,13 +4747,13 @@ fuzzy_match_in_list(
}
}
ptrs[i].score = score;
- found_match = TRUE;
+ ++found_match;
}
++i;
clear_tv(&rettv);
}
- if (found_match)
+ if (found_match > 0)
{
list_T *l;
@@ -4822,6 +4833,7 @@ do_fuzzymatch(typval_T *argvars, typval_T *rettv, int retmatchpos)
char_u *key = NULL;
int ret;
int matchseq = FALSE;
+ long max_matches = 0;
if (in_vim9script()
&& (check_for_list_arg(argvars, 0) == FAIL
@@ -4879,6 +4891,16 @@ do_fuzzymatch(typval_T *argvars, typval_T *rettv, int retmatchpos)
return;
}
}
+ else if ((di = dict_find(d, (char_u *)"limit", -1)) != NULL)
+ {
+ if (di->di_tv.v_type != VAR_NUMBER)
+ {
+ semsg(_(e_invalid_argument_str), tv_get_string(&di->di_tv));
+ return;
+ }
+ max_matches = (long)tv_get_number_chk(&di->di_tv, NULL);
+ }
+
if (dict_has_key(d, "matchseq"))
matchseq = TRUE;
}
@@ -4913,7 +4935,7 @@ do_fuzzymatch(typval_T *argvars, typval_T *rettv, int retmatchpos)
}
fuzzy_match_in_list(argvars[0].vval.v_list, tv_get_string(&argvars[1]),
- matchseq, key, &cb, retmatchpos, rettv->vval.v_list);
+ matchseq, key, &cb, retmatchpos, rettv->vval.v_list, max_matches);
done:
free_callback(&cb);