When a pattern has multiple words, fuzzy match each word (in any order)
and return the matching strings sorted by the match score.
https://github.com/vim/vim/pull/7163
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.![]()
Merging #7163 into master will increase coverage by
0.00%.
The diff coverage is94.02%.
@@ Coverage Diff @@ ## master #7163 +/- ## ======================================= Coverage 88.73% 88.73% ======================================= Files 148 148 Lines 162113 162164 +51 ======================================= + Hits 143843 143900 +57 + Misses 18270 18264 -6
| Impacted Files | Coverage Δ | |
|---|---|---|
| src/search.c | 92.64% <94.02%> (+0.03%) |
⬆️ |
| src/clipboard.c | 83.31% <0.00%> (-0.11%) |
⬇️ |
| src/sign.c | 95.03% <0.00%> (+0.08%) |
⬆️ |
| src/gui.c | 63.35% <0.00%> (+0.14%) |
⬆️ |
| src/if_xcmdsrv.c | 88.90% <0.00%> (+0.17%) |
⬆️ |
| src/gui_gtk_x11.c | 59.06% <0.00%> (+0.24%) |
⬆️ |
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact),ø = not affected,? = missing data
Powered by Codecov. Last update 335e671...a6126b7. Read the comment docs.
Hmm, so if I match "one two" on a text that contains "two one", it stil matches? Isn't that a bit unexpected? If I would match "one_two" then it would not match "two_one", right? Thus we are making white space very special. Not sure if that is the goal.
Wouldn't it be better to make this optional? How can we fuzzy search for a literal white space character (not uncommon in file paths on Windows)?
—
You are receiving this because you commented.
Hmm, so if I match "one two" on a text that contains "two one", it stil matches? Isn't that a bit unexpected? If I would match "one_two" then it would not match "two_one", right? Thus we are making white space very special. Not sure if that is the goal.
Wouldn't it be better to make this optional? How can we fuzzy search for a literal white space character (not uncommon in file paths on Windows)?
We already have the optional {dict} argument. How about adding an item in there to disallow reordering words?
Naming it isn't so easy, "keep order" has a completely different meaning. Perhaps "sequential"?
—
You are receiving this because you commented.
This is a welcome addition. Emulating this feature in Vim script was not trivial, and time-consuming. I've made a brief test, and it seems to work. However, I've noticed that the matchseq key is ignored when filtering a list of dictionaries instead of a list of strings.
Here is a test which currently fails, while I think it should pass:
vim9script
[#{text: 'one two'}, #{text: 'two one'}]
->matchfuzzy('two one', #{key: 'text', matchseq: true})
->assert_equal([{'text': 'two one'}])
—
You are receiving this because you commented.
Emulating this feature in Vim script was not trivial, and time-consuming.
Just to give an idea. Before the patch:
vim9script
def Permutations(l: list<string>): list<list<string>>
if len(l) == 0
return [[]]
endif
var ret = []
for sublistPermutation in Permutations(l[1:])
for permutation in InsertItemAtAllPositions(l[0], sublistPermutation)
ret += [permutation]
endfor
endfor
return ret
enddef
def InsertItemAtAllPositions(item: string, l: list<string>): list<list<string>>
var ret = []
for i in range(len(l) + 1)
ret += [ (i == 0 ? [] : l[0 : i - 1]) + [item] + l[i : ] ]
endfor
return ret
enddef
var matchfuzzypos: list<any>
var filtered_source: list<dict<string>>
var pos: list<list<number>>
var tokens = split('one two three')
g:source = ['...']
if len(tokens) >= 4
var rest = tokens[2:]->join()->substitute('\s\+', '', 'g')
tokens = [tokens[0], tokens[1], rest]
endif
matchfuzzypos = tokens
->Permutations()
->map({_, v -> join(v, '')})
->map({_, v -> matchfuzzypos(g:source, v, #{key: 'text'})})
->reduce({a, v -> [a[0] + v[0], a[1] + v[1]]})
After the patch:
vim9script
var source = ['...']
var filtered_source: list<dict<string>>
var pos: list<list<number>>
[filtered_source, pos] = matchfuzzypos(source, 'one two three', #{key: 'text'})
—
You are receiving this because you commented.
I've noticed something else, although I'm not sure whether it could or should be changed.
When matchfuzzy*() filters a sequence of words, it is allowed to have some overlapping between the positions of 2 different words.
For example:
echo matchfuzzy(['ftplugin-docs'], 'fun undo')
['ftplugin-docs']
fun has been matched on these positions:
v v v
ftplugin-docs
undo has been matched on these positions:
ftplugin-docs
^ ^ ^^
If we place the two sets of positions on top of each other, we can see that the start of the second set starts before the end of the first one:
v v v
ftplugin-docs
^ ^ ^^
Note that fzf(1) does the same thing, so maybe that's what people expect (I don't; I would expect overlapping to be disallowed). I suspect that changing this would make the performance drastically decrease; if so, forget about this post.
—
You are receiving this because you commented.
I don't; I would expect overlapping to be disallowed
Although, if the overlapping matches are scored lower than the non-overlapping ones, that's not an issue.
—
You are receiving this because you commented.
This is a welcome addition. Emulating this feature in Vim script was not trivial, and time-consuming. I've made a brief test, and it seems to work. However, I've noticed that the
matchseqkey is ignored when filtering a list of dictionaries instead of a list of strings.Here is a test which currently fails, while I think it should pass:
vim9script [#{text: 'one two'}, #{text: 'two one'}] ->matchfuzzy('two one', #{key: 'text', matchseq: true}) ->assert_equal([{'text': 'two one'}])
I've noticed something else, although I'm not sure whether it could or should be changed.
When
matchfuzzy*()filters a sequence of words, it is allowed to have some overlapping between the positions of 2 different words.For example:
echo matchfuzzy(['ftplugin-docs'], 'fun undo') ['ftplugin-docs']
funhas been matched on these positions:v v v ftplugin-docs
undohas been matched on these positions:ftplugin-docs ^ ^ ^^If we place the two sets of positions on top of each other, we can see that the start of the second set starts before the end of the first one:
v v v ftplugin-docs ^ ^ ^^Note that
fzf(1)does the same thing, so maybe that's what people expect (I don't; I would expect overlapping to be disallowed). I suspect that changing this would make the performance drastically decrease; if so, forget about this post.
What is considered a "word"? Does this take into account 'iskeyword'?
—
You are receiving this because you commented.
What is considered a "word"? Does this take into account 'iskeyword'?
Are there any open remarks? Otherwise, let me know when this is ready to include.
—
You are receiving this because you commented.
Are there any open remarks? Otherwise, let me know when this is ready to include.
—
You are receiving this because you are subscribed to this thread.