mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-28 07:45:00 +00:00
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.
This commit is contained in:
parent
f5a11369ea
commit
a2f956a1d6
@ -188,6 +188,25 @@ be considered.")
|
|||||||
;; I also find it often preferable not to pair next to a word.
|
;; I also find it often preferable not to pair next to a word.
|
||||||
(eq (char-syntax (following-char)) ?w)))
|
(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)
|
(defun electric-pair-syntax-info (command-event)
|
||||||
"Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START).
|
"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))))
|
(post-string-or-comment (nth 8 (syntax-ppss (point))))
|
||||||
(string-or-comment (and post-string-or-comment
|
(string-or-comment (and post-string-or-comment
|
||||||
pre-string-or-comment))
|
pre-string-or-comment))
|
||||||
(table (if string-or-comment
|
(table-syntax-and-pair
|
||||||
electric-pair-text-syntax-table
|
(cl-flet ((f ()
|
||||||
(syntax-table)))
|
(list (char-syntax command-event)
|
||||||
(table-syntax-and-pair (with-syntax-table table
|
(or (matching-paren command-event)
|
||||||
(list (char-syntax command-event)
|
command-event))))
|
||||||
(or (matching-paren command-event)
|
(if string-or-comment
|
||||||
command-event))))
|
(electric-pair--with-text-syntax () (f))
|
||||||
|
(f))))
|
||||||
(fallback (if string-or-comment
|
(fallback (if string-or-comment
|
||||||
(append electric-pair-text-pairs
|
(append electric-pair-text-pairs
|
||||||
electric-pair-pairs)
|
electric-pair-pairs)
|
||||||
@ -237,22 +257,6 @@ inside a comment or string."
|
|||||||
(electric-layout-allow-duplicate-newlines t))
|
(electric-layout-allow-duplicate-newlines t))
|
||||||
(self-insert-command 1)))
|
(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)
|
(defun electric-pair--syntax-ppss (&optional pos where)
|
||||||
"Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'.
|
"Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'.
|
||||||
|
|
||||||
@ -271,8 +275,7 @@ when to fallback to `parse-partial-sexp'."
|
|||||||
(skip-syntax-forward " >!")
|
(skip-syntax-forward " >!")
|
||||||
(point)))))
|
(point)))))
|
||||||
(if s-or-c-start
|
(if s-or-c-start
|
||||||
(electric-pair--with-uncached-syntax (electric-pair-text-syntax-table
|
(electric-pair--with-text-syntax (s-or-c-start)
|
||||||
s-or-c-start)
|
|
||||||
(parse-partial-sexp s-or-c-start pos))
|
(parse-partial-sexp s-or-c-start pos))
|
||||||
;; HACK! cc-mode apparently has some `syntax-ppss' bugs
|
;; HACK! cc-mode apparently has some `syntax-ppss' bugs
|
||||||
(if (memq major-mode '(c-mode c++ mode))
|
(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))."
|
If point is not enclosed by any lists, return ((t) . (t))."
|
||||||
(let* (innermost
|
(let* (innermost
|
||||||
outermost
|
outermost
|
||||||
(table (if string-or-comment
|
|
||||||
electric-pair-text-syntax-table
|
|
||||||
(syntax-table)))
|
|
||||||
(at-top-level-or-equivalent-fn
|
(at-top-level-or-equivalent-fn
|
||||||
;; called when `scan-sexps' ran perfectly, when it found
|
;; called when `scan-sexps' ran perfectly, when it found
|
||||||
;; a parenthesis pointing in the direction of travel.
|
;; 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)
|
(cond ((< direction 0)
|
||||||
(condition-case nil
|
(condition-case nil
|
||||||
(eq (char-after pos)
|
(eq (char-after pos)
|
||||||
(electric-pair--with-uncached-syntax
|
(cl-flet ((f ()
|
||||||
(table)
|
(matching-paren
|
||||||
(matching-paren
|
(char-before
|
||||||
(char-before
|
(scan-sexps (point) 1)))))
|
||||||
(scan-sexps (point) 1)))))
|
(if string-or-comment
|
||||||
|
(electric-pair--with-text-syntax ()
|
||||||
|
(f))
|
||||||
|
(f))))
|
||||||
(scan-error nil)))
|
(scan-error nil)))
|
||||||
(t
|
(t
|
||||||
;; In this case, no need to use
|
;; 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)))
|
(opener (char-after start)))
|
||||||
(and start
|
(and start
|
||||||
(eq (char-before pos)
|
(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))
|
(matching-paren opener))
|
||||||
opener))))))))
|
opener))))))))
|
||||||
(actual-pair (if (> direction 0)
|
(actual-pair (if (> direction 0)
|
||||||
@ -356,11 +361,14 @@ If point is not enclosed by any lists, return ((t) . (t))."
|
|||||||
(save-excursion
|
(save-excursion
|
||||||
(while (not outermost)
|
(while (not outermost)
|
||||||
(condition-case err
|
(condition-case err
|
||||||
(electric-pair--with-uncached-syntax (table)
|
(cl-flet ((f ()
|
||||||
(scan-sexps (point) (if (> direction 0)
|
(scan-sexps (point) (if (> direction 0)
|
||||||
(point-max)
|
(point-max)
|
||||||
(- (point-max))))
|
(- (point-max))))
|
||||||
(funcall at-top-level-or-equivalent-fn))
|
(funcall at-top-level-or-equivalent-fn)))
|
||||||
|
(if string-or-comment
|
||||||
|
(electric-pair--with-text-syntax () (f))
|
||||||
|
(f)))
|
||||||
(scan-error
|
(scan-error
|
||||||
(cond ((or
|
(cond ((or
|
||||||
;; some error happened and it is not of the "ended
|
;; some error happened and it is not of the "ended
|
||||||
|
Loading…
Reference in New Issue
Block a user