Neat behavior of M-x occur

Having used Emacs for several years now, I somehow hadn’t come across the prefix argument and active region behavior for one of the most well-known commands: occur.

Below is the docstring of occur reads, with the relevant portions preserved:

occur is an interactive native-comp-function in replace.el.

It is bound to M-s o.

(occur REGEXP &optional NLINES REGION)

Inferred type: (function (t &optional t t) t)

Show all lines in the current buffer containing a match for REGEXP.
If a match spreads across multiple lines, all those lines are shown.

[…]

Each line is displayed with NLINES lines before and after, or -NLINES
before if NLINES is negative.
NLINES defaults to list-matching-lines-default-context-lines.
Interactively it is the prefix arg.

Optional arg REGION, if non-nil, mean restrict search to the
specified region. Otherwise search the entire buffer.*
*REGION must be a list of (START . END) positions as returned by
region-bounds.

[…]

When NLINES is a string or when the function is called
interactively with prefix argument without a number (C-u alone
as prefix) the matching strings are collected into the ‘*Occur*’
buffer by using NLINES as a replacement regexp. NLINES may
contain \& and \N which convention follows replace-match.
For example, providing “defun\s +\(\S +\)” for REGEXP and
“\1” for NLINES collects all the function names in a lisp
program. When there is no parenthesized subexpressions in REGEXP
the entire match is collected. In any case the searched buffer
is not modified.

[…]

So:

  1. When called on a region, on that region is searched.
  2. When called with a numerical prefix argument, that many lines before and after every match is added to the search results. (This reminds me of next-screen-context-lines.) This functionality is particularly useful to me since added context is sometimes necessary.1
  3. When called with a universal argument, just the matching string (not the entire line) is inserted into a line in a read-only buffer.
  4. If called from elisp and NLINES is provided (as a regexp string), then the behavior is like C-u but matches can be modified like replace-match. (See (elisp) Replacing Match for more information.)

Also, searching “NLINES” with apropos-documentation brings up a few other built-in commands that have similar functionality. isearch-occur, multi-occur, list-matching-lines, and occur-context-lines to name a few.

Pretty neat!

Further Reading


  1. I sometimes use occur-edit-mode (bound to e in occur-mode buffers), and the added context lines can be relevant to the edits I want to make to the matched text. ↩︎