raghur / fruzzy

Freaky fast fuzzy finder for (denite.nvim/CtrlP matcher) for vim/neovim
110 stars 7 forks source link

Is it possible to write a CtrlP matcher with this? #1

Closed lervag closed 6 years ago

lervag commented 6 years ago

Based on the description, I suspect it should be possible to write a CtrlP matcher with this as a backend. Do you think this is possible?

See also ctrlp-py-matcher and cpsm.

raghur commented 6 years ago

Of course... It should be. I used to use CPSM quite a while back but don't anymore

Do you want to contribute a PR?

lervag commented 6 years ago

Yes, I might, but I need some time to understand how to do it. If you already have some ideas it would be helpful to hear them. FYI, I have a lot of experience with Vim plugins, but none with developing within CtrlP or similar types of plugins.

raghur commented 6 years ago

That's great! My vimscript fu is pretty bad. I don't know what sort of interface CtrlP matcher expects - but you'd have to find that out. After that, it's a matter of:

  1. make sure fruzzy.py or fruzzy_mod is loaded and can be imported (based on whether user wants to load native mod)
  2. [pure python] call def scoreMatches(query, candidates, limit, key=None, ispath=True):
  3. [native] - call scoreMatchesStr (same params as above - other than there is no key func)
  4. Take a look at fruzzy_test.py for a wrapper that calls one of the above based on pref
    def scoreMatchesProxy(q, c, limit, key=None, ispath=True):
    if useNative:
        idxArr = scoreMatchesStr(q, (key(x) for x in c), limit, ispath)
        results = []
        for i in idxArr:
            results.append((c[i[0]], i[1]))
        return results
    else:
        return scoreMatches(q, c, limit, key, ispath)
  5. The python version takes any sequence and a key func to extract the string to search. The native version only takes a string sequence and returns a list of tuples (matchindex, score) in order of highest relevance.
  6. do any massaging reqd for ctrlp and send it back
lervag commented 6 years ago

It seems cspm is a good inspiration for how to do this. I've started to work on it, but it will probably take some time. I need to understand how to properly connect vimscript to python (I think we're almost there), and then how to import the fruzzy package from the ctrlp.py file and so on. I'm opening a PR so you can see how things develop.

lervag commented 6 years ago

Ok, I've done some more work, see #7. The initial goal is to have the pure python version to work first. I'll continue the discussion here for now. Some questions:

  1. What is key in scoreMatches?
  2. It would be nice to also highlight the matching strings. Do you have any idea how to achieve this? With cpsm, the matcher returns a list of regexes...
raghur commented 6 years ago

What is key in scoreMatches?

key is a func/lambda that is passed each item from candidates and returns a string. You only need it if you have a list of objects and need to extract the string to be matched against the query from each object in that list. Pass in none if you already have a list of strings.

It would be nice to also highlight the matching strings. Do you have any idea how to achieve this? With cpsm, the matcher returns a list of regexes...

fuzzyMatches returns a tuple:

(x, positions, clusterScore, sepScore, camelCaseScore, rank) where:

x - the candidate
positions - array of ints of char positions where the each char of query is matched
clusterScore, sepScore, camelCaseScore - raw scores
rank - Calculated rank of the match

So we don't have a reg ex but individual char positions. If you want a regex, you can just transform the input to a regex (this is what denite does - so a query like abc becomes vimscript regex like a[^a]{-}b[^b]{-}c that's used to highlight the match.

lervag commented 6 years ago

Pass in none if you already have a list of strings.

Great, thanks!

And thanks for the explenation of the returned tuple. I'll let you know if there are more questions.