35

So, using the regular expression builder (M-x re-builder), finding lines that end in \ takes "\\$", while in search and replace by regex, it only takes "\$". I would have expected the regex builder to build directly usable expressions, so what accounts for this difference?

3
  • 6
    It builds expressions directly usable in code.
    – abo-abo
    Commented Dec 19, 2014 at 21:55
  • 1
    @abo-abo That's the answer I was looking for, I didn't realize that there's a difference between what's usable in code and what's usable in the ui. It seems counter intuitive that re-builder uses the codes syntax, and the manual doesn't say, but that explains the difference.
    – user2699
    Commented Dec 20, 2014 at 6:12
  • 3
    In order to make regex builder more useful for composing interactive searches, take a look at the ReBuilder emacs wiki page, especially the reb-query-replace function definition.
    – dfeich
    Commented Dec 20, 2014 at 8:58

1 Answer 1

42

There are actually four different re-builder syntax options, and you can switch between them with C-cTAB

Two are for the sexp-form regexp compilers rx and sregex (but as the former is more comprehensive and almost entirely syntax-compatible, you can really ignore sregex unless you happen to be working with old code that used it).

The other two syntax options are read (the default) and string (which is the syntax you use interactively).

The read syntax is the 'code' syntax -- i.e. as recognised by the lisp reader -- in which you enter the regexp as per the read syntax for strings:

C-hig (elisp) Syntax for Strings RET

The string syntax (which I've always considered an unnecessarily confusing name in this context) is the syntax of a regular expression string which has already been read, and which therefore does not have any of the character escaping required when writing the string. Which is to say, this is the actual regular expression syntax, the same as you use when Emacs prompts you interactively.

If you would like to use string syntax by default, add the following to your init file, or use M-x customize-option RET reb-re-syntax RET

(setq reb-re-syntax 'string)

Note that you can switch back and forth between read and string syntax when editing the regexp, with no loss of data. You can also switch from the sexp forms to read/string syntax (naturally; compiling sexps to strings is what those libraries are for), but you can't go in the other direction and generate a sexp from a string. re-builder remembers what the sexp was, so you don't lose that form when you change syntax; but it also doesn't get updated if you modify the regexp in a different syntax and then change back. In short, if you're building the regexp as a sexp, make sure you only edit it while using that syntax.


A gotcha with the rx support is that it's actually using the rx-to-string function, which isn't quite identical to using the rx macro in code. rx accepts an arbitrary number of form arguments and treats them as an implied sequence, whereas rx-to-string accepts only a single form, and any top-level sequence must be made explicit with '(sequence ...) or equivalent.

In short, when you enter a form '(...) in re-builder, it is processed as (rx-to-string '(...)) and not (rx ...)

Also take note that an invalid form might cause re-builder to stop dynamically updating the matches in the associated buffer, even after the form is made valid again. The C-cC-u binding for reb-force-update is useful for resolving these situations.


By default the mode line shows "RE Builder" when using read or string syntax, and "RE Builder Lisp" when using rx or sregex syntax, but it seems far more useful to identify the specific syntax in use (especially to differentiate between read and string).

If you install the delight package from GNU ELPA, you can use the following to add a syntax indicator to the mode line.

(let ((name '("Regexp[" (:eval (symbol-name reb-re-syntax)) "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))

This changes the mode name to "Regexp[read]" in read syntax, and likewise for the others.

Or to include a hint for the rx vs rx-to-string gotcha described above, make the mode line say "Regexp[rx-to-string]" when using the rx syntax:

(let ((name '("Regexp["
              (:eval (symbol-name (if (eq reb-re-syntax 'rx)
                                      'rx-to-string
                                    reb-re-syntax)))
              "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))

Your Answer

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

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