diff options
| author | Elías Gabriel Pérez | 2025-04-24 17:34:58 -0600 |
|---|---|---|
| committer | Eli Zaretskii | 2025-06-21 12:24:55 +0300 |
| commit | 60fbeda771639ded68ffd0666df340c7a06cafcf (patch) | |
| tree | 9b11ccee5a6bbba5e51eb0b23b5b0dbff300d6f6 | |
| parent | e379f14193982ef500d8806386e26155ff780290 (diff) | |
| download | emacs-60fbeda771639ded68ffd0666df340c7a06cafcf.tar.gz emacs-60fbeda771639ded68ffd0666df340c7a06cafcf.zip | |
Support strings for electric pairs (bug#78053)
This add support for insert string pairs in 'electric-pairs-mode'.
* lisp/elec-pair.el (electric-pair-pairs)
(electric-pair-text-pairs): Add new defcustom types.
(electric-pair-syntax-info)
(electric-pair-post-self-insert-function): Add support for
strings.
* etc/NEWS: Announce changes.
* test/lisp/electric-tests.el: Add new tests.
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/elec-pair.el | 80 | ||||
| -rw-r--r-- | test/lisp/electric-tests.el | 27 |
3 files changed, 113 insertions, 4 deletions
| @@ -563,6 +563,16 @@ You can now insert or wrap text with multiple sets of parentheses and | |||
| 563 | other matching delimiters at once with Electric Pair mode, by providing | 563 | other matching delimiters at once with Electric Pair mode, by providing |
| 564 | a prefix argument when inserting one of the delimiters. | 564 | a prefix argument when inserting one of the delimiters. |
| 565 | 565 | ||
| 566 | --- | ||
| 567 | ** Electric pair mode now supports multi-character paired delimiters. | ||
| 568 | 'electric-pair-pairs' and 'electric-pair-text-pairs' now allows using | ||
| 569 | strings for multi-character paired delimiters. | ||
| 570 | |||
| 571 | To use this add a list to both electric pair variables: ("/*" . "*/"). | ||
| 572 | |||
| 573 | You can also specify to insert an extra space after the first string | ||
| 574 | pair: ("/*" " */" t). | ||
| 575 | |||
| 566 | +++ | 576 | +++ |
| 567 | ** You can now use 'M-~' during 'C-x s' ('save-some-buffers'). | 577 | ** You can now use 'M-~' during 'C-x s' ('save-some-buffers'). |
| 568 | Typing 'M-~' while saving some buffers means not to save the buffer and | 578 | Typing 'M-~' while saving some buffers means not to save the buffer and |
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 3173160370e..7c32e2521c5 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el | |||
| @@ -43,10 +43,34 @@ Pairs of delimiters in this list are a fallback in case they have | |||
| 43 | no syntax relevant to `electric-pair-mode' in the mode's syntax | 43 | no syntax relevant to `electric-pair-mode' in the mode's syntax |
| 44 | table. | 44 | table. |
| 45 | 45 | ||
| 46 | Each list element should be in one of these forms: | ||
| 47 | (CHAR . CHAR) | ||
| 48 | Where CHAR is character to be used as pair. | ||
| 49 | |||
| 50 | (STRING STRING SPC) | ||
| 51 | Where STRING is a string to be used as pair and SPC a non-nil value | ||
| 52 | which specifies to insert an extra space after first STRING. | ||
| 53 | |||
| 54 | (STRING . STRING) | ||
| 55 | This is similar to (STRING STRING SPC) form, except that SPC (space) is | ||
| 56 | ignored and will not be inserted. | ||
| 57 | |||
| 58 | In both string pairs forms, the first string pair must be a regular | ||
| 59 | expression. | ||
| 60 | |||
| 61 | In comparation to character pairs, string pairs does not support | ||
| 62 | inserting pairs in regions and can not be deleted with | ||
| 63 | `electric-pair-delete-pair', thus string pairs should be used only for | ||
| 64 | multi-character pairs. | ||
| 65 | |||
| 46 | See also the variable `electric-pair-text-pairs'." | 66 | See also the variable `electric-pair-text-pairs'." |
| 47 | :version "24.1" | 67 | :version "24.1" |
| 48 | :group 'electricity | 68 | :group 'electricity |
| 49 | :type '(repeat (cons character character))) | 69 | :type '(repeat |
| 70 | (choice (cons :tag "Characters" character character) | ||
| 71 | (cons :tag "Strings" string string) | ||
| 72 | (list :tag "Strings, plus insert SPC after first string" | ||
| 73 | string string boolean)))) | ||
| 50 | 74 | ||
| 51 | (defcustom electric-pair-text-pairs | 75 | (defcustom electric-pair-text-pairs |
| 52 | `((?\" . ?\") | 76 | `((?\" . ?\") |
| @@ -56,10 +80,36 @@ See also the variable `electric-pair-text-pairs'." | |||
| 56 | 80 | ||
| 57 | Pairs of delimiters in this list are a fallback in case they have | 81 | Pairs of delimiters in this list are a fallback in case they have |
| 58 | no syntax relevant to `electric-pair-mode' in the syntax table | 82 | no syntax relevant to `electric-pair-mode' in the syntax table |
| 59 | defined in `electric-pair-text-syntax-table'." | 83 | defined in `electric-pair-text-syntax-table'. |
| 84 | |||
| 85 | Each list element should be in one of these forms: | ||
| 86 | (CHAR . CHAR) | ||
| 87 | Where CHAR is character to be used as pair. | ||
| 88 | |||
| 89 | (STRING STRING SPC) | ||
| 90 | Where STRING is a string to be used as pair and SPC a non-nil value | ||
| 91 | which specifies to insert an extra space after first STRING. | ||
| 92 | |||
| 93 | (STRING . STRING) | ||
| 94 | This is similar to (STRING STRING SPC) form, except that SPC (space) is | ||
| 95 | ignored and will not be inserted. | ||
| 96 | |||
| 97 | In both string pairs forms, the first string pair must be a regular | ||
| 98 | expression. | ||
| 99 | |||
| 100 | In comparation to character pairs, string pairs does not support | ||
| 101 | inserting pairs in regions and can not be deleted with | ||
| 102 | `electric-pair-delete-pair', thus string pairs should be used only for | ||
| 103 | multi-character pairs. | ||
| 104 | |||
| 105 | See also the variable `electric-pair-pairs'." | ||
| 60 | :version "24.4" | 106 | :version "24.4" |
| 61 | :group 'electricity | 107 | :group 'electricity |
| 62 | :type '(repeat (cons character character))) | 108 | :type '(repeat |
| 109 | (choice (cons :tag "Characters" character character) | ||
| 110 | (cons :tag "Strings" string string) | ||
| 111 | (list :tag "Strings, plus insert SPC after first string" | ||
| 112 | string string boolean)))) | ||
| 63 | 113 | ||
| 64 | (defcustom electric-pair-skip-self #'electric-pair-default-skip-self | 114 | (defcustom electric-pair-skip-self #'electric-pair-default-skip-self |
| 65 | "If non-nil, skip char instead of inserting a second closing paren. | 115 | "If non-nil, skip char instead of inserting a second closing paren. |
| @@ -276,6 +326,22 @@ string." | |||
| 276 | (direct (assq command-event fallback)) | 326 | (direct (assq command-event fallback)) |
| 277 | (reverse (rassq command-event fallback))) | 327 | (reverse (rassq command-event fallback))) |
| 278 | (cond | 328 | (cond |
| 329 | ((cl-loop | ||
| 330 | for pairs in fallback | ||
| 331 | if (and | ||
| 332 | (stringp (car pairs)) | ||
| 333 | (looking-back (car pairs) (pos-bol))) | ||
| 334 | return (list | ||
| 335 | 'str | ||
| 336 | ;; Get pair ender | ||
| 337 | (if (proper-list-p pairs) | ||
| 338 | (nth 1 pairs) | ||
| 339 | (cdr pairs)) | ||
| 340 | nil | ||
| 341 | ;; Check if pairs have to insert a space after | ||
| 342 | ;; first pair was inserted. | ||
| 343 | (if (proper-list-p pairs) | ||
| 344 | (nth 2 pairs))))) | ||
| 279 | ((memq (car table-syntax-and-pair) | 345 | ((memq (car table-syntax-and-pair) |
| 280 | '(?\" ?\( ?\) ?\$)) | 346 | '(?\" ?\( ?\) ?\$)) |
| 281 | (append table-syntax-and-pair (list nil string-or-comment))) | 347 | (append table-syntax-and-pair (list nil string-or-comment))) |
| @@ -560,7 +626,7 @@ The decision is taken by order of preference: | |||
| 560 | (beg (when num (- pos num))) | 626 | (beg (when num (- pos num))) |
| 561 | (skip-whitespace-info)) | 627 | (skip-whitespace-info)) |
| 562 | (pcase (electric-pair-syntax-info last-command-event) | 628 | (pcase (electric-pair-syntax-info last-command-event) |
| 563 | (`(,syntax ,pair ,unconditional ,_) | 629 | (`(,syntax ,pair ,unconditional ,space) |
| 564 | (cond | 630 | (cond |
| 565 | ((null pos) nil) | 631 | ((null pos) nil) |
| 566 | ((zerop num) nil) | 632 | ((zerop num) nil) |
| @@ -622,6 +688,12 @@ The decision is taken by order of preference: | |||
| 622 | pos)) | 688 | pos)) |
| 623 | (forward-char num)) | 689 | (forward-char num)) |
| 624 | ;; Insert matching pair. | 690 | ;; Insert matching pair. |
| 691 | ;; String pairs | ||
| 692 | ((and (eq syntax 'str) (not overwrite-mode)) | ||
| 693 | (if space (insert " ")) | ||
| 694 | (save-excursion | ||
| 695 | (insert pair))) | ||
| 696 | ;; Char pairs | ||
| 625 | ((and (memq syntax '(?\( ?\" ?\$)) | 697 | ((and (memq syntax '(?\( ?\" ?\$)) |
| 626 | (not overwrite-mode) | 698 | (not overwrite-mode) |
| 627 | (or unconditional | 699 | (or unconditional |
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el index ad7506f68ff..4468559cf38 100644 --- a/test/lisp/electric-tests.el +++ b/test/lisp/electric-tests.el | |||
| @@ -549,6 +549,33 @@ baz\"\"" | |||
| 549 | (electric-pair-mode 1) | 549 | (electric-pair-mode 1) |
| 550 | (electric-indent-mode 1) | 550 | (electric-indent-mode 1) |
| 551 | (electric-layout-mode 1))) | 551 | (electric-layout-mode 1))) |
| 552 | |||
| 553 | ;;; String pairs | ||
| 554 | ;;; TODO: add more tests | ||
| 555 | ;;; | ||
| 556 | |||
| 557 | ;; NOTE: Currently string pairs do not support insert pairs in region | ||
| 558 | ;; or delete them with electric-pair-delete-pair | ||
| 559 | |||
| 560 | (ert-deftest electric-pair-strings-pairs () | ||
| 561 | (save-electric-modes | ||
| 562 | (with-temp-buffer | ||
| 563 | (setq-local electric-pair-pairs `((,(regexp-quote "/*") . "*/"))) | ||
| 564 | (electric-pair-local-mode) | ||
| 565 | (insert "/") | ||
| 566 | (let ((last-command-event ?\*)) | ||
| 567 | (ert-simulate-command '(self-insert-command 1))) | ||
| 568 | (should (equal "/**/" (buffer-string)))))) | ||
| 569 | |||
| 570 | (ert-deftest electric-pair-strings-pairs-with-space () | ||
| 571 | (save-electric-modes | ||
| 572 | (with-temp-buffer | ||
| 573 | (setq-local electric-pair-pairs `((,(regexp-quote "/*") " */" t))) | ||
| 574 | (electric-pair-local-mode) | ||
| 575 | (insert "/") | ||
| 576 | (let ((last-command-event ?\*)) | ||
| 577 | (ert-simulate-command '(self-insert-command 1))) | ||
| 578 | (should (equal "/* */" (buffer-string)))))) | ||
| 552 | 579 | ||
| 553 | 580 | ||
| 554 | ;;; Backspacing | 581 | ;;; Backspacing |