Specifying Indent Rules for Emacs Lisp

Eric J.M. Ritz has an excellent post on indenting Elisp code. Say what? Isn’t that what Emacs is for? Yes but there’s a corner case when you’re writing macros.

Here’s a macro that I use to make my Elisp code work on a region if one’s defined or on the whole buffer if not.

(defmacro with-region-or-buffer (args &rest body)
  "Execute BODY with BEG and END bound to the beginning and end of the
current region if one exists or the current buffer if not."
  `(let ((,(car args) (if (use-region-p) (region-beginning) (point-min)))
         (,(cadr args) (if (use-region-p) (region-end) (point-max))))
     ,@body))

As it stands, a call to that macro would get formatted as

(with-region-or-buffer (start end)
                       (blah start end)
                       (more blahs start end))

but that’s not what we want. We’d like it to get formatted as

(with-region-or-buffer (start end)
  (blah start end)
  (more blahs start end))

The easy way to get Emacs to indent it properly is with the declare declaration as shown in the slightly revised version of with-region-or-buffer shown below.

(defmacro with-region-or-buffer (args &rest body)
  "Execute BODY with BEG and END bound to the beginning and end of the
current region if one exists or the current buffer if not."
  (declare (indent 1))
  `(let ((,(car args) (if (use-region-p) (region-beginning) (point-min)))
         (,(cadr args) (if (use-region-p) (region-end) (point-max))))
     ,@body))

It’s really hard to find the documentation for this (at least I always find it hard) so I’m glad to have Ritz’s post for bookmarking purposes. The post has a link to the documentation for declare so you can see what other arguments to the indent declaration are possible.

Update: what’s → what

This entry was posted in Programming and tagged , . Bookmark the permalink.