5

IIUC, all helm commands (including helm-swoop, swiper-helm) have regex enabled by default for user input. Can we toggle/disable it by some command/shortcut? Let me know if I missed something.

Using isearch as an analogy: default helm is similar to isearch-forward-regexp that always uses regex engine. Do we have helm-no-regex that is similar to isearch-forward which doesn't use regex?

For example, in helm-mini, when I search for "xy .c", I would like to match files like "xy_test.c", but not "xyzc.h". I know that we can escape the '.' (i.e., search for "xy \.c"), but I would like to escape all regex symbols by default. Is it possible?

I guess a possible solution is to pre-process input string by escaping all special characters?

(If it's not possible for helm, how about ivy/counsel/swiper?)

2 Answers 2

6

If it's not possible for helm, how about ivy/counsel/swiper?

Ivy is the library which Swiper search and Counsel convenience functions are backed by, so changing the way Ivy interprets its input affects the other two packages by extension.

IIUC, all helm commands (including helm-swoop, swiper-helm) have regex enabled by default for user input.

This is also true of Ivy; see below.

How to toggle regex for helm/ivy user input?

If you know ahead of time how you want Ivy to interpret input by default, or for any command in particular, you can customise ivy-re-builders-alist:

ivy-re-builders-alist is a variable defined in ‘ivy.el’.
Its value is ((t . ivy--regex-plus))

Documentation:
An alist of regex building functions for each collection function.

Each key is (in order of priority):
1. The actual collection function, e.g. ‘read-file-name-internal’.
2. The symbol passed by :caller into ‘ivy-read’.
3. ‘this-command’.
4. t.

Each value is a function that should take a string and return a
valid regex or a regex sequence (see below).

Possible choices: ‘ivy--regex’, ‘regexp-quote’,
‘ivy--regex-plus’, ‘ivy--regex-fuzzy’, ‘ivy--regex-ignore-order’.

If a function returns a list, it should format like this:
’(("matching-regexp" . t) ("non-matching-regexp") ...).

The matches will be filtered in a sequence, you can mix the
regexps that should match and that should not match as you
like.

See (ivy) Completion Styles and https://emacs.stackexchange.com/a/36748/15748 for further pointers.

Can we toggle/disable [regex matching] by some command/shortcut?

You can hot-swap completion styles during completion via C-om(hydra-ivy/ivy-rotate-preferred-builders), but for this you need to install the optional ivy-hydra package; see (ivy) Hydra in the minibuffer.

Alternatively, you can bind the command ivy-rotate-preferred-builders to a key of your choosing in ivy-minibuffer-map.

You can customise which regexp builders either of these commands rotate via ivy-preferred-re-builders:

ivy-preferred-re-builders is a variable defined in ‘ivy.el’.
Its value is
((ivy--regex-plus . "ivy")
 (ivy--regex-ignore-order . "order")
 (ivy--regex-fuzzy . "fuzzy"))

Documentation:
Alist of preferred re-builders with display names.
This list can be rotated with ‘ivy-rotate-preferred-builders’.

Do we have helm-no-regex that is similar to isearch-forward which doesn't use regex?

The closest thing that Ivy provides for this by default is the regexp-quote regexp builder:

(with-eval-after-load 'ivy
  ;; All searches are literal by default
  (add-to-list 'ivy-re-builders-alist (cons t #'regexp-quote))
  (add-to-list 'ivy-preferred-re-builders (cons #'regexp-quote "quote")))

For example, in helm-mini, when I search for "xy .c", I would like to match files like "xy_test.c", but not "xyzc.h". I know that we can escape the '.' (i.e., search for "xy \.c"), but I would like to escape all regex symbols by default. Is it possible?

Ivy does not, OOTB, provide a function which interprets everything except spaces literally, but you can write one yourself, or suggest such a function on the project's issue tracker.

Here are two such sample regexp builders. They result in identical matching behaviour, except the former is sensitive to the ordering of the whitespace-separated substrings, whereas the latter is not. You can add them to ivy-re-builders-alist and ivy-preferred-re-builders as previously shown.

(defun my-regexp-quote (string)
  "Build a regexp suitable for Ivy from STRING.
Convert whitespace to \".*\" and `regexp-quote' everything else."
  (mapconcat #'regexp-quote (split-string string) ".*"))

(defun my-regexp-quote-dynamic (string)
  "Build a regexp alist suitable for Ivy from STRING.
Has a similar effect to `my-regexp-quote', except the order of
whitespace-separated substrings is ignored."
  (mapcar (lambda (substring)
            (cons (regexp-quote substring) t))
          (split-string string)))
0

I think you are looking for the helm-ff-fuzzy-matching variable.

As the docs say:

Enable fuzzy matching for ‘helm-find-files’ when non--nil.

See ‘helm-ff--transform-pattern-for-completion’ for more info.

It’s default value is t, you may want to set it to nil to achieve what you want.

2
  • 1
    Tried (setq helm-ff-fuzzy-matching nil), but it still interprets the dot char as any char (i.e., still using regex). Thanks anyway.
    – AhLeung
    Apr 14, 2018 at 4:25
  • fuzzy is unlinked to regular expressions.
    – RichieHH
    Mar 5, 2020 at 7:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.