Emacs: Extend Selection, Select Text in Quote, Select Line, Select Block

Buy Xah Emacs Tutorial. Master emacs benefits for life.
, , …,

This page shows many useful emacs commands for text selection.

Select Text in Quote

This command select just text inside quotes. (it does not deal with nested quotes)

(defun xah-select-text-in-quote ()
  "Select text between the nearest left and right delimiters.
Delimiters here includes the following chars: \"<>(){}[]“”‘’‹›«»「」『』【】〖〗《》〈〉〔〕
This command does not properly deal with nested brackets.
URL `http://ergoemacs.org/emacs/modernization_mark-word.html'
Version 2015-04-02"
  (interactive)
  (let (ξp1
        ξp2
        (ξskipChars "^\"<>(){}[]“”‘’‹›«»「」『』【】〖〗《》〈〉〔〕"))
    (skip-chars-backward ξskipChars)
    (setq ξp1 (point))
    (skip-chars-forward ξskipChars)
    (setq ξp2 (point))
    (set-mark ξp1)))

You should give this command a key. 〔➤ Emacs: How to Define Keys〕.

Select Current Line

A “line” is a frequent semantic unit in source code. Here's a command that select current line by a single operation.

(defun xah-select-current-line ()
  "Select current line.
URL `http://ergoemacs.org/emacs/modernization_mark-word.html'
Version 2015-02-07
"
  (interactive)
  (end-of-line)
  (set-mark (line-beginning-position)))

Select Current Block

select-current-block lets you select current block of text by a single keystroke. (a block here is text between empty lines. It's similar to emacs's “paragraph” concept, except it's not major-mode dependent, so the behavior is predictable anywhere.)

(defun xah-select-current-block ()
  "Select the current block of text between blank lines.
URL `http://ergoemacs.org/emacs/modernization_mark-word.html'
Version 2015-02-07
"
  (interactive)
  (let (p1 p2)
    (progn
      (if (re-search-backward "\n[ \t]*\n" nil "move")
          (progn (re-search-forward "\n[ \t]*\n")
                 (setq p1 (point)))
        (setq p1 (point)))
      (if (re-search-forward "\n[ \t]*\n" nil "move")
          (progn (re-search-backward "\n[ \t]*\n")
                 (setq p2 (point)))
        (setq p2 (point))))
    (set-mark p1)))

extend-selection

Here's the code that implements the above idea for lisp (or any simply nested syntax):

;; by Nikolaj Schumacher, 2008-10-20. Released under GPL.
(defun semnav-up (arg)
  (interactive "p")
  (when (nth 3 (syntax-ppss))
    (if (> arg 0)
        (progn
          (skip-syntax-forward "^\"")
          (goto-char (1+ (point)))
          (decf arg))
      (skip-syntax-backward "^\"")
      (goto-char (1- (point)))
      (incf arg)))
  (up-list arg))

;; by Nikolaj Schumacher, 2008-10-20. Released under GPL.
(defun extend-selection (arg &optional incremental)
  "Select the current word.
Subsequent calls expands the selection to larger semantic unit."
  (interactive (list (prefix-numeric-value current-prefix-arg)
                     (or (use-region-p)
                         (eq last-command this-command))))
  (if incremental
      (progn
        (semnav-up (- arg))
        (forward-sexp)
        (mark-sexp -1))
    (if (> arg 1)
        (extend-selection (1- arg) t)
      (if (looking-at "\\=\\(\\s_\\|\\sw\\)*\\_>")
          (goto-char (match-end 0))
        (unless (memq (char-before) '(?\) ?\"))
          (forward-sexp)))
      (mark-sexp -1))))

(global-set-key (kbd "M-8") 'extend-selection)

I suggest 【Alt+8】 for the command. Pressing it once will select the current whole word. Press it again will extend the selection to the next outer parens.

“extend-selection” does extend selection for lisp or simply nested syntax.

The “extend-selection” can be used to select quoted text. If the quoted text has more than one word, you need to call it twice. “extend-selection” will select including the quote chars.

The above commands are also ErgoEmacs at ErgoEmacs Keybinding.

These commands are most useful together with commands that move cursor to brackets or quotes. 〔➤ Emacs: Commands to Move Cursor by Brackets, Quotes


Replacing Emacs Text Selection Scheme

Emacs has a command to select the current word, mark-word, with default shortcut of 【Alt+@】. Selecting the current word is a frequently needed operation. However, emacs's mark-word command is inconvenient. It does not select the whole word. It only select from the cursor position to the end of the word. For example, if your word is “transmission”, and your cursor is at the “m”, then it will select just “mission”. To select the whole word, you need to move the cursor to the beginning of the word first.

Also, mark-word has a feature that if you repeat the command, then it extend the selection to the next word to the right. But again, you need first to move the cursor to the start position you want. Emacs has in fact a whole system of selecting text:

“M-@”
     Set mark after end of next word (“mark-word”).  This command and
     the following one do not move point.

“C-M-@”
     Set mark after end of following balanced expression (“mark-sexp”).

“M-h”
     Put region around current paragraph (“mark-paragraph”).

“C-M-h”
     Put region around current defun (“mark-defun”).

“C-x h”
     Put region around the entire buffer (“mark-whole-buffer”).

“C-x C-p”
     Put region around current page (“mark-page”).

(info "(emacs) Marking Objects")

Here is suggestion of a scheme that may replace or supplement the above system.

We create a command that select the whole word. When repeated, it should select the next larger syntactic unit. In human languages, that would be sentence, then paragraph, then whole buffer. In computer languages, the sequence would be: current identifier or token, current expression, current construct (or line), current block or defun. If the language is lisp, this simply means extending the selection to the next outer parens. For a illustrated example of this, see: A Text Editor Feature: Extend Selection By Semantic Unit.

This extend-selection scheme with transient-mark-mode on, should simplify and replace the functionality of {mark-word, mark-sexp, mark-paragraph, mark-defun}. With just one command to remember, and more efficient to operate. The mark-whole-buffer can be replaced by a shortcut 【Ctrl+a】 to be compatible with modern UI standard, and mark-page is today rather obsolete because it depends on page marker char “^L” (ASCII 12), which is not used in most languages but only in older emacs lisp source code.

Like it?
Buy Xah Emacs Tutorial
or share
blog comments powered by Disqus