diff options
| -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.") | |||
| 188 | ;; I also find it often preferable not to pair next to a word. | 188 | ;; I also find it often preferable not to pair next to a word. |
| 189 | (eq (char-syntax (following-char)) ?w))) | 189 | (eq (char-syntax (following-char)) ?w))) |
| 190 | 190 | ||
| 191 | (cl-defmacro electric-pair--with-text-syntax ((&optional start) &rest body) | ||
| 192 | "Run BODY with `electric-pair-text-syntax-table' active. | ||
| 193 | This ensures that all syntax related values are set properly and the | ||
| 194 | `syntax-ppss' cache is cleared before and after. | ||
| 195 | In particular, this must be used when BODY contains code which may | ||
| 196 | update the `syntax-ppss' cache. This includes calling | ||
| 197 | `parse-partial-sexp' and any sexp-based movement functions when | ||
| 198 | `parse-sexp-lookup-properties' is non-nil. The cache is flushed from | ||
| 199 | position START, defaulting to point." | ||
| 200 | (declare (debug ((&optional form) body)) (indent 1)) | ||
| 201 | (let ((start-var (make-symbol "start"))) | ||
| 202 | `(let ((syntax-propertize-function nil) | ||
| 203 | (,start-var ,(or start '(point)))) | ||
| 204 | (syntax-ppss-flush-cache ,start-var) | ||
| 205 | (unwind-protect | ||
| 206 | (with-syntax-table electric-pair-text-syntax-table | ||
| 207 | ,@body) | ||
| 208 | (syntax-ppss-flush-cache ,start-var))))) | ||
| 209 | |||
| 191 | (defun electric-pair-syntax-info (command-event) | 210 | (defun electric-pair-syntax-info (command-event) |
| 192 | "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). | 211 | "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). |
| 193 | 212 | ||
| @@ -202,13 +221,14 @@ inside a comment or string." | |||
| 202 | (post-string-or-comment (nth 8 (syntax-ppss (point)))) | 221 | (post-string-or-comment (nth 8 (syntax-ppss (point)))) |
| 203 | (string-or-comment (and post-string-or-comment | 222 | (string-or-comment (and post-string-or-comment |
| 204 | pre-string-or-comment)) | 223 | pre-string-or-comment)) |
| 205 | (table (if string-or-comment | 224 | (table-syntax-and-pair |
| 206 | electric-pair-text-syntax-table | 225 | (cl-flet ((f () |
| 207 | (syntax-table))) | 226 | (list (char-syntax command-event) |
| 208 | (table-syntax-and-pair (with-syntax-table table | 227 | (or (matching-paren command-event) |
| 209 | (list (char-syntax command-event) | 228 | command-event)))) |
| 210 | (or (matching-paren command-event) | 229 | (if string-or-comment |
| 211 | command-event)))) | 230 | (electric-pair--with-text-syntax () (f)) |
| 231 | (f)))) | ||
| 212 | (fallback (if string-or-comment | 232 | (fallback (if string-or-comment |
| 213 | (append electric-pair-text-pairs | 233 | (append electric-pair-text-pairs |
| 214 | electric-pair-pairs) | 234 | electric-pair-pairs) |
| @@ -237,22 +257,6 @@ inside a comment or string." | |||
| 237 | (electric-layout-allow-duplicate-newlines t)) | 257 | (electric-layout-allow-duplicate-newlines t)) |
| 238 | (self-insert-command 1))) | 258 | (self-insert-command 1))) |
| 239 | 259 | ||
| 240 | (cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body) | ||
| 241 | "Like `with-syntax-table', but flush the `syntax-ppss' cache afterwards. | ||
| 242 | Use this instead of (with-syntax-table TABLE BODY) when BODY | ||
| 243 | contains code which may update the `syntax-ppss' cache. This | ||
| 244 | includes calling `parse-partial-sexp' and any sexp-based movement | ||
| 245 | functions when `parse-sexp-lookup-properties' is non-nil. The | ||
| 246 | cache is flushed from position START, defaulting to point." | ||
| 247 | (declare (debug ((form &optional form) body)) (indent 1)) | ||
| 248 | (let ((start-var (make-symbol "start"))) | ||
| 249 | `(let ((syntax-propertize-function #'ignore) | ||
| 250 | (,start-var ,(or start '(point)))) | ||
| 251 | (unwind-protect | ||
| 252 | (with-syntax-table ,table | ||
| 253 | ,@body) | ||
| 254 | (syntax-ppss-flush-cache ,start-var))))) | ||
| 255 | |||
| 256 | (defun electric-pair--syntax-ppss (&optional pos where) | 260 | (defun electric-pair--syntax-ppss (&optional pos where) |
| 257 | "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. | 261 | "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. |
| 258 | 262 | ||
| @@ -271,8 +275,7 @@ when to fallback to `parse-partial-sexp'." | |||
| 271 | (skip-syntax-forward " >!") | 275 | (skip-syntax-forward " >!") |
| 272 | (point))))) | 276 | (point))))) |
| 273 | (if s-or-c-start | 277 | (if s-or-c-start |
| 274 | (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table | 278 | (electric-pair--with-text-syntax (s-or-c-start) |
| 275 | s-or-c-start) | ||
| 276 | (parse-partial-sexp s-or-c-start pos)) | 279 | (parse-partial-sexp s-or-c-start pos)) |
| 277 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs | 280 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs |
| 278 | (if (memq major-mode '(c-mode c++ mode)) | 281 | (if (memq major-mode '(c-mode c++ mode)) |
| @@ -301,9 +304,6 @@ If the outermost list is matched, don't rely on its PAIR. | |||
| 301 | If point is not enclosed by any lists, return ((t) . (t))." | 304 | If point is not enclosed by any lists, return ((t) . (t))." |
| 302 | (let* (innermost | 305 | (let* (innermost |
| 303 | outermost | 306 | outermost |
| 304 | (table (if string-or-comment | ||
| 305 | electric-pair-text-syntax-table | ||
| 306 | (syntax-table))) | ||
| 307 | (at-top-level-or-equivalent-fn | 307 | (at-top-level-or-equivalent-fn |
| 308 | ;; called when `scan-sexps' ran perfectly, when it found | 308 | ;; called when `scan-sexps' ran perfectly, when it found |
| 309 | ;; a parenthesis pointing in the direction of travel. | 309 | ;; a parenthesis pointing in the direction of travel. |
| @@ -325,11 +325,14 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 325 | (cond ((< direction 0) | 325 | (cond ((< direction 0) |
| 326 | (condition-case nil | 326 | (condition-case nil |
| 327 | (eq (char-after pos) | 327 | (eq (char-after pos) |
| 328 | (electric-pair--with-uncached-syntax | 328 | (cl-flet ((f () |
| 329 | (table) | 329 | (matching-paren |
| 330 | (matching-paren | 330 | (char-before |
| 331 | (char-before | 331 | (scan-sexps (point) 1))))) |
| 332 | (scan-sexps (point) 1))))) | 332 | (if string-or-comment |
| 333 | (electric-pair--with-text-syntax () | ||
| 334 | (f)) | ||
| 335 | (f)))) | ||
| 333 | (scan-error nil))) | 336 | (scan-error nil))) |
| 334 | (t | 337 | (t |
| 335 | ;; In this case, no need to use | 338 | ;; In this case, no need to use |
| @@ -343,7 +346,9 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 343 | (opener (char-after start))) | 346 | (opener (char-after start))) |
| 344 | (and start | 347 | (and start |
| 345 | (eq (char-before pos) | 348 | (eq (char-before pos) |
| 346 | (or (with-syntax-table table | 349 | (or (if string-or-comment |
| 350 | (electric-pair--with-text-syntax () | ||
| 351 | (matching-paren opener)) | ||
| 347 | (matching-paren opener)) | 352 | (matching-paren opener)) |
| 348 | opener)))))))) | 353 | opener)))))))) |
| 349 | (actual-pair (if (> direction 0) | 354 | (actual-pair (if (> direction 0) |
| @@ -356,11 +361,14 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 356 | (save-excursion | 361 | (save-excursion |
| 357 | (while (not outermost) | 362 | (while (not outermost) |
| 358 | (condition-case err | 363 | (condition-case err |
| 359 | (electric-pair--with-uncached-syntax (table) | 364 | (cl-flet ((f () |
| 360 | (scan-sexps (point) (if (> direction 0) | 365 | (scan-sexps (point) (if (> direction 0) |
| 361 | (point-max) | 366 | (point-max) |
| 362 | (- (point-max)))) | 367 | (- (point-max)))) |
| 363 | (funcall at-top-level-or-equivalent-fn)) | 368 | (funcall at-top-level-or-equivalent-fn))) |
| 369 | (if string-or-comment | ||
| 370 | (electric-pair--with-text-syntax () (f)) | ||
| 371 | (f))) | ||
| 364 | (scan-error | 372 | (scan-error |
| 365 | (cond ((or | 373 | (cond ((or |
| 366 | ;; some error happened and it is not of the "ended | 374 | ;; some error happened and it is not of the "ended |