Skip to content

Add support fuzzy matching a list of dictionaries using either a key or a callback function#6947

Closed
yegappan wants to merge 2 commits intovim:masterfrom
yegappan:fuzzy
Closed

Add support fuzzy matching a list of dictionaries using either a key or a callback function#6947
yegappan wants to merge 2 commits intovim:masterfrom
yegappan:fuzzy

Conversation

@yegappan
Copy link
Member

No description provided.

@yegappan yegappan requested a review from brammool as a code owner September 13, 2020 05:42
@codecov
Copy link

codecov bot commented Sep 13, 2020

Codecov Report

Merging #6947 into master will decrease coverage by 0.20%.
The diff coverage is 94.77%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6947      +/-   ##
==========================================
- Coverage   88.58%   88.38%   -0.21%     
==========================================
  Files         148      144       -4     
  Lines      161528   158442    -3086     
==========================================
- Hits       143096   140040    -3056     
+ Misses      18432    18402      -30     
Impacted Files Coverage Δ
src/evalfunc.c 96.27% <ø> (+0.01%) ⬆️
src/search.c 91.27% <94.77%> (-0.60%) ⬇️
src/json.c 90.95% <0.00%> (-1.30%) ⬇️
src/mbyte.c 79.29% <0.00%> (-1.29%) ⬇️
src/gui.c 62.27% <0.00%> (-1.19%) ⬇️
src/help.c 90.05% <0.00%> (-0.91%) ⬇️
src/textobject.c 91.69% <0.00%> (-0.71%) ⬇️
src/gui_gtk_x11.c 58.28% <0.00%> (-0.71%) ⬇️
src/message.c 87.84% <0.00%> (-0.66%) ⬇️
src/if_python.c 82.65% <0.00%> (-0.62%) ⬇️
... and 127 more

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 10e4f12...0e1bee5. Read the comment docs.

based on the matching score. {str} is treated as a literal
string and regular expression matching is NOT supported.
The maximum supported {str} length is 256.
matchfuzzy({list}, {str} [, {key}])

This comment was marked as resolved.

@yegappan yegappan force-pushed the fuzzy branch 4 times, most recently from c145346 to 070ce66 Compare September 14, 2020 03:01
@yegappan yegappan force-pushed the fuzzy branch 2 times, most recently from 31d8dfa to c6c41f8 Compare September 15, 2020 17:41
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 'name'})", 'E730:')

" Test for the fuzzymatchpos() function
call assert_equal([['curl', 'world'], [[2,3], [2,3]]], matchfuzzypos(['world', 'curl'], 'rl'))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing tests for key and text_cb for matchfuzzypost

call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 'name'})", 'E730:')

" Test for the fuzzymatchpos() function
call assert_equal([['curl', 'world'], [[2,3], [2,3]]], matchfuzzypos(['world', 'curl'], 'rl'))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also have a test case for multiple matches in the same item.

