Emacs: Insert Brackets by Pair
This page shows a command
xah-insert-bracket-pair
to insert bracket pair, better than the emacs builtin
electric-pair-mode
.
Emacs has
electric-pair-mode
, which insert a bracket pair when you type the left bracket.
[see Emacs: Auto Close Brackets, electric-pair-mode]
Problems of electric-pair-mode
- It does not close { } when in
emacs-lisp-mode
(as of 2017-10-09, GNU Emacs 25.3.1). Which brackets it will close depends on the major mode you are in. - The keys to insert brackets, are still the keys on PC keyboard, which are typed by your stretched pinky.
Advantages of xah-insert-bracket-pair
- Wrap brackets around current word (if cursor is on a word), or text selection, else just insert a pair and place cursor in between.
- Behavior is same and predictable anywhere.
- Convient shortcuts keys on homerow, or any key you chose.
- Inserts 10 other Unicode brackets and quotes.
Bracket Pair Insertion Commands
Put this in your Emacs Init File:
(defun xah-insert-bracket-pair (@left-bracket @right-bracket &optional @wrap-method) "Insert brackets around selection, word, at point, and maybe move cursor in between. *left-bracket and *right-bracket are strings. *wrap-method must be either 'line or 'block. 'block means between empty lines. • if there's a region, add brackets around region. • If *wrap-method is 'line, wrap around line. • If *wrap-method is 'block, wrap around block. • if cursor is at beginning of line and its not empty line and contain at least 1 space, wrap around the line. • If cursor is at end of a word or buffer, one of the following will happen: xyz▮ → xyz(▮) xyz▮ → (xyz▮) if in one of the lisp modes. • wrap brackets around word if any. e.g. xy▮z → (xyz▮). Or just (▮) URL `http://xahlee.info/emacs/emacs/elisp_insert_brackets_by_pair.html' Version 2017-01-17" (if (use-region-p) (progn ; there's active region (let ( ($p1 (region-beginning)) ($p2 (region-end))) (goto-char $p2) (insert @right-bracket) (goto-char $p1) (insert @left-bracket) (goto-char (+ $p2 2)))) (progn ; no text selection (let ($p1 $p2) (cond ((eq @wrap-method 'line) (setq $p1 (line-beginning-position) $p2 (line-end-position)) (goto-char $p2) (insert @right-bracket) (goto-char $p1) (insert @left-bracket) (goto-char (+ $p2 (length @left-bracket)))) ((eq @wrap-method 'block) (save-excursion (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)))) (goto-char $p2) (insert @right-bracket) (goto-char $p1) (insert @left-bracket) (goto-char (+ $p2 (length @left-bracket))))) ( ; do line. line must contain space (and (eq (point) (line-beginning-position)) ;; (string-match " " (buffer-substring-no-properties (line-beginning-position) (line-end-position))) (not (eq (line-beginning-position) (line-end-position)))) (insert @left-bracket ) (end-of-line) (insert @right-bracket)) ((and (or ; cursor is at end of word or buffer. i.e. xyz▮ (looking-at "[^-_[:alnum:]]") (eq (point) (point-max))) (not (or (string-equal major-mode "xah-elisp-mode") (string-equal major-mode "emacs-lisp-mode") (string-equal major-mode "lisp-mode") (string-equal major-mode "lisp-interaction-mode") (string-equal major-mode "common-lisp-mode") (string-equal major-mode "clojure-mode") (string-equal major-mode "xah-clojure-mode") (string-equal major-mode "scheme-mode")))) (progn (setq $p1 (point) $p2 (point)) (insert @left-bracket @right-bracket) (search-backward @right-bracket ))) (t (progn ;; wrap around “word”. basically, want all alphanumeric, plus hyphen and underscore, but don't want space or punctuations. Also want chinese chars ;; 我有一帘幽梦,不知与谁能共。多少秘密在其中,欲诉无人能懂。 (skip-chars-backward "-_[:alnum:]") (setq $p1 (point)) (skip-chars-forward "-_[:alnum:]") (setq $p2 (point)) (goto-char $p2) (insert @right-bracket) (goto-char $p1) (insert @left-bracket) (goto-char (+ $p2 (length @left-bracket))))))))))
Now we define the commands:
(defun xah-insert-paren () (interactive) (xah-insert-bracket-pair "(" ")") ) (defun xah-insert-bracket () (interactive) (xah-insert-bracket-pair "[" "]") ) (defun xah-insert-brace () (interactive) (xah-insert-bracket-pair "{" "}") )
Here's more for Unicode Brackets (very useful if you write a lot structured text.)
(defun xah-insert-double-curly-quote () (interactive) (xah-insert-bracket-pair "“" "”") ) (defun xah-insert-curly-single-quote () (interactive) (xah-insert-bracket-pair "‘" "’") ) (defun xah-insert-single-angle-quote () (interactive) (xah-insert-bracket-pair "‹" "›") ) (defun xah-insert-double-angle-quote () (interactive) (xah-insert-bracket-pair "«" "»") ) (defun xah-insert-ascii-double-quote () (interactive) (xah-insert-bracket-pair "\"" "\"") ) (defun xah-insert-ascii-single-quote () (interactive) (xah-insert-bracket-pair "'" "'") ) (defun xah-insert-emacs-quote () (interactive) (xah-insert-bracket-pair "`" "'") ) (defun xah-insert-corner-bracket () (interactive) (xah-insert-bracket-pair "「" "」") ) (defun xah-insert-white-corner-bracket () (interactive) (xah-insert-bracket-pair "『" "』") ) (defun xah-insert-angle-bracket () (interactive) (xah-insert-bracket-pair "〈" "〉") ) (defun xah-insert-double-angle-bracket () (interactive) (xah-insert-bracket-pair "《" "》") ) (defun xah-insert-white-lenticular-bracket () (interactive) (xah-insert-bracket-pair "〖" "〗") ) (defun xah-insert-black-lenticular-bracket () (interactive) (xah-insert-bracket-pair "【" "】") ) (defun xah-insert-tortoise-shell-bracket () (interactive) (xah-insert-bracket-pair "〔" "〕") )
[see Unicode: Brackets, Quotes «»「」【】《》]
Setting Up Keys
Now you can set any key to call your commands.
(global-set-key (kbd "<f8> 7") 'xah-insert-brace) ; {} (global-set-key (kbd "<f8> 8") 'xah-insert-paren) ; () (global-set-key (kbd "<f8> 9") 'xah-insert-bracket) ; []
or
(global-set-key (kbd "M-7") 'xah-insert-brace) ; {} (global-set-key (kbd "M-8") 'xah-insert-paren) ; () (global-set-key (kbd "M-9") 'xah-insert-bracket) ; []