abo-abo / function-args

C++ completion for GNU Emacs
120 stars 10 forks source link

Add fuzzy matching for Helm commands #17

Closed tuhdo closed 9 years ago

tuhdo commented 9 years ago

Currently, Helm has just got a big update on fuzzy matching. You can enable fuzzy matching per source with :fuzzy-match slot set to t. Examples:

(helm :sources (helm-build-sync-source "test"
                 :candidates '("foo" "fox" "box" "bar" "baz")
                 :fuzzy-match t)
      :buffer "*helm test*")

(helm :sources (helm-build-in-buffer-source "test"
                 :data '("foo" "fox" "box" "bar" "baz")
                 :fuzzy-match t)
      :buffer "*helm test*")

Of course, you must use helm-build-sync-source and helm-build-in-buffer-source, because those are idiomatic ways to build Helm source now. Helm fuzzy matching has an advantage that you can perform fuzzy matching, or fall back to the old multi-matching depends on the patterns you entered. Many built-in Helm command have just got enabled with fuzzy matching, like helm-M-x, helm-lisp-completion-at-point, helm-locate-library, helm-recentf and works really well.

abo-abo commented 9 years ago

The examples that you provided are too simple to really show off the fuzzy matching. Can you give a better one? Maybe you have a link that shows this?

tuhdo commented 9 years ago

I added a demo in this PR. You can see how I convert from stock alist to proper way in this series of commits.

You can also download the latest Helm and play :)

abo-abo commented 9 years ago

How can I do this:

(helm :sources (helm-build-sync-source "test"
                 :candidates '(("foo" 10)
                               ("fox" 10)
                               ("box" 10)
                               ("bar" 10)
                               ("baz" 10))
                 :fuzzy-match t)
      :buffer "*helm test*")

It seems that it wants a list of strings instead of a list of lists with string a first element, like before. I need to pass tag info for each candidate. Passing only a string is not enough.

tuhdo commented 9 years ago

Currently it only accpets a list of strings. What did you pass into the source in the old way and why it is needed, may I know? Probably you can use slot candidate-transformer, filtered-candidate-transformer or filter-one-by-one to process custom candidates. The document for each slot is written in helm-source-sync. But for accuracy, I will ask on Helm mailing list.

abo-abo commented 9 years ago

Each candidate currently is a cons cell, with a pretty-printed tag name as car, and the full tag as cdr. The full tag is needed for many reasons.

helm-semantic just passes tags as properties of strings. I don't really like that approach. I'd prefer to do it the old way.

tuhdo commented 9 years ago

It turned out that it is currently buggy with fuzzy-match using cons cells. Will be fixed soon. You can view the thread here.

abo-abo commented 9 years ago

Thanks!

tuhdo commented 9 years ago

It is fixed. You can try this example:

(helm :sources (helm-build-sync-source "test"
                 :candidates '(("one" . 1)
                               ("two" . 2)
                               ("three" . 3))
                 :fuzzy-match t
                 :action (lambda (_c)
                           (apply '+ (helm-marked-candidates))))
      :buffer "*helm test*")

You must pass in a list of cons cells, not list of lists.

tuhdo commented 9 years ago

Thanks!