Elisp: Region, Active Region

By Xah Lee. Date: . Last updated: .

Here's how to work with {region, active region, transient-mark-mode} in emacs lisp.

What's Mark?

mark → A position the user can set, for the purpose of making a text selection.

Alt+x set-mark-commandCtrl+Space】 to set a mark.

In lisp code, you should call push-mark or set-mark.

What's Region?

region → The last marked position to the current cursor position.

Once a user sets a mark in a buffer, a region exists. So, almost always, there exists a region in a buffer.

You can get the positions of region by the functions {region-beginning, region-end}.

(defun ff ()
  "sample code to show region begin/end positions"
  (interactive)
  (message "begin at %s\nend at %s"
           (region-beginning)
           (region-end)))

By convention, commands ending in the word “-region” acts on the region. For example: • kill-regioncomment-regionfill-regionindent-region.

What's Active Region?

Because a region exists once a user sets a mark, and always having a section of text highlighted to the cursor position is annoying, so there's a new concept of Active Region.

A Region is Active when the variable mark-active is true. (in elisp, nil and () are false, everything else is true. True is represented by t by convention.)

Highlighting of Region: transient-mark-mode

Emacs has a minor mode called transient-mark-mode. When on, it will highlight the region when it's active.

variable transient-mark-mode → when true, transient-mark-mode is on.

transient-mark-mode is introduced in emacs 19 (released in ).

transient-mark-mode is on by default since Emacs 23.1 (released in )

When Should a Region be Active?

Typically, when set-mark-command is called, the region becomes active (highlighted). When a command is called, it typically set the region status to inactive.

This means, when you set mark using the keyboard or the mouse, text selection become highlighted, then after you called some command, the region returns to inactive again (and the highlighting goes away).

What's Text Selection?

Emacs's concept of “active region” is practically the same as the modern term “Text Selection”.

Text Selection = when region is active, and is not empty.

When you want your command to act on a text selection when there is one, check on use-region-p.

(defun my-is-region-active ()
  "print whether region is active."
  (interactive)
  (if (use-region-p)
      (message "region active")
    (message "region not active")))

The function use-region-p basically checks 3 things:

  1. transient-mark-mode is on.
  2. mark-active is true.
  3. region isn't empty by checking use-empty-active-region.

Create Active Region

The following example sets a mark, and activates the region.

(defun my-select-line ()
  "Select current line."
  (interactive)
  (let (p1 p2)
    (setq p1 (line-beginning-position))
    (setq p2 (line-end-position))
    (goto-char p1)
    (push-mark p2)
    (setq mark-active t)))

Note: Emacs commands should not change/modify/activate region, unless you have good reason.

Pass Region Begin/End Positions to Function Arguments

Let your function have 2 parameters, then use (interactive "r"), then the parameters will be filled with begin/end positions of the region.

(defun ff (p1 p2)
  "sample code, print region begin/end positions."
  (interactive "r")
  (message "Region starts: %d, end at: %d" p1 p2))

Get Active Region or Current {Word, Line}

Often you want a command that works on the current word (or line), but if there is a text selection, act on the text selection.

Here's a example of getting current word, or active region.

(defun downcase-word-or-region ()
  "Downcase current word or region."
(interactive)
(let (pos1 pos2 bds)
  (if (use-region-p)
     (setq pos1 (region-beginning) pos2 (region-end))
    (progn
      (setq bds (bounds-of-thing-at-point 'symbol))
      (setq pos1 (car bds) pos2 (cdr bds))))

  ;; now, pos1 and pos2 are the starting and ending positions of the
  ;; current word, or current text selection if exist.
  (downcase-region pos1 pos2)
  ))

〔►see Elisp: Using thing-at-point

Emacs 23 Changes

Starting with Emacs 23 (release in ), transient-mark-mode is on by default, and many command's behavior changed. If there is a text selection, the command acts on it, else it acts on the current word, line, paragraph, buffer (or whatever is its default input).

〔►see Emacs 23.1 New Features (released 2009-07)

Commands with this new behavior includes: {fill-paragraph, ispell-word, indent-for-tab-command, comment-dwim}. The number of commands that are sensitive to existence of text selection will probably increase.

Note that commands ending in “-region” still should act on region as before, regardless of the region activeness status.

This change is good, because users don't need to think about whether he should choose the region or non-region version of the command. The command simply act on a text selection if there is one.

(info "(elisp) The Mark")

Writing Emacs Command

  1. Elisp: How to Write Commands
  2. Elisp: Region, Active Region
  3. Elisp: Get Buffer String
  4. Elisp: Functions on Line
  5. Elisp: Cut Copy Paste to/from kill-ring
  6. Elisp: Get User Input
  7. Elisp: Get universal-argument
  8. Elisp: Find Replace String in Buffer
  9. Elisp: Using thing-at-point
Like it? Buy Xah Emacs Tutorial. Thanks.