27

Say, I have some code like this:

(defun some-function ()
  (interactive)
  ;; do something
  )

Now I want some-function to operate only on the selected region in the buffer ? How can I do that ? Also, can there be two separate code path for doing something if I have selected some region and doing something else If I haven't selected.

1 Answer 1

36
(defun some-function (beginning end)
  (interactive "r")
  (if (use-region-p)
      (message "The region is active, and is from %d to %d" beginning end)
    (message "The region is still there (from % d to %d), but it is inactive" 
             beginning end)))

The use of (interactive "r") means that the parameters beginning and end will automatically receive the values of the region beginning and the region end, respectively, when the function is invoked. (You can also get those values anytime using the functions region-beginning and region-end, respectively.)

The region is always present (if there is a mark in the current buffer), but you might not think it is. The region is active when it is highlighted (text is selected). You can test whether the region is active using predicate region-active-p. But the better test is usually use-region-p, because (by default) it returns true (non-nil) only when the region is both active and nonempty (point and mark are different).

Originally, there was no highlighting of the region. And for a long time, even though highlighting was available, it was not the default behavior. For highlighting to occur, you must have transient-mark-mode turned on (or turned on at least temporarily). By default, transient-mark-mode is turned on in recent Emacs versions.

It's helpful to look at the definition of predicate use-region-p:

(defun use-region-p ()
  (and (region-active-p)
       (or use-empty-active-region
           (> (region-end) (region-beginning)))))

use-empty-active-region is a user option, whose default value is nil (false), meaning that by default use-region-p will not return true if the region is empty. In that case, for it to return true, the end of the region must be greater than the beginning (the behavior I described above).

And if we look at the definition of region-active-p:

(defun region-active-p ()
  (and transient-mark-mode
       mark-active
       (mark)))

We see that it returns true (non-nil) when all of these are true:

  • transient-mark-mode is turned on.
  • The mark is active (mark-active).
  • There is a mark in the current buffer.

The mark being active is really what the region being active is all about. When it is active, assuming that transient-mark-mode is on and there is a mark in the current buffer, the region is highlighted.

5
  • AFAICS if mark is set to point, i.e. region has not extend, mark-active is nil. So mark-active and transient-mark-mode are the only things adding value in these fairly redundant functions. May 12, 2015 at 12:32
  • 1
    @AndreasRöhler: Nope. C-SPC M-: mark-active => t. You can definitely have an empty region that is nevertheless active.
    – Drew
    May 12, 2015 at 13:41
  • Okay, thanks. Still think mark-active and region-active-p --defined as extend greater zero-- should be all needed. May 12, 2015 at 15:26
  • @Drew, I believe there's a typo in: ", whose default value is nil (true)," . It should probably read ",whose default is nil (false)" or something like that since non-nil corresponds to true.
    – PRouleau
    Jan 2 at 22:19
  • @PRouleau: Good catch; thx. (Yup, nil means false.) Fixed.
    – Drew
    Jan 2 at 22:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.