aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElías Gabriel Pérez2025-04-24 17:34:58 -0600
committerEli Zaretskii2025-06-21 12:24:55 +0300
commit60fbeda771639ded68ffd0666df340c7a06cafcf (patch)
tree9b11ccee5a6bbba5e51eb0b23b5b0dbff300d6f6
parente379f14193982ef500d8806386e26155ff780290 (diff)
downloademacs-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/NEWS10
-rw-r--r--lisp/elec-pair.el80
-rw-r--r--test/lisp/electric-tests.el27
3 files changed, 113 insertions, 4 deletions
diff --git a/etc/NEWS b/etc/NEWS
index e3c5f56216f..510b38ed79e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -563,6 +563,16 @@ You can now insert or wrap text with multiple sets of parentheses and
563other matching delimiters at once with Electric Pair mode, by providing 563other matching delimiters at once with Electric Pair mode, by providing
564a prefix argument when inserting one of the delimiters. 564a 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
569strings for multi-character paired delimiters.
570
571To use this add a list to both electric pair variables: ("/*" . "*/").
572
573You can also specify to insert an extra space after the first string
574pair: ("/*" " */" 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').
568Typing 'M-~' while saving some buffers means not to save the buffer and 578Typing '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
43no syntax relevant to `electric-pair-mode' in the mode's syntax 43no syntax relevant to `electric-pair-mode' in the mode's syntax
44table. 44table.
45 45
46Each list element should be in one of these forms:
47 (CHAR . CHAR)
48Where CHAR is character to be used as pair.
49
50 (STRING STRING SPC)
51Where STRING is a string to be used as pair and SPC a non-nil value
52which specifies to insert an extra space after first STRING.
53
54 (STRING . STRING)
55This is similar to (STRING STRING SPC) form, except that SPC (space) is
56ignored and will not be inserted.
57
58In both string pairs forms, the first string pair must be a regular
59expression.
60
61In comparation to character pairs, string pairs does not support
62inserting pairs in regions and can not be deleted with
63`electric-pair-delete-pair', thus string pairs should be used only for
64multi-character pairs.
65
46See also the variable `electric-pair-text-pairs'." 66See 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
57Pairs of delimiters in this list are a fallback in case they have 81Pairs of delimiters in this list are a fallback in case they have
58no syntax relevant to `electric-pair-mode' in the syntax table 82no syntax relevant to `electric-pair-mode' in the syntax table
59defined in `electric-pair-text-syntax-table'." 83defined in `electric-pair-text-syntax-table'.
84
85Each list element should be in one of these forms:
86 (CHAR . CHAR)
87Where CHAR is character to be used as pair.
88
89 (STRING STRING SPC)
90Where STRING is a string to be used as pair and SPC a non-nil value
91which specifies to insert an extra space after first STRING.
92
93 (STRING . STRING)
94This is similar to (STRING STRING SPC) form, except that SPC (space) is
95ignored and will not be inserted.
96
97In both string pairs forms, the first string pair must be a regular
98expression.
99
100In comparation to character pairs, string pairs does not support
101inserting pairs in regions and can not be deleted with
102`electric-pair-delete-pair', thus string pairs should be used only for
103multi-character pairs.
104
105See 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