Skip to content

Commit 4f73b8e

Browse files
committed
patch 8.2.1726: fuzzy matching only works on strings
Problem: Fuzzy matching only works on strings. Solution: Support passing a dict. Add matchfuzzypos() to also get the match positions. (Yegappan Lakshmanan, closes #6947)
1 parent 44aaf54 commit 4f73b8e

File tree

9 files changed

+629
-167
lines changed

9 files changed

+629
-167
lines changed

runtime/doc/eval.txt

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,7 +2641,10 @@ matcharg({nr}) List arguments of |:match|
26412641
matchdelete({id} [, {win}]) Number delete match identified by {id}
26422642
matchend({expr}, {pat} [, {start} [, {count}]])
26432643
Number position where {pat} ends in {expr}
2644-
matchfuzzy({list}, {str}) List fuzzy match {str} in {list}
2644+
matchfuzzy({list}, {str} [, {dict}])
2645+
List fuzzy match {str} in {list}
2646+
matchfuzzypos({list}, {str} [, {dict}])
2647+
List fuzzy match {str} in {list}
26452648
matchlist({expr}, {pat} [, {start} [, {count}]])
26462649
List match and submatches of {pat} in {expr}
26472650
matchstr({expr}, {pat} [, {start} [, {count}]])
@@ -7311,12 +7314,25 @@ matchend({expr}, {pat} [, {start} [, {count}]]) *matchend()*
73117314
GetText()->matchend('word')
73127315

73137316

7314-
matchfuzzy({list}, {str}) *matchfuzzy()*
7315-
Returns a list with all the strings in {list} that fuzzy
7316-
match {str}. The strings in the returned list are sorted
7317-
based on the matching score. {str} is treated as a literal
7318-
string and regular expression matching is NOT supported.
7319-
The maximum supported {str} length is 256.
7317+
matchfuzzy({list}, {str} [, {dict}]) *matchfuzzy()*
7318+
If {list} is a list of strings, then returns a list with all
7319+
the strings in {list} that fuzzy match {str}. The strings in
7320+
the returned list are sorted based on the matching score.
7321+
7322+
If {list} is a list of dictionaries, then the optional {dict}
7323+
argument supports the following items:
7324+
key key of the item which is fuzzy matched against
7325+
{str}. The value of this item should be a
7326+
string.
7327+
text_cb |Funcref| that will be called for every item
7328+
in {list} to get the text for fuzzy matching.
7329+
This should accept a dictionary item as the
7330+
argument and return the text for that item to
7331+
use for fuzzy matching.
7332+
7333+
{str} is treated as a literal string and regular expression
7334+
matching is NOT supported. The maximum supported {str} length
7335+
is 256.
73207336

73217337
If there are no matching strings or there is an error, then an
73227338
empty list is returned. If length of {str} is greater than
@@ -7327,11 +7343,36 @@ matchfuzzy({list}, {str}) *matchfuzzy()*
73277343
< results in ["clay"]. >
73287344
:echo getbufinfo()->map({_, v -> v.name})->matchfuzzy("ndl")
73297345
< results in a list of buffer names fuzzy matching "ndl". >
7346+
:echo getbufinfo()->matchfuzzy("ndl", {'key' : 'name'})
7347+
< results in a list of buffer information dicts with buffer
7348+
names fuzzy matching "ndl". >
7349+
:echo getbufinfo()->matchfuzzy("spl",
7350+
\ {'text_cb' : {v -> v.name}})
7351+
< results in a list of buffer information dicts with buffer
7352+
names fuzzy matching "spl". >
73307353
:echo v:oldfiles->matchfuzzy("test")
73317354
< results in a list of file names fuzzy matching "test". >
73327355
:let l = readfile("buffer.c")->matchfuzzy("str")
73337356
< results in a list of lines in "buffer.c" fuzzy matching "str".
73347357

7358+
matchfuzzypos({list}, {str} [, {dict}]) *matchfuzzypos()*
7359+
Same as |matchfuzzy()|, but returns the list of matched
7360+
strings and the list of character positions where characters
7361+
in {str} matches.
7362+
7363+
If {str} matches multiple times in a string, then only the
7364+
positions for the best match is returned.
7365+
7366+
If there are no matching strings or there is an error, then a
7367+
list with two empty list items is returned.
7368+
7369+
Example: >
7370+
:echo matchfuzzypos(['testing'], 'tsg')
7371+
< results in [['testing'], [[0, 2, 6]]] >
7372+
:echo matchfuzzypos(['clay', 'lacy'], 'la')
7373+
< results in [['lacy', 'clay'], [[0, 1], [1, 2]]] >
7374+
:echo [{'text': 'hello', 'id' : 10}]->matchfuzzypos('ll', {'key' : 'text'})
7375+
< results in [{'id': 10, 'text': 'hello'}] [[2, 3]]
73357376

73367377
matchlist({expr}, {pat} [, {start} [, {count}]]) *matchlist()*
73377378
Same as |match()|, but return a |List|. The first item in the

runtime/doc/usr_41.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ String manipulation: *string-functions*
604604
match() position where a pattern matches in a string
605605
matchend() position where a pattern match ends in a string
606606
matchfuzzy() fuzzy matches a string in a list of strings
607+
matchfuzzypos() fuzzy matches a string in a list of strings
607608
matchstr() match of a pattern in a string
608609
matchstrpos() match and positions of a pattern in a string
609610
matchlist() like matchstr() and also return submatches

src/evalfunc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@ static funcentry_T global_functions[] =
753753
{"matcharg", 1, 1, FEARG_1, ret_list_string, f_matcharg},
754754
{"matchdelete", 1, 2, FEARG_1, ret_number, f_matchdelete},
755755
{"matchend", 2, 4, FEARG_1, ret_number, f_matchend},
756-
{"matchfuzzy", 2, 2, FEARG_1, ret_list_string, f_matchfuzzy},
756+
{"matchfuzzy", 2, 3, FEARG_1, ret_list_string, f_matchfuzzy},
757+
{"matchfuzzypos", 2, 3, FEARG_1, ret_list_any, f_matchfuzzypos},
757758
{"matchlist", 2, 4, FEARG_1, ret_list_string, f_matchlist},
758759
{"matchstr", 2, 4, FEARG_1, ret_string, f_matchstr},
759760
{"matchstrpos", 2, 4, FEARG_1, ret_list_any, f_matchstrpos},

src/proto/search.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ spat_T *get_spat(int idx);
3737
int get_spat_last_idx(void);
3838
void f_searchcount(typval_T *argvars, typval_T *rettv);
3939
void f_matchfuzzy(typval_T *argvars, typval_T *rettv);
40+
void f_matchfuzzypos(typval_T *argvars, typval_T *rettv);
4041
/* vim: set ft=c : */

0 commit comments

Comments
 (0)