diff options
| author | Noam Postavsky | 2017-12-14 21:25:13 -0500 |
|---|---|---|
| committer | Noam Postavsky | 2017-12-16 21:02:38 -0500 |
| commit | 89cfdbf729bc731331358e0efc69547547aa3ca2 (patch) | |
| tree | c70f4749d78bb754f604f100c361cb0668788793 | |
| parent | c5061d81b972d9b846359d6b9be1c5a0fc4a2402 (diff) | |
| download | emacs-89cfdbf729bc731331358e0efc69547547aa3ca2.tar.gz emacs-89cfdbf729bc731331358e0efc69547547aa3ca2.zip | |
Don't mess up syntax-ppss cache in electric-pair (Bug#29710)
In Emacs 25 and above, calling `scan-sexps', `parse-partial-sexp', or
similar may update the syntax-ppss cache if
`parse-sexp-lookup-properties' is non-nil. Therefore, when calling
any of these functions with a different than normal syntax-table, the
cache must be cleaned afterwards.
* lisp/elec-pair.el (electric-pair--with-uncached-syntax): New macro.
(electric-pair--syntax-ppss, electric-pair--balance-info): Use it.
| -rw-r--r-- | lisp/elec-pair.el | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 7f523d1df45..a980f51d3c0 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | ;;; Code: | 24 | ;;; Code: |
| 25 | 25 | ||
| 26 | (require 'electric) | 26 | (require 'electric) |
| 27 | (eval-when-compile (require 'cl-lib)) | ||
| 27 | 28 | ||
| 28 | ;;; Electric pairing. | 29 | ;;; Electric pairing. |
| 29 | 30 | ||
| @@ -222,6 +223,22 @@ inside a comment or string." | |||
| 222 | (electric-pair-mode nil)) | 223 | (electric-pair-mode nil)) |
| 223 | (self-insert-command 1))) | 224 | (self-insert-command 1))) |
| 224 | 225 | ||
| 226 | (cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body) | ||
| 227 | "Like `with-syntax-table', but flush the syntax-ppss cache afterwards. | ||
| 228 | Use this instead of (with-syntax-table TABLE BODY) when BODY | ||
| 229 | contains code which may update the syntax-ppss cache. This | ||
| 230 | includes calling `parse-partial-sexp' and any sexp-based movement | ||
| 231 | functions when `parse-sexp-lookup-properties' is non-nil. The | ||
| 232 | cache is flushed from position START, defaulting to point." | ||
| 233 | (declare (debug ((form &optional form) body)) (indent 1)) | ||
| 234 | (let ((start-var (make-symbol "start"))) | ||
| 235 | `(let ((syntax-propertize-function nil) | ||
| 236 | (,start-var ,(or start '(point)))) | ||
| 237 | (unwind-protect | ||
| 238 | (with-syntax-table ,table | ||
| 239 | ,@body) | ||
| 240 | (syntax-ppss-flush-cache ,start-var))))) | ||
| 241 | |||
| 225 | (defun electric-pair--syntax-ppss (&optional pos where) | 242 | (defun electric-pair--syntax-ppss (&optional pos where) |
| 226 | "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. | 243 | "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. |
| 227 | 244 | ||
| @@ -240,7 +257,8 @@ when to fallback to `parse-partial-sexp'." | |||
| 240 | (skip-syntax-forward " >!") | 257 | (skip-syntax-forward " >!") |
| 241 | (point))))) | 258 | (point))))) |
| 242 | (if s-or-c-start | 259 | (if s-or-c-start |
| 243 | (with-syntax-table electric-pair-text-syntax-table | 260 | (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table |
| 261 | s-or-c-start) | ||
| 244 | (parse-partial-sexp s-or-c-start pos)) | 262 | (parse-partial-sexp s-or-c-start pos)) |
| 245 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs | 263 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs |
| 246 | (if (memq major-mode '(c-mode c++ mode)) | 264 | (if (memq major-mode '(c-mode c++ mode)) |
| @@ -293,7 +311,8 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 293 | (cond ((< direction 0) | 311 | (cond ((< direction 0) |
| 294 | (condition-case nil | 312 | (condition-case nil |
| 295 | (eq (char-after pos) | 313 | (eq (char-after pos) |
| 296 | (with-syntax-table table | 314 | (electric-pair--with-uncached-syntax |
| 315 | (table) | ||
| 297 | (matching-paren | 316 | (matching-paren |
| 298 | (char-before | 317 | (char-before |
| 299 | (scan-sexps (point) 1))))) | 318 | (scan-sexps (point) 1))))) |
| @@ -323,7 +342,7 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 323 | (save-excursion | 342 | (save-excursion |
| 324 | (while (not outermost) | 343 | (while (not outermost) |
| 325 | (condition-case err | 344 | (condition-case err |
| 326 | (with-syntax-table table | 345 | (electric-pair--with-uncached-syntax (table) |
| 327 | (scan-sexps (point) (if (> direction 0) | 346 | (scan-sexps (point) (if (> direction 0) |
| 328 | (point-max) | 347 | (point-max) |
| 329 | (- (point-max)))) | 348 | (- (point-max)))) |