Emacs: Select Line, between Quotes, Extend Selection ๐Ÿš€

By Xah Lee. Date: . Last updated: .

Master these text selection commands, and you almost never need to manually mark a region.

Select Text between Quotes/Brackets

Select text inside quotes is one of the most frequently needed operation in programing languages code.

(defun xah-select-text-in-quote ()
  "Select text between the nearest left and right delimiters.
Delimiters here includes the following chars: \"`<>(){}[]โ€œโ€โ€˜โ€™โ€นโ€บยซยปใ€Œใ€ใ€Žใ€ใ€ใ€‘ใ€–ใ€—ใ€Šใ€‹ใ€ˆใ€‰ใ€”ใ€•๏ผˆ๏ผ‰
This command select between any bracket chars, does not consider nesting. For example, if text is
the selected char is โ€œcโ€, not โ€œa(b)cโ€.

URL `http://xahlee.info/emacs/emacs/modernization_mark-word.html'
Version 2020-11-24 2021-07-11"
  (let ( $skipChars $p1 )
    (setq $skipChars "^\"`<>(){}[]โ€œโ€โ€˜โ€™โ€นโ€บยซยปใ€Œใ€ใ€Žใ€ใ€ใ€‘ใ€–ใ€—ใ€Šใ€‹ใ€ˆใ€‰ใ€”ใ€•๏ผˆ๏ผ‰ใ€˜ใ€™")
    (skip-chars-backward $skipChars)
    (setq $p1 (point))
    (skip-chars-forward $skipChars)
    (set-mark $p1)))

Select Current Line

This command selects current line.

If there's already a selection, extend selection downward by line.

(defun xah-select-line ()
  "Select current line. If region is active, extend selection downward by line.
URL `http://xahlee.info/emacs/emacs/modernization_mark-word.html'
Version 2017-11-01"
  (if (region-active-p)
        (forward-line 1)
      (set-mark (line-beginning-position)))))

Select Current Block

This lets you select current block of text. (a block here is text between empty lines.)

If there's already a selection, extend selection downward by block.

(defun xah-select-block ()
  "Select the current/next block of text between blank lines.
If region is active, extend selection downward by block.

URL `http://xahlee.info/emacs/emacs/modernization_mark-word.html'
Version 2019-12-26"
  (if (region-active-p)
      (re-search-forward "\n[ \t]*\n" nil "move")
      (skip-chars-forward " \n\t")
      (when (re-search-backward "\n[ \t]*\n" nil "move")
        (re-search-forward "\n[ \t]*\n"))
      (push-mark (point) t t)
      (re-search-forward "\n[ \t]*\n" nil "move"))))

Extend Selection

Here's a multi-purpose command that select different text depending on where cursor is, and if called repeatedly, extend selection.

This command is currently most useful in lisp code. Or, place cursor on a bracket and select the whole including bracket and text in between. (bracket here includes parenthesis and any type of quotation marks.)

(defun xah-extend-selection ()
  "Select the current word, bracket/quote expression, or expand selection.
Subsequent calls expands the selection.

when there is no selection,
โ€ข if cursor is on a any type of bracket (including parenthesis, quotation mark), select whole bracketed thing including bracket
โ€ข else, select current word.

when there is a selection, the selection extension behavior is still experimental. But when cursor is on a any type of bracket (parenthesis, quote), it extends selection to outer bracket.

URL `http://xahlee.info/emacs/emacs/modernization_mark-word.html'
Version: 2020-02-04 2022-05-16"
  (if (region-active-p)
        (let (($rb (region-beginning)) ($re (region-end)))
          (goto-char $rb)
           ((looking-at "\\s(")
            (if (eq (nth 0 (syntax-ppss)) 0)
                  ;; (message "left bracket, depth 0.")
                  (end-of-line) ; select current line
                  (set-mark (line-beginning-position)))
                ;; (message "left bracket, depth not 0")
                (up-list -1 t t)
           ((eq $rb (line-beginning-position))
              (goto-char $rb)
              (let (($firstLineEndPos (line-end-position)))
                 ((eq $re $firstLineEndPos)
                    ;; (message "exactly 1 line. extend to next whole line." )
                    (forward-line 1)
                 ((< $re $firstLineEndPos)
                    ;; (message "less than 1 line. complete the line." )
                 ((> $re $firstLineEndPos)
                    ;; (message "beginning of line, but end is greater than 1st end of line" )
                    (goto-char $re)
                    (if (eq (point) (line-end-position))
                          ;; (message "exactly multiple lines" )
                          (forward-line 1)
                        ;; (message "multiple lines but end is not eol. make it so" )
                        (goto-char $re)
                 (t (error "%s: logic error 42946" real-this-command ))))))
           ((and (> (point) (line-beginning-position)) (<= (point) (line-end-position)))
              ;; (message "less than 1 line" )
              (end-of-line) ; select current line
              (set-mark (line-beginning-position))))
            ;; (message "last resort" )
       ((looking-at "\\s(")
        ;; (message "left bracket")
        (mark-sexp)) ; left bracket
       ((looking-at "\\s)")
        ;; (message "right bracket")
        (backward-up-list) (mark-sexp))
       ((looking-at "\\s\"")
        ;; (message "string quote")
        (mark-sexp)) ; string quote
       ;; ((and (eq (point) (line-beginning-position)) (not (looking-at "\n")))
       ;;  (message "beginning of line and not empty")
       ;;  (end-of-line)
       ;;  (set-mark (line-beginning-position)))
       ((or (looking-back "\\s_" 1) (looking-back "\\sw" 1))
        ;; (message "left is word or symbol")
        (skip-syntax-backward "_w" )
        ;; (re-search-backward "^\\(\\sw\\|\\s_\\)" nil t)
        (skip-syntax-forward "_w")
        (setq mark-active t)
        ;; (exchange-point-and-mark)
       ((and (looking-at "\\s ") (looking-back "\\s " 1))
        ;; (message "left and right both space" )
        (skip-chars-backward "\\s " ) (set-mark (point))
        (skip-chars-forward "\\s "))
       ((and (looking-at "\n") (looking-back "\n" 1))
        ;; (message "left and right both newline")
        (skip-chars-forward "\n")
        (set-mark (point))
        (re-search-forward "\n[ \t]*\n")) ; between blank lines, select next block
        ;; (message "just mark sexp" )

You should give these commands keys. [see Emacs: How to Define Keys].

I suggest these keybinding:

xah-extend-selection is even more useful together with commands that move cursor to brackets or quotes. [see Emacs: Move Cursor to Bracket ๐Ÿš€]

The above commands are also in ergoemacs-mode [https://ergoemacs.github.io/ ] and xah-fly-keys. [see Emacs: Xah Fly Keys]

Emacs, Work with Brackets

Emacs Modernization

Xah Emacs Commands