matchfuzzypos(['hello world hello world', 'hello', 'world]`, 'hello')

endfunc

" Test for the fuzzymatchpos() function
func Test_matchfuzzypos()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing tests for empty array. matchfuzzypos([], 'foo')

:let l = readfile("buffer.c")->matchfuzzy("str")
< results in a list of lines in "buffer.c" fuzzy matching "str".

matchfuzzypos({list}, {str} [, {dict}]) *matchfuzzypos()*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add example for dict or might be add a comment to refer to matchfuzzy dict option.

Copy link

@prabirshrestha prabirshrestha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added few comments.

" Test for the fuzzymatchpos() function
func Test_matchfuzzypos()
call assert_equal([['curl', 'world'], [[2,3], [2,3]]], matchfuzzypos(['world', 'curl'], 'rl'))
call assert_equal([['curl', 'world'], [[2,3], [2,3]]], matchfuzzypos(['world', 'one', 'curl'], 'rl'))
Copy link

@prabirshrestha prabirshrestha Sep 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this response be this instead? so that if there are multiple highlights it can still be represented correctly?

[
   [ "curl", "world", "curl world"],
   [
       [ [2,3] ],
       [ [2,3 ] ],
       [  [2,3], [7,8] ]
   ]
]

@vim-ml
Copy link

vim-ml commented Sep 15, 2020 via email

@yegappan yegappan force-pushed the fuzzy branch 5 times, most recently from 304776a to 2d75b3f Compare September 17, 2020 23:50
@prabirshrestha
Copy link

@yegappan any plans to return multiple highlights for an item? Is it currently the limitation in the library?
Would be good if it supported it even if the library didnt support it so in future can update the library without updating the public api.

@vim-ml
Copy link

vim-ml commented Sep 18, 2020 via email

@prabirshrestha
Copy link

It is very common if you are trying to create a fuzzy matching for files.

Here is a real example where I'm searching for sys\dri\hosts. In this case I'm actually interested in hosts file and not sys. this means hosts needs to be highlighted.

image

In projects I can see this using as controller/feature/featuresA/component.tsx, controller/features/featuresA/service.tsx I might want to use featureA/service. which means I want both to highlight.

@vim-ml
Copy link

vim-ml commented Sep 18, 2020 via email

@prabirshrestha
Copy link

prabirshrestha commented Sep 18, 2020

If I have 100 matches with each items having 2 highlights and only want to highlight 39:49 items do I need to loop through all the highlights which is 200 iterations or I can just ask for items[39:49] and iterate only 20 higlights?

I'm looking something like ios api for virtualization.

@vim-ml
Copy link

vim-ml commented Sep 19, 2020 via email

@yegappan yegappan force-pushed the fuzzy branch 2 times, most recently from 714ef10 to 113e4ca Compare September 19, 2020 06:45
@prabirshrestha
Copy link

Now it makes sense. I was looking for range but seems like you are giving character positions so should be possible to do it.

For this text System32\\drivers\\mausbhost.sys when I search for Sys\dri\hosts I get 0, 1, 2, 8, 9, 10, 11, 16, 22, 23, 24, 25, 27. If I want to use prop_add I need to calculate the length on my own as I most likely want to avoid adding prop_add for each character.

let matches = [ 0, 1, 2, 8, 9, 10, 11, 16, 22, 23, 24, 25, 27 ]

call prop_add(lnum, 0, { 'length': 3 })
call prop_add(lnum, 8, { 'length': 4 })
call prop_add(lnum, 16, { 'length': 1 })
call prop_add(lnum, 22, { 'length': 4 })
call prop_add(lnum, 27, { 'length': 1 })

might be what I need now is another function to convert it to range.

let matches = [ 0, 1, 2, 8, 9, 10, 11, 16, 22, 23, 24, 25, 27 ]
let matchrange = matchpos2range(matches) 
" matchrange = [[0, 3], [8, 4], [16, 1], [22, 4], [27, 1]]

for range in matchrange
    call prop_add(lnum, range[0], { 'length': range[1] })
endfor

@bfrg
Copy link
Contributor

bfrg commented Sep 19, 2020

Here's a very simple command that I used for testing matchfuzzypos():

if prop_type_get('test')->empty()
    call prop_type_add('test', {'highlight': 'Search'})
endif

function s:fuzzyfind(bang, mod, ...) abort
    if a:0 != 2
        return
    endif

    const files = systemlist('cd ' .. a:1 .. '; find -type f | sed "s/^\.\///"')
    const matches = matchfuzzypos(files, a:2)
    const info = printf('%s [dir: %s]', a:2, fnamemodify(a:1, ':~:.'))

    if empty(matches)
        return
    endif

    silent execute a:mod 'new' fnameescape(info)
    setlocal buftype=nofile noswapfile bufhidden=wipe
    call setline(1, matches[0])

    if a:bang
        for i in len(matches[1])->range()[: winheight(0) - 1]
            call len(matches[1][i])
                    \ ->range()
                    \ ->map({_,j ->
                    \   prop_add(i + 1, matches[1][i][j] + 1, {
                    \     'length': 1,
                    \     'type': 'test',
                    \     'bufnr': bufnr('%')
                    \   })
                    \ })
        endfor
    endif
    setlocal nomodifiable
endfunction

command -nargs=+ -bang -complete=dir Fuzzy call s:fuzzyfind(<bang>0, <q-mods>, <f-args>)

Use it like :Fuzzy! ~/path/to/project/ syshost.

@yegappan yegappan force-pushed the fuzzy branch 2 times, most recently from 6bcbbbe to 98ca316 Compare September 20, 2020 06:02
…or a callback function and the matchfuzzypos() function. Add support for fuzzy matching multibyte characters.
@brammool brammool closed this in 4f73b8e Sep 22, 2020
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 27, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 28, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 28, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 28, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 28, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 28, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Sep 29, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
vigoux added a commit to vigoux/neovim that referenced this pull request Oct 30, 2020
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 1, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 1, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and dead checks.
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 1, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and dead checks.

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 1, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and dead checks.

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 2, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and dead checks.

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 2, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and seemingly useless NULL checks (Nvim allocs can't return
NULL. I'm not sure why the retmatchpos stuff in match_fuzzy checks for NULL too,
given that Vim checks for NULL alloc in do_fuzzymatch...)

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
seandewar added a commit to seandewar/neovim that referenced this pull request Jan 2, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and seemingly useless NULL checks (Nvim allocs can't return
NULL. I'm not sure why the retmatchpos stuff in match_fuzzy checks for NULL too,
given that Vim checks for NULL alloc in do_fuzzymatch...)

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
zeertzjq pushed a commit to seandewar/neovim that referenced this pull request Jan 31, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and seemingly useless NULL checks (Nvim allocs can't return
NULL. I'm not sure why the retmatchpos stuff in match_fuzzy checks for NULL too,
given that Vim checks for NULL alloc in do_fuzzymatch...)

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
seandewar added a commit to seandewar/neovim that referenced this pull request Feb 7, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and seemingly useless NULL checks -- Nvim allocs can't
return NULL. I'm not sure why the retmatchpos stuff in match_fuzzy checks for
NULL too, given that Vim checks for NULL alloc in do_fuzzymatch; assert that the
li stuff is not NULL as that's the one check I'm ever-so-slightly unsure about.

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
zbirenbaum pushed a commit to zbirenbaum/neovim that referenced this pull request Feb 11, 2022
Problem:    Fuzzy matching only works on strings.
Solution:   Support passing a dict.  Add matchfuzzypos() to also get the match
            positions. (Yegappan Lakshmanan, closes vim/vim#6947)
vim/vim@4f73b8e

Also remove some N/A and seemingly useless NULL checks -- Nvim allocs can't
return NULL. I'm not sure why the retmatchpos stuff in match_fuzzy checks for
NULL too, given that Vim checks for NULL alloc in do_fuzzymatch; assert that the
li stuff is not NULL as that's the one check I'm ever-so-slightly unsure about.

Adjust tests. Note that the text_cb tests actually throw E6000 in Nvim, but we
also can't assert that error due to v8.2.1183 not being ported yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants