summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllen Li <darkfeline@felesatra.moe>2022-07-03 12:31:15 +0200
committerLars Ingebrigtsen <larsi@gnus.org>2022-07-03 12:31:15 +0200
commita2f956a1d6fad6a2bc7c5d79eb3aa76cbb63cc40 (patch)
tree23c5101f29f5f4c347403126851213962c39dfd6
parentf5a11369ea1480d0b99fd538c759b53c88fd6acc (diff)
downloademacs-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.el86
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