Emacs: Extend Selection 📜
Here's a command that select different textual unit depending on where cursor is, and if called repeatedly, extend selection.
If cursor is on a left bracket, it selects the whole bracketed text including the bracket. (bracket here includes parenthesis and any type of quotation marks.)
This command is currently most useful when working with lisp code.
more useful when combined with Emacs: Move Cursor to Bracket 📜
(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 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. After this command is called, press `xah-repeat-key' to repeat it. URL `http://xahlee.info/emacs/emacs/emacs_extend_selection.html' Created: 2020-02-04 Version: 2025-09-04" (interactive) (cond ((region-active-p) (let ((xbeg (region-beginning)) (xend (region-end))) (goto-char xbeg) (cond ((looking-at "\\s(") (if (eq (nth 0 (syntax-ppss)) 0) (progn (message "%s debug: left bracket, depth 0." real-this-command) (end-of-line) ; select current line (push-mark (line-beginning-position) t t)) (progn (message "%s debug: left bracket, depth not 0" real-this-command) (up-list -1 t t) (mark-sexp) (exchange-point-and-mark)))) ((eq xbeg (line-beginning-position)) (progn (goto-char xbeg) (let ((xfirstLineEndPos (line-end-position))) (cond ((eq xend xfirstLineEndPos) (progn (message "%s debug: exactly 1 line. extend to next whole line." real-this-command) (forward-line 1) (end-of-line))) ((< xend xfirstLineEndPos) (progn (message "%s debug: less than 1 line. complete the line." real-this-command) (end-of-line))) ((> xend xfirstLineEndPos) (progn (message "%s debug: beginning of line, but end is greater than 1st end of line" real-this-command) (goto-char xend) (if (eq (point) (line-end-position)) (progn (message "%s debug: exactly multiple lines" real-this-command) (forward-line 1) (end-of-line)) (progn (message "%s debug: multiple lines but end is not eol. make it so" real-this-command) (goto-char xend) (end-of-line))))) (t (error "%s: logic error 42946" real-this-command)))))) ((and (> (point) (line-beginning-position)) (<= (point) (line-end-position))) (progn (message "%s debug: less than 1 line" real-this-command) (end-of-line) ; select current line (push-mark (line-beginning-position) t t))) (t (message "%s debug: last resort" real-this-command) nil)))) ((looking-at "\\s(") (message "%s debug: left bracket" real-this-command) (mark-sexp) (exchange-point-and-mark)) ((looking-at "\\s)") (message "%s debug: right bracket" real-this-command) (backward-up-list) (mark-sexp) (exchange-point-and-mark)) ((looking-at "\\s\"") (message "%s debug: string quote" real-this-command) (mark-sexp) (exchange-point-and-mark)) ((looking-at "[ \t\n]") (message "%s debug: is white space" real-this-command) ;; (skip-chars-backward " \t\n") (push-mark) (skip-chars-forward " \t\n") (setq mark-active t)) ((looking-at "[-_a-zA-Z0-9]") (message "%s debug: right is word or symbol" real-this-command) (skip-chars-backward "-_a-zA-Z0-9") (push-mark) (skip-chars-forward "-_a-zA-Z0-9") (setq mark-active t)) ;; ((and (looking-at "[[:blank:]]") ;; (prog2 (backward-char) (looking-at "[[:blank:]]") (forward-char))) ;; ;; (message "%s debug: left and right both space" real-this-command) ;; (skip-chars-backward "[[:blank:]]") (push-mark (point) t t) ;; (skip-chars-forward "[[:blank:]]")) ((and (looking-at "\n") (eq (char-before) 10)) (message "%s debug: left and right both newline" real-this-command) (skip-chars-forward "\n") (push-mark (point) t t) (re-search-forward "\n[ \t]*\n")) (t (message "%s debug: no condition met. just select 1 char" real-this-command) (push-mark (point) t t) (forward-char))) (set-transient-map (let ((xkmap (make-sparse-keymap))) (define-key xkmap (kbd (if (boundp 'xah-repeat-key) xah-repeat-key "RET")) real-this-command) xkmap)))