Searching in Buffers with Occur Mode

The Emacs M-x occur (also bound to M-s o) command is a useful replacement for GNU grep, when your only requirement is searching open buffers in Emacs. Like grep, the occur command will take a regular expression and print, in a separate buffer, all the lines that match the expression. One really nifty thing about occur is that it will preserve the faces (the colors, or syntax highlighting, if you will) in the displayed matches.

The default command, M-x occur, will only search the active buffer, but its cousins M-x multi-occur and M-x multi-occur-in-matching-buffers will search the buffers you specify, or all buffers that match a given regexp pattern, respectively.

There’s a few helper commands that will make your life easier, such as occur-rename-buffer that renames an *Occur* output buffer so it includes the names of the buffers it searched. Useful if you want to search for different things. This command is also bound to r in the *Occur* buffer itself.

You can also re-run the occur command by pressing g in the output buffer. (Note: this is actually a standard, of sorts, used by most interactive buffers including dired, compile and grep.)

Another useful feature is its support for the compilation mode commands next/previous-error (M-g M-n and M-g M-p respectively), as they enable you to cycle through the list of occur matches from within the source buffer itself.

In a similar vein, you can enable follow mode in the *Occur* buffer by pressing C-c C-f, and future calls to M-n and M-p in the *Occur* buffer will automatically jump to the correct match in the source buffer.

Making Occur a little more useful

My only complaint about occur is that it does not let you quickly search a set of buffers that match a specific major mode – arguably a common use case if you’re a programmer. The code seen below will search all open buffers that share the same mode as the active buffer.

(eval-when-compile
  (require 'cl))

(defun get-buffers-matching-mode (mode)
  "Returns a list of buffers where their major-mode is equal to MODE"
  (let ((buffer-mode-matches '()))
   (dolist (buf (buffer-list))
     (with-current-buffer buf
       (if (eq mode major-mode)
           (add-to-list 'buffer-mode-matches buf))))
   buffer-mode-matches))

(defun multi-occur-in-this-mode ()
  "Show all lines matching REGEXP in buffers with this major mode."
  (interactive)
  (multi-occur
   (get-buffers-matching-mode major-mode)
   (car (occur-read-primary-args))))

;; global key for `multi-occur-in-this-mode' - you should change this.
(global-set-key (kbd "C-<f2>") 'multi-occur-in-this-mode)