1

I'd like to define a command that initiates an isearch-forward-regexp with a predefined regexp.

Say I want to find all occurrences of either "aaa" or "bbb". The regexp which I can enter interactively with isearch-forward-regexp is \\(aaa\\|bbb\\)

Is there any way to do this without entering the regexp interactively? I've tried things like this:

(defun my-search ()
(interactive)
(isearch-mode t t)
(isearch-yank-string "\\(aaa\\|bbb\\)"))

but this approach doesn't seem to work because there doesn't seem to be any way to define a string in emacs that evaluates to \\(aaa\\|bbb\\) when yanked into isearch.

For instance "\\(aaa" evaluates to (aaa, but "\\\\(aaa" evaluates to \\\\(aaa. There doesn't seem to be a way to evaluate to a single backslash.

Is there a way of doing what I want?

Drew
  • 29,895
  • 7
  • 74
  • 104
Addlai
  • 121
  • 4

1 Answers1

2

This command should do what I think you are asking for:

(defun foo (regexp) 
  (interactive (list (read-regexp "Regexp: ")))
  (isearch-mode t t)
  (let ((isearch-regexp  nil))
    (isearch-yank-string regexp)))

For example: M-x foo RET, then enter \(aaa\|bbb\) RET.

If you call it from Lisp instead of interactively then just provide the regexp you want as a string. For example:

(foo "\\(aaa\\|bbb\\)")

Note that isearch-yank-string does this:

(if isearch-regexp (setq string (regexp-quote string)))

That's why foo binds isearch-regexp to nil around the call to isearch-yank-string: to prevent quoting regexp special chars in the string.

Drew
  • 29,895
  • 7
  • 74
  • 104
  • It doesn't seem to be working for me. When I run (foo "\\\(aaa\\|bbb\\\)") it searches for the literal string of the regexp, not the meaning of the regexp. For instance, "aaa" does not match, but the regexp string as it appears in the code of the function does match. Does it work on your emacs? – Addlai Oct 28 '17 at 14:42
  • Yes, it works fine in my Emacs - all Emacs releases from Emacs 20 through the latest Emacs 26.1 pretest. Be sure you include the let-binding of `isearch-regexp`, otherwise the behavior will be what you describe. That's because `isearch-yank-string` quotes regexp special chars if it thinks you're doing regexp searching. Test using `emacs -Q` (no init file). You may need to use `C-s` to repeat the search, once started. – Drew Oct 28 '17 at 19:28
  • Inexplicably, it started working after I restarted emacs, even with loading my .emacs. Perhaps I inadvertently put emacs in a peculiar state while fiddling with the function. Thanks. – Addlai Oct 28 '17 at 20:35
  • Consider accepting the answer, if you find it acceptable. (If you get a better answer later you can always change the accepted answer.) – Drew Oct 29 '17 at 07:14
  • When I tried to get the actual command to work, I had problems. Initially, isearch doesn't find anything. When I hit Ctrl-s a second time, it finds the occurrences, but in a wrapped search that goes back to the beginning of the file. I've given up on it at the moment and started exploring Atom, which seems to have a more powerful and modern design. – Addlai Nov 09 '17 at 04:02
  • Yes, you need to hit `C-s` a second time, in this context. – Drew Nov 09 '17 at 04:43