Patch 8.2.4760

9 views
Skip to first unread message

Bram Moolenaar

unread,
Apr 16, 2022, 7:36:28 AM4/16/22
to vim...@googlegroups.com

Patch 8.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)
Files: runtime/doc/builtin.txt, src/search.c,
src/testdir/test_matchfuzzy.vim


*** ../vim-8.2.4759/runtime/doc/builtin.txt 2022-04-12 12:54:06.917010952 +0100
--- runtime/doc/builtin.txt 2022-04-16 12:32:02.928950392 +0100
***************
*** 5565,5571 ****

If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items:
! key key of the item which is fuzzy matched against
{str}. The value of this item should be a
string.
text_cb |Funcref| that will be called for every item
--- 5583,5589 ----

If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items:
! key Key of the item which is fuzzy matched against
{str}. The value of this item should be a
string.
text_cb |Funcref| that will be called for every item
***************
*** 5573,5578 ****
--- 5591,5598 ----
This should accept a dictionary item as the
argument and return the text for that item to
use for fuzzy matching.
+ limit Maximum number of matches in {list} to be
+ returned. Zero means no limit.

{str} is treated as a literal string and regular expression
matching is NOT supported. The maximum supported {str} length
***************
*** 5585,5591 ****
empty list is returned. If length of {str} is greater than
256, then returns an empty list.

! Refer to |fuzzy-match| for more information about fuzzy
matching strings.

Example: >
--- 5605,5614 ----
empty list is returned. If length of {str} is greater than
256, then returns an empty list.

! When {limit} is given, matchfuzzy() will find up to this
! number of matches in {list} and return them in sorted order.
!
! Refer to |fuzzy-matching| for more information about fuzzy
matching strings.

Example: >
*** ../vim-8.2.4759/src/search.c 2022-04-10 18:09:03.075959743 +0100
--- src/search.c 2022-04-16 12:27:13.228168375 +0100
***************
*** 4648,4666 ****
char_u *key,
callback_T *item_cb,
int retmatchpos,
! list_T *fmatchlist)
{
long len;
fuzzyItem_T *ptrs;
listitem_T *li;
long i = 0;
! int found_match = FALSE;
int_u matches[MAX_FUZZY_MATCHES];

len = list_len(items);
if (len == 0)
return;

ptrs = ALLOC_CLEAR_MULT(fuzzyItem_T, len);
if (ptrs == NULL)
return;
--- 4648,4668 ----
char_u *key,
callback_T *item_cb,
int retmatchpos,
! list_T *fmatchlist,
! long max_matches)
{
long len;
fuzzyItem_T *ptrs;
listitem_T *li;
long i = 0;
! 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,4680 ****
--- 4677,4691 ----
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,4748 ****
}
}
ptrs[i].score = score;
! found_match = TRUE;
}
++i;
clear_tv(&rettv);
}

! if (found_match)
{
list_T *l;

--- 4747,4759 ----
}
}
ptrs[i].score = score;
! ++found_match;
}
++i;
clear_tv(&rettv);
}

! if (found_match > 0)
{
list_T *l;

***************
*** 4822,4827 ****
--- 4833,4839 ----
char_u *key = NULL;
int ret;
int matchseq = FALSE;
+ long max_matches = 0;

if (in_vim9script()
&& (check_for_list_arg(argvars, 0) == FAIL
***************
*** 4879,4884 ****
--- 4891,4906 ----
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,4919 ****
}

fuzzy_match_in_list(argvars[0].vval.v_list, tv_get_string(&argvars[1]),
! matchseq, key, &cb, retmatchpos, rettv->vval.v_list);

done:
free_callback(&cb);
--- 4935,4941 ----
}

fuzzy_match_in_list(argvars[0].vval.v_list, tv_get_string(&argvars[1]),
! matchseq, key, &cb, retmatchpos, rettv->vval.v_list, max_matches);

done:
free_callback(&cb);
*** ../vim-8.2.4759/src/testdir/test_matchfuzzy.vim 2021-01-02 17:31:10.887220293 +0000
--- src/testdir/test_matchfuzzy.vim 2022-04-16 12:16:45.818897317 +0100
***************
*** 230,233 ****
--- 230,245 ----
call assert_equal([['xффйд'], [[2, 3, 4]], [168]], matchfuzzypos(['xффйд'], 'фйд'))
endfunc

+ " Test for matchfuzzy() with limit
+ func Test_matchfuzzy_limit()
+ let x = ['1', '2', '3', '2']
+ call assert_equal(['2', '2'], x->matchfuzzy('2'))
+ call assert_equal(['2', '2'], x->matchfuzzy('2', #{}))
+ call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 0}))
+ call assert_equal(['2'], x->matchfuzzy('2', #{limit: 1}))
+ call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 2}))
+ call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 3}))
+ call assert_fails("call matchfuzzy(x, '2', #{limit: '2'})", 'E475:')
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.4759/src/version.c 2022-04-16 12:03:34.176519007 +0100
--- src/version.c 2022-04-16 12:18:53.874671915 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4760,
/**/

--
The process for understanding customers primarily involves sitting around with
other marketing people and talking about what you would to if you were dumb
enough to be a customer.
(Scott Adams - The Dilbert principle)

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages