Using Perl-compatible regular expressions in Emacs

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.

Teaching Magit new tricks

If you’re using Magit 1.0 or newer to work with Git from Emacs, you have probably noticed that when you press keys it now shows a little menu where you can enable flags and pass options. It’s easy to add more. Here’s how I teach Magit about “push -u”, which I use to push local branches to a remote repository and configure them to track the remote branch automatically:

(eval-after-load 'magit
  '(magit-key-mode-insert-switch 'pushing "-u" "Set upstream" "-u"))

You can find all the groups of switches and arguments by typing C-h v magit-key-mode-groups