I’ve been thinking about Emacs’s regular expressions lately, and how I rarely use them. I tend to reach for keyboard macros first, and only occasionally use query-replace-regexp when I need to do a complex search-and-replace. I use M-x rgrep almost every day, but I rarely pass it regular expressions. I think I would probably use regular expressions more, but I’m much more familiar with the so-called Perl-compatible regular expressions such as those supported by PCRE, and I think the unfamiliar Emacs and POSIX style is a subtle reason why I’ve been avoiding them. So, I decided as an experiment to start teaching Emacs to use grep with the -P option, which is a years-old “experimental” feature available in all the greps I use that enables Perl-style regular expressions. I started with the following settings:
(setq grep-command "grep -nHP -e " grep-find-template "find . <X> -type f <F> -exec grep <C> -nHP -e <R> {} /dev/null \\;")
These are the same as the defaults for me, except with the added ‘P’ flag. With these two settings, M-x grep and M-x rgrep will use Perl-compatible regular expressions. It’s particularly helpful with M-x rgrep, since the regular expression is automatically shell-escaped, so it provides a way to avoid backslash-itis due to the combination of this shell escaping and the more humane (in my opinion) escaping rules that PCRE uses.
I wanted a replacement for M-x occur that would use PCRE as well, so I wrapped M-x grep and taught it to use occur’s conventions, including the optional numeric argument that causes it to include some extra lines of context in the output.
(defun grep-occur (regexp &optional nlines) (interactive (occur-read-primary-args)) (save-some-buffers) (grep (concat grep-command (shell-quote-argument regexp) (if nlines (if (> nlines 0) (format " -C %d " nlines) (format " -B %d " (abs nlines))) " ") (buffer-file-name))))
Since this uses the same grep-command variable, it supports PCRE as well, and I can now show all matches for a PCRE in the current buffer (as long as it is saved to a file first), and jump between them with next-error and previous-error (C-x ` or M-g n / M-g p by default). I added a (save-some-buffers) call to give the option of saving unsaved buffers before running the grep command, similar to how M-x compile works.
I’m just starting to incorporate this into my workflow, but I think it’s pretty neat. I’d love to know of any other places where I can integrate PCRE effectively, if you can think of any.