rx

A nifty macro that generates regular expressions for you, from reasonably-comprehensible s-expressions. Inspired by something similar in Olin Shivers’ “scsh”. Use decribe-function found by pressing C-h f then enter rx to find the full documentation with all usable keywords.

Example:

(rx bol
  (zero-or-more blank)
  (one-or-more digit)
  ":")

yields

""^[[:blank:]]*[[:digit:]]+:""

When given just a single string argument, it acts just like regexp-to-string.

Here is one way in which to temporarily extend the keywords used by rx for specific purposes:

 (defmacro rx-extra (&rest body-forms)
   (let ((add-ins (list
                   `(file . ,(rx (+ (or alnum digit "." "/" "-" "_"))))
                   `(ws0 . ,(rx (0+ (any " " "\t"))))
                   `(ws+ . ,(rx (+ (any " " "\t"))))
                   `(int . ,(rx (+ digit))))))
     `(let ((rx-constituents (append ',add-ins rx-constituents nil)))
        ,@body-forms)))

For the newer version, use:

(defmacro rx-extra (&rest body-forms)
  `(rx-let ((file (+ (or alnum digit "." "/" "-" "_")))
            (ws0 (0+ (any " " "\t")))
            (ws+ (+ (any " " "\t")))
            (int (+ digit)))
     ,@body-forms))

Example of using the above rx-extra macro:

 
 (let ((string " at Isrc/file-23_2.c line 23 ;: flubber"))
   (if (string-match (rx-extra
                      (rx ws+ "at" ws+ (group file) ws+ "line" ws+ (group int))) string)
       (format "file is %s line is %s"
               (match-string-no-properties 1 string)
               (match-string-no-properties 2 string))))

This returns: “file is Isrc/file-23_2.c line is 23”

So the idea behind rx-extra is that you can add new named regular expressions to be used cleanly in other rx forms.


CategoryRegexp