region-or-buffer
(revisited)
In Writing Emacs Commands That Work on Regions or the Entire Buffer I
blogged about an Emacs macro (with-region-or-buffer
) that I use to
allow my Emacs commands to work on the current region if one exists or
the entire buffer if not. I've been using that macro for some time
now and it works perfectly for me. It probably works perfectly for
almost everyone but there is an edge case: It implicitly assumes that
transient-mark-mode
is set. I've always set it explicitly in my
.emacs
file and as of Emacs 23 it's on by default. There are
occasions, however, when one might want to have it off (see Fixing the Mark Commands in Transient Mark Mode for some examples and work
arounds in the Mastering Emacs blog).
This came to my attention while I was browsing in Xah Lee's excellent
Emacs Blog. He recommends using the function region-active-p
, which
is merely (and transient-mark-mode mark-active)
. That takes care of
the edge case and for the sake of portability I decided to update
with-region-or-buffer
to use it. In the process of doing that
update, however, I discovered that the recommended solution is to use
use-region-p
, which asks the additional question of whether the
region is empty and use-empty-active-region
is nil. Since there's
no point in acting on an empty region, using this predicate will cause
the action to be applied to the whole buffer instead.
With this in mind, the with-region-or-buffer
macro is now
(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. This macro replaces similar code using (interactive \"r\"), which can fail when there is no mark set. \(fn (BEG END) BODY...)" `(let ((,(car args) (if (use-region-p) (region-beginning) (point-min))) (,(cadr args) (if (use-region-p) (region-end) (point-max)))) ,@body))
No comments:
Post a Comment