master 8a8d9b5c6a4: Make electric-pair-mode respect field boundaries (bug#50236)
João Távora <[email protected]>
| Newsgroups | gmane.emacs.diffs |
|---|---|
| Message-ID | <[email protected]> |
branch: master commit 8a8d9b5c6a48239b235c9cf5bc4e8816e3520501 Author: Andrew Hyatt <[email protected]> Commit: João Távora <[email protected]> Make electric-pair-mode respect field boundaries (bug#50236) 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, call electric--pair-psif-1 (electric--pair-psif-1): New helper from old electric-pair-post-self-insert-function. * 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 | 9 +++++++++ lisp/comint.el | 5 ++++- lisp/elec-pair.el | 24 +++++++++++++++++++++++- test/lisp/electric-tests.el | 26 +++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index d9c30749ab4..9a88a6d4403 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -120,6 +120,15 @@ look after the replacement, using the new face 'query-replace-preview'. This tells you what back-references like '\1' expand to before you commit to the edit. The preview is off by default. +** Electric Pair mode + +*** Electric pair mode can restrict operation to nearby fields +This is particularly useful in comint-based modes (like 'M-x shell' or +'M-x run-python') 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. + * Changes in Specialized Modes and Packages in Emacs 32.1 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 @@ The command \\[comint-accumulate] sets this.") (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 @@ Entry to this mode runs the hooks on `comint-mode-hook'." (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..700dae0a41c 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -596,10 +596,32 @@ happened." (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, falling back to 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 @@ baz\"\"" (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