bug#50236: 27.2; electric-pair-mode is inconvenient in comint
João Távora <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
João Távora <[email protected]> writes: > On Mon, Aug 17, 2026, 11:56 Eli Zaretskii <[email protected]> wrote: > If not, I'm not sure it is wise to > install on the emacs-31 branchrvof so close to the release. Sean, WDYT? > > Should be reasonably safe, is my judgement. It's very elegant and > small. Also I made it a noop in anything but comint.el modes. Actualy, the patch had a tiny bug. Should be setting the controlling variable with setq-local, not setq, so that it is truly isolated to comint.el-based modes. Attaching correct version: João
0001-Make-electric-pair-mode-respect-field-boundaries-bug.patch
(text/x-patch, 5.7 KB)
From 6a5a503de77bddb215746a688daae984bf834e16 Mon Sep 17 00:00:00 2001 From: Andrew Hyatt <[email protected]> Date: Sun, 16 Aug 2026 12:31:55 +0100 Subject: [PATCH] Make electric-pair-mode respect field boundaries (bug#50236) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Among other potential benefits, this makes e-p-m work correctly in all comint-based modes. * lisp/elec-pair.el (electric-pair-field-search-size): New variable. (electric-pair-post-self-insert-function): Tweak. (electric--pair-psif-1) * etc/NEWS: Call out change. * lisp/comint.el (electric-pair-field-search-size): forward-declare. (comint-mode): Set electric-pair-field-search-size to 1000. * test/lisp/electric-tests.el (preserve-balance) (preserve-balance-not-across-fields): New tests. Co-authored-by: João Távora <[email protected]> --- etc/NEWS | 7 +++++++ lisp/comint.el | 5 ++++- lisp/elec-pair.el | 24 +++++++++++++++++++++++- test/lisp/electric-tests.el | 26 +++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 5f5f59d2a9f..fe662e4421d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -972,6 +972,13 @@ To use this, add a list to both electric pair user options: '("/*" . "*/")'. You can also specify that an extra space should be inserted after the first string, like this: '("/*" " */" t)'. +*** Electric pair mode can restrict operation to nearby fields +This is particularly useful in comint-based modes (like Eshell) and +other situations where process output may contain unpaired delimiters, +while keeping delimiters you insert balanced. The +''electric-pair-field-search-size'' variable controls the search +distance for nearby fields. + --- ** New user option 'electric-indent-actions'. This user option specifies a list of actions to reindent. The possible diff --git a/lisp/comint.el b/lisp/comint.el index e5418f4ee67..a78002ab6b8 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -702,6 +702,8 @@ comint-stored-incomplete-input (put 'comint-mode 'mode-class 'special) +(defvar electric-pair-field-search-size) + (define-derived-mode comint-mode fundamental-mode "Comint" "Major mode for interacting with an inferior interpreter. Interpreter name is same as buffer name, sans the asterisks. @@ -792,7 +794,8 @@ comint-mode (add-hook 'isearch-mode-hook #'comint-history-isearch-setup nil t) (add-hook 'completion-at-point-functions #'comint-completion-at-point nil t) ;; This behavior is not useful in comint buffers, and is annoying - (setq-local next-line-add-newlines nil)) + (setq-local next-line-add-newlines nil) + (setq-local electric-pair-field-search-size 1000)) (defun comint-check-proc (buffer) "Return non-nil if there is a living process associated w/buffer BUFFER. diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 54fbc960b0f..d7ae555e408 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -596,10 +596,32 @@ electric-pair-default-inhibit (electric-pair-inhibit-if-helps-balance char) (electric-pair-conservative-inhibit char))) +(defvar electric-pair-field-search-size nil + "How far to look for nearby fields to restrict `electric-pair-mode'. + +If nil, do not look for nearby fields and use the accessible portion of +the buffer. If a integer number of characters, look at most that far +backward and forward for a field boundary. If one isn't found, use the +accessible portion of the buffer in that direction.") + (defun electric-pair-post-self-insert-function () "Do main work for `electric-pair-mode'. This function is added to `post-self-insert-hook' when -`electric-pair-mode' is enabled. +`electric-pair-mode' is enabled." + ;; First, figure out whether to restrit the buffer (bug#50236) + (if (or (null electric-pair-field-search-size) + (use-region-p)) + (electric--pair-psif-1) + (let* ((min (- (point) electric-pair-field-search-size)) + (max (+ (point) electric-pair-field-search-size)) + (beg (field-beginning nil nil (max (point-min) min))) + (end (field-end nil nil (min (point-max) max)))) + (with-restriction + (if (= min beg) (point-min) beg) (if (= max end) (point-max) end) + (electric--pair-psif-1))))) + +(defun electric--pair-psif-1 () + "Do main work for `electric-pair-post-self-insert-function.' If the newly inserted character C has delimiter syntax, this function may decide to insert additional paired delimiters, or diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el index 9209e1739fd..d678279c8cc 100644 --- a/test/lisp/electric-tests.el +++ b/test/lisp/electric-tests.el @@ -703,7 +703,31 @@ autowrapping-multi-2 (goto-char (point-max)) (skip-chars-backward "\"") (mark-sexp -1))) - + +(define-electric-pair-test preserve-balance + "\"\n\n" "---\"" + :expected-string "\"\n\n\"" + :expected-point 5 + :modes '(fundamental-mode) + :test-in-comments nil + :test-in-strings nil + :bindings '((electric-pair-preserve-balance . t)) + :fixture-fn (lambda () + (electric-pair-mode 1))) + +(define-electric-pair-test preserve-balance-not-across-fields + "\"\n\n" "---\"" + :expected-string "\"\n\n\"\"" + :expected-point 5 + :modes '(fundamental-mode) + :test-in-comments nil + :test-in-strings nil + :bindings '((electric-pair-preserve-balance . t) + (electric-pair-field-search-size . 100)) + :fixture-fn (lambda () + (electric-pair-mode 1) + (add-text-properties (point-min) (+ (point-min) 2) + '(field t)))) ;;; Electric quotes (define-electric-pair-test electric-quote-string -- 2.55.0