diff options
author | Allen Li <darkfeline@felesatra.moe> | 2022-07-03 12:31:15 +0200 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2022-07-03 12:31:15 +0200 |
commit | a2f956a1d6fad6a2bc7c5d79eb3aa76cbb63cc40 (patch) | |
tree | 23c5101f29f5f4c347403126851213962c39dfd6 | |
parent | f5a11369ea1480d0b99fd538c759b53c88fd6acc (diff) | |
download | emacs-a2f956a1d6fad6a2bc7c5d79eb3aa76cbb63cc40.tar.gz |
elec-pair: Fix bug incorrectly hiding syntax-propertize-function
* lisp/elec-pair.el (electric-pair--with-text-syntax): New macro.
(electric-pair-syntax-info):
(electric-pair--balance-info):
(electric-pair--syntax-ppss, electric-pair--balance-info): Use it.
(electric-pair--with-uncached-syntax): Remove (bug#49629).
The main bug that this is fixing is `syntax-propertize-function' being
hidden in `electric-pair--balance-info' when the original syntax table
is to be used, not `electric-pair-text-syntax-table'.
Notably, this causes `electric-pair-mode' to often misbehave in HTML
files when pairing angle brackets.
This commit also flushes the cache before installing
`electric-pair-text-syntax-table', to prevent cached syntax for the
original table from affecting things.
-rw-r--r-- | lisp/elec-pair.el | 86 |
1 files changed, 47 insertions, 39 deletions
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 720f6083681..247e9b93ec2 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -188,6 +188,25 @@ be considered.") ;; I also find it often preferable not to pair next to a word. (eq (char-syntax (following-char)) ?w))) +(cl-defmacro electric-pair--with-text-syntax ((&optional start) &rest body) + "Run BODY with `electric-pair-text-syntax-table' active. +This ensures that all syntax related values are set properly and the +`syntax-ppss' cache is cleared before and after. +In particular, this must be used when BODY contains code which may +update the `syntax-ppss' cache. This includes calling +`parse-partial-sexp' and any sexp-based movement functions when +`parse-sexp-lookup-properties' is non-nil. The cache is flushed from +position START, defaulting to point." + (declare (debug ((&optional form) body)) (indent 1)) + (let ((start-var (make-symbol "start"))) + `(let ((syntax-propertize-function nil) + (,start-var ,(or start '(point)))) + (syntax-ppss-flush-cache ,start-var) + (unwind-protect + (with-syntax-table electric-pair-text-syntax-table + ,@body) + (syntax-ppss-flush-cache ,start-var))))) + (defun electric-pair-syntax-info (command-event) "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). @@ -202,13 +221,14 @@ inside a comment or string." (post-string-or-comment (nth 8 (syntax-ppss (point)))) (string-or-comment (and post-string-or-comment pre-string-or-comment)) - (table (if string-or-comment - electric-pair-text-syntax-table - (syntax-table))) - (table-syntax-and-pair (with-syntax-table table - (list (char-syntax command-event) - (or (matching-paren command-event) - command-event)))) + (table-syntax-and-pair + (cl-flet ((f () + (list (char-syntax command-event) + (or (matching-paren command-event) + command-event)))) + (if string-or-comment + (electric-pair--with-text-syntax () (f)) + (f)))) (fallback (if string-or-comment (append electric-pair-text-pairs electric-pair-pairs) @@ -237,22 +257,6 @@ inside a comment or string." (electric-layout-allow-duplicate-newlines t)) (self-insert-command 1))) -(cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body) - "Like `with-syntax-table', but flush the `syntax-ppss' cache afterwards. -Use this instead of (with-syntax-table TABLE BODY) when BODY -contains code which may update the `syntax-ppss' cache. This -includes calling `parse-partial-sexp' and any sexp-based movement -functions when `parse-sexp-lookup-properties' is non-nil. The -cache is flushed from position START, defaulting to point." - (declare (debug ((form &optional form) body)) (indent 1)) - (let ((start-var (make-symbol "start"))) - `(let ((syntax-propertize-function #'ignore) - (,start-var ,(or start '(point)))) - (unwind-protect - (with-syntax-table ,table - ,@body) - (syntax-ppss-flush-cache ,start-var))))) - (defun electric-pair--syntax-ppss (&optional pos where) "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. @@ -271,8 +275,7 @@ when to fallback to `parse-partial-sexp'." (skip-syntax-forward " >!") (point))))) (if s-or-c-start - (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table - s-or-c-start) + (electric-pair--with-text-syntax (s-or-c-start) (parse-partial-sexp s-or-c-start pos)) ;; HACK! cc-mode apparently has some `syntax-ppss' bugs (if (memq major-mode '(c-mode c++ mode)) @@ -301,9 +304,6 @@ If the outermost list is matched, don't rely on its PAIR. If point is not enclosed by any lists, return ((t) . (t))." (let* (innermost outermost - (table (if string-or-comment - electric-pair-text-syntax-table - (syntax-table))) (at-top-level-or-equivalent-fn ;; called when `scan-sexps' ran perfectly, when it found ;; a parenthesis pointing in the direction of travel. @@ -325,11 +325,14 @@ If point is not enclosed by any lists, return ((t) . (t))." (cond ((< direction 0) (condition-case nil (eq (char-after pos) - (electric-pair--with-uncached-syntax - (table) - (matching-paren - (char-before - (scan-sexps (point) 1))))) + (cl-flet ((f () + (matching-paren + (char-before + (scan-sexps (point) 1))))) + (if string-or-comment + (electric-pair--with-text-syntax () + (f)) + (f)))) (scan-error nil))) (t ;; In this case, no need to use @@ -343,7 +346,9 @@ If point is not enclosed by any lists, return ((t) . (t))." (opener (char-after start))) (and start (eq (char-before pos) - (or (with-syntax-table table + (or (if string-or-comment + (electric-pair--with-text-syntax () + (matching-paren opener)) (matching-paren opener)) opener)))))))) (actual-pair (if (> direction 0) @@ -356,11 +361,14 @@ If point is not enclosed by any lists, return ((t) . (t))." (save-excursion (while (not outermost) (condition-case err - (electric-pair--with-uncached-syntax (table) - (scan-sexps (point) (if (> direction 0) - (point-max) - (- (point-max)))) - (funcall at-top-level-or-equivalent-fn)) + (cl-flet ((f () + (scan-sexps (point) (if (> direction 0) + (point-max) + (- (point-max)))) + (funcall at-top-level-or-equivalent-fn))) + (if string-or-comment + (electric-pair--with-text-syntax () (f)) + (f))) (scan-error (cond ((or ;; some error happened and it is not of the "ended |