Elisp: Mark, 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, Active Region?

mark

A position in buffer that user can set, for the purpose of marking the start point of 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}.

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

active region (text selection)
  • Active Region is basically the same concept as text selection.
  • Active Region is a boolean status, indicating if current region is “active”.
  • Many commands automatically work on active region as input.
  • Active Region is highlighted if Transient Mark Mode is on.

elisp function or variable related to active region are:

  • region-active-p
  • use-region-p
  • deactivate-mark
  • mark-active

Functions for Mark and Region

region-beginning

Return the region beginning position.

(defun ff ()
  "sample code to show region begin/end positions"
  (interactive)
  (message "begin at %s\nend at %s"
           (region-beginning)
           (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 position to mark-ring

mark-ring

Variable. A list of marked positions of the current buffer, most recent first.

region-active-p

return true if region is active.

deactivate-mark

Buffer Local Variable. If true, editing commands will deactivate the mark when the command is done.

(defun xx ()
  "sample code, a command that don't deactivate the mark when it is done."
  (interactive)
  (let ((deactivate-mark nil)
        (message "xx done"))))
deactivate-mark

(deactivate-mark &optional FORCE)

Deactivate the mark.

If Transient Mark Mode is disabled, this function normally does nothing; but if FORCE is true, it deactivates the mark.

When is a Region Active?

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

Example: Create a Text Selection

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

💡 TIP: 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.

Example: Check If Region is Active

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.

Example: Get Text Selection or Current Word

Often you want a command that automatically act on a text unit such as current word, 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 Elisp: thing-at-point

Reference

Elisp, mark, region

Elisp, text processing functions