Emacs Lisp: Region, Active Region

By Xah Lee. Date: . Last updated: .

Here's how to work with region, active region, in emacs lisp.

What is Mark, Region?

mark
A position in buffer that user can set, for the purpose of making a text selection, or jump to a position later.
Alt+x set-mark-commandCtrl+Space】 to set a mark.
In lisp code, you should call push-mark or set-mark.
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}.
region-beginning
(region-beginning)
Return the region beginning position.
region-end
(region-end)
Return the region end position.
push-mark
(push-mark &optional LOCATION NOMSG ACTIVATE)
Set mark at LOCATION (cursor position by default) and push old mark on mark ring.
(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. Example: kill-region, comment-region, fill-region, indent-region .

What is 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.

Check Active Region Status or Set it

mark-active
When the value is true (t), it means the region is active. Set it to t/nil to make the region active/inactive.

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.

transient-mark-mode
Minor mode. Highlight active region. It is introduced in emacs 19 (released in ). It is on by default since Emacs 23.1 [see Emacs 23.1 Features (released 2009-07)]
transient-mark-mode
Variable. When true, transient-mark-mode is on.

When is a Region Active?

Typically, when set-mark-command is called, the region becomes active. And any other command typically set the region status to inactive after it is called.

What is 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 a 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 it's the part of the purpose of the command. Because, it's confusing to user when a command changes text selection or mark.

Get Active Region or Current {Word, Line, Text Block, File Path, Buffer, etc}

Often you want a command that automatically act on a text unit such as current {word, line, text block, file path, buffer, etc}, when there is no text selection, and use text selection if there is one.

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)
  ))

For detail on other text unit, see Emacs Lisp: Using thing-at-point

Emacs 23 Changes

Starting with Emacs 23 (released 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 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 which of the region or non-region command to call.

(info "(elisp) The Mark")


Practical Elisp ⭐

Writing Command

Text Processing

Get User Input

File/Buffer

Writing Script