diff options
| author | João Távora | 2013-12-26 22:02:49 +0000 |
|---|---|---|
| committer | João Távora | 2013-12-26 22:02:49 +0000 |
| commit | 3b8d5131a316ad2fdc206744cec489a11f0bf1d3 (patch) | |
| tree | 7a717cd2152141fdd7e5abe20926c7c0d4092869 /lisp | |
| parent | fbcc63a3176389f39cb06f5a56f2abb29b06eaab (diff) | |
| download | emacs-3b8d5131a316ad2fdc206744cec489a11f0bf1d3.tar.gz emacs-3b8d5131a316ad2fdc206744cec489a11f0bf1d3.zip | |
Make Electric Pair mode smarter/more useful:
* lisp/electric.el: Pairing/skipping helps preserve
balance. Autobackspacing behaviour. Opens extra newlines between
pairs. Skip whitespace before closing delimiters.
* lisp/emacs-lisp/lisp-mode.el (lisp-mode-variables): Use new
features.
* test/automated/electric-tests.lisp: New file.
* doc/emacs/programs.texi: Describe new features.
* lisp/simple.el: Pass non-nil interactive arg to newline call inside
newline-and-indent.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 22 | ||||
| -rw-r--r-- | lisp/electric.el | 599 | ||||
| -rw-r--r-- | lisp/emacs-lisp/lisp-mode.el | 8 | ||||
| -rw-r--r-- | lisp/simple.el | 8 |
4 files changed, 542 insertions, 95 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 972106bd26f..2831988efd9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,25 @@ | |||
| 1 | 2013-12-26 João Távora <joaotavora@gmail.com> | ||
| 2 | |||
| 3 | * electric.el (electric-pair-mode): More flexible engine for skip- | ||
| 4 | and inhibit predicates, new options for pairing-related | ||
| 5 | functionality. | ||
| 6 | (electric-pair-preserve-balance): Pair/skip parentheses and quotes | ||
| 7 | if that keeps or improves their balance in buffers. | ||
| 8 | (electric-pair-delete-adjacent-pairs): Delete the pair when | ||
| 9 | backspacing over adjacent matched delimiters. | ||
| 10 | (electric-pair-open-extra-newline): Open extra newline when | ||
| 11 | inserting newlines between adjacent matched delimiters. | ||
| 12 | (electric--sort-post-self-insertion-hook): Sort | ||
| 13 | post-self-insert-hook according to priority values when | ||
| 14 | minor-modes are activated. | ||
| 15 | * simple.el (newline-and-indent): Call newline with interactive | ||
| 16 | set to t. | ||
| 17 | (blink-paren-post-self-insert-function): Set priority to 100. | ||
| 18 | * emacs-lisp/lisp-mode.el (lisp-mode-variables): Use | ||
| 19 | electric-pair-text-pairs to pair backtick-and-quote in strings and | ||
| 20 | comments. Locally set electric-pair-skip-whitespace to 'chomp and | ||
| 21 | electric-pair-open-newline-between-pairs to nil. | ||
| 22 | |||
| 1 | 2013-12-26 Fabián Ezequiel Gallina <fgallina@gnu.org> | 23 | 2013-12-26 Fabián Ezequiel Gallina <fgallina@gnu.org> |
| 2 | 24 | ||
| 3 | * progmodes/python.el: Use lexical-binding. | 25 | * progmodes/python.el: Use lexical-binding. |
diff --git a/lisp/electric.el b/lisp/electric.el index 91b99b4bfe7..fc5e63f90bb 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -187,6 +187,17 @@ Returns nil when we can't find this char." | |||
| 187 | (eq (char-before) last-command-event))))) | 187 | (eq (char-before) last-command-event))))) |
| 188 | pos))) | 188 | pos))) |
| 189 | 189 | ||
| 190 | (defun electric--sort-post-self-insertion-hook () | ||
| 191 | "Ensure order of electric functions in `post-self-insertion-hook'. | ||
| 192 | |||
| 193 | Hooks in this variable interact in non-trivial ways, so a | ||
| 194 | relative order must be maintained within it." | ||
| 195 | (setq-default post-self-insert-hook | ||
| 196 | (sort (default-value 'post-self-insert-hook) | ||
| 197 | #'(lambda (fn1 fn2) | ||
| 198 | (< (or (get fn1 'priority) 0) | ||
| 199 | (or (get fn2 'priority) 0)))))) | ||
| 200 | |||
| 190 | ;;; Electric indentation. | 201 | ;;; Electric indentation. |
| 191 | 202 | ||
| 192 | ;; Autoloading variables is generally undesirable, but major modes | 203 | ;; Autoloading variables is generally undesirable, but major modes |
| @@ -267,6 +278,8 @@ mode set `electric-indent-inhibit', but this can be used as a workaround.") | |||
| 267 | (> pos (line-beginning-position))) | 278 | (> pos (line-beginning-position))) |
| 268 | (indent-according-to-mode))))) | 279 | (indent-according-to-mode))))) |
| 269 | 280 | ||
| 281 | (put 'electric-indent-post-self-insert-function 'priority 60) | ||
| 282 | |||
| 270 | (defun electric-indent-just-newline (arg) | 283 | (defun electric-indent-just-newline (arg) |
| 271 | "Insert just a newline, without any auto-indentation." | 284 | "Insert just a newline, without any auto-indentation." |
| 272 | (interactive "*P") | 285 | (interactive "*P") |
| @@ -295,20 +308,9 @@ insert a character from `electric-indent-chars'." | |||
| 295 | #'electric-indent-post-self-insert-function)) | 308 | #'electric-indent-post-self-insert-function)) |
| 296 | (when (eq (lookup-key global-map [?\C-j]) 'newline-and-indent) | 309 | (when (eq (lookup-key global-map [?\C-j]) 'newline-and-indent) |
| 297 | (define-key global-map [?\C-j] 'electric-indent-just-newline)) | 310 | (define-key global-map [?\C-j] 'electric-indent-just-newline)) |
| 298 | ;; post-self-insert-hooks interact in non-trivial ways. | ||
| 299 | ;; It turns out that electric-indent-mode generally works better if run | ||
| 300 | ;; late, but still before blink-paren. | ||
| 301 | (add-hook 'post-self-insert-hook | 311 | (add-hook 'post-self-insert-hook |
| 302 | #'electric-indent-post-self-insert-function | 312 | #'electric-indent-post-self-insert-function) |
| 303 | 'append) | 313 | (electric--sort-post-self-insertion-hook))) |
| 304 | ;; FIXME: Ugly! | ||
| 305 | (let ((bp (memq #'blink-paren-post-self-insert-function | ||
| 306 | (default-value 'post-self-insert-hook)))) | ||
| 307 | (when (memq #'electric-indent-post-self-insert-function bp) | ||
| 308 | (setcar bp #'electric-indent-post-self-insert-function) | ||
| 309 | (setcdr bp (cons #'blink-paren-post-self-insert-function | ||
| 310 | (delq #'electric-indent-post-self-insert-function | ||
| 311 | (cdr bp)))))))) | ||
| 312 | 314 | ||
| 313 | ;;;###autoload | 315 | ;;;###autoload |
| 314 | (define-minor-mode electric-indent-local-mode | 316 | (define-minor-mode electric-indent-local-mode |
| @@ -327,32 +329,163 @@ insert a character from `electric-indent-chars'." | |||
| 327 | 329 | ||
| 328 | (defcustom electric-pair-pairs | 330 | (defcustom electric-pair-pairs |
| 329 | '((?\" . ?\")) | 331 | '((?\" . ?\")) |
| 330 | "Alist of pairs that should be used regardless of major mode." | 332 | "Alist of pairs that should be used regardless of major mode. |
| 333 | |||
| 334 | Pairs of delimiters in this list are a fallback in case they have | ||
| 335 | no syntax relevant to `electric-pair-mode' in the mode's syntax | ||
| 336 | table. | ||
| 337 | |||
| 338 | See also the variable `electric-pair-text-pairs'." | ||
| 331 | :version "24.1" | 339 | :version "24.1" |
| 332 | :type '(repeat (cons character character))) | 340 | :type '(repeat (cons character character))) |
| 333 | 341 | ||
| 334 | (defcustom electric-pair-skip-self t | 342 | (defcustom electric-pair-text-pairs |
| 343 | '((?\" . ?\" )) | ||
| 344 | "Alist of pairs that should always be used in comments and strings. | ||
| 345 | |||
| 346 | Pairs of delimiters in this list are a fallback in case they have | ||
| 347 | no syntax relevant to `electric-pair-mode' in the syntax table | ||
| 348 | defined in `electric-pair-text-syntax-table'" | ||
| 349 | :version "24.4" | ||
| 350 | :type '(repeat (cons character character))) | ||
| 351 | |||
| 352 | (defcustom electric-pair-skip-self #'electric-pair-default-skip-self | ||
| 335 | "If non-nil, skip char instead of inserting a second closing paren. | 353 | "If non-nil, skip char instead of inserting a second closing paren. |
| 354 | |||
| 336 | When inserting a closing paren character right before the same character, | 355 | When inserting a closing paren character right before the same character, |
| 337 | just skip that character instead, so that hitting ( followed by ) results | 356 | just skip that character instead, so that hitting ( followed by ) results |
| 338 | in \"()\" rather than \"())\". | 357 | in \"()\" rather than \"())\". |
| 339 | This can be convenient for people who find it easier to hit ) than C-f." | 358 | |
| 359 | This can be convenient for people who find it easier to hit ) than C-f. | ||
| 360 | |||
| 361 | Can also be a function of one argument (the closer char just | ||
| 362 | inserted), in which case that function's return value is | ||
| 363 | considered instead." | ||
| 340 | :version "24.1" | 364 | :version "24.1" |
| 341 | :type 'boolean) | 365 | :type '(choice |
| 366 | (const :tag "Never skip" nil) | ||
| 367 | (const :tag "Help balance" electric-pair-default-skip-self) | ||
| 368 | (const :tag "Always skip" t) | ||
| 369 | function)) | ||
| 342 | 370 | ||
| 343 | (defcustom electric-pair-inhibit-predicate | 371 | (defcustom electric-pair-inhibit-predicate |
| 344 | #'electric-pair-default-inhibit | 372 | #'electric-pair-default-inhibit |
| 345 | "Predicate to prevent insertion of a matching pair. | 373 | "Predicate to prevent insertion of a matching pair. |
| 374 | |||
| 346 | The function is called with a single char (the opening char just inserted). | 375 | The function is called with a single char (the opening char just inserted). |
| 347 | If it returns non-nil, then `electric-pair-mode' will not insert a matching | 376 | If it returns non-nil, then `electric-pair-mode' will not insert a matching |
| 348 | closer." | 377 | closer." |
| 349 | :version "24.4" | 378 | :version "24.4" |
| 350 | :type '(choice | 379 | :type '(choice |
| 351 | (const :tag "Default" electric-pair-default-inhibit) | 380 | (const :tag "Conservative" electric-pair-conservative-inhibit) |
| 381 | (const :tag "Help balance" electric-pair-default-inhibit) | ||
| 352 | (const :tag "Always pair" ignore) | 382 | (const :tag "Always pair" ignore) |
| 353 | function)) | 383 | function)) |
| 354 | 384 | ||
| 355 | (defun electric-pair-default-inhibit (char) | 385 | (defcustom electric-pair-preserve-balance t |
| 386 | "Non-nil if default pairing and skipping should help balance parentheses. | ||
| 387 | |||
| 388 | The default values of `electric-pair-inhibit-predicate' and | ||
| 389 | `electric-pair-skip-self' check this variable before delegating to other | ||
| 390 | predicates reponsible for making decisions on whether to pair/skip some | ||
| 391 | characters based on the actual state of the buffer's parenthesis and | ||
| 392 | quotes." | ||
| 393 | :version "24.4" | ||
| 394 | :type 'boolean) | ||
| 395 | |||
| 396 | (defcustom electric-pair-delete-adjacent-pairs t | ||
| 397 | "If non-nil, backspacing an open paren also deletes adjacent closer. | ||
| 398 | |||
| 399 | Can also be a function of no arguments, in which case that function's | ||
| 400 | return value is considered instead." | ||
| 401 | :version "24.4" | ||
| 402 | :type '(choice | ||
| 403 | (const :tag "Yes" t) | ||
| 404 | (const :tag "No" nil) | ||
| 405 | function)) | ||
| 406 | |||
| 407 | (defcustom electric-pair-open-newline-between-pairs t | ||
| 408 | "If non-nil, a newline between adjacent parentheses opens an extra one. | ||
| 409 | |||
| 410 | Can also be a function of no arguments, in which case that function's | ||
| 411 | return value is considered instead." | ||
| 412 | :version "24.4" | ||
| 413 | :type '(choice | ||
| 414 | (const :tag "Yes" t) | ||
| 415 | (const :tag "No" nil) | ||
| 416 | function)) | ||
| 417 | |||
| 418 | (defcustom electric-pair-skip-whitespace t | ||
| 419 | "If non-nil skip whitespace when skipping over closing parens. | ||
| 420 | |||
| 421 | The specific kind of whitespace skipped is given by the variable | ||
| 422 | `electric-pair-skip-whitespace-chars'. | ||
| 423 | |||
| 424 | The symbol `chomp' specifies that the skipped-over whitespace | ||
| 425 | should be deleted. | ||
| 426 | |||
| 427 | Can also be a function of no arguments, in which case that function's | ||
| 428 | return value is considered instead." | ||
| 429 | :version "24.4" | ||
| 430 | :type '(choice | ||
| 431 | (const :tag "Yes, jump over whitespace" t) | ||
| 432 | (const :tag "Yes, and delete whitespace" 'chomp) | ||
| 433 | (const :tag "No, no whitespace skipping" nil) | ||
| 434 | function)) | ||
| 435 | |||
| 436 | (defcustom electric-pair-skip-whitespace-chars (list ?\t ?\s ?\n) | ||
| 437 | "Whitespace characters considered by `electric-pair-skip-whitespace'." | ||
| 438 | :version "24.4" | ||
| 439 | :type '(choice (set (const :tag "Space" ?\s) | ||
| 440 | (const :tag "Tab" ?\t) | ||
| 441 | (const :tag "Newline" ?\n)) | ||
| 442 | (list character))) | ||
| 443 | |||
| 444 | (defun electric-pair--skip-whitespace () | ||
| 445 | "Skip whitespace forward, not crossing comment or string boundaries." | ||
| 446 | (let ((saved (point)) | ||
| 447 | (string-or-comment (nth 8 (syntax-ppss)))) | ||
| 448 | (skip-chars-forward (apply #'string electric-pair-skip-whitespace-chars)) | ||
| 449 | (unless (eq string-or-comment (nth 8 (syntax-ppss))) | ||
| 450 | (goto-char saved)))) | ||
| 451 | |||
| 452 | (defvar electric-pair-text-syntax-table prog-mode-syntax-table | ||
| 453 | "Syntax table used when pairing inside comments and strings. | ||
| 454 | |||
| 455 | `electric-pair-mode' considers this syntax table only when point in inside | ||
| 456 | quotes or comments. If lookup fails here, `electric-pair-text-pairs' will | ||
| 457 | be considered.") | ||
| 458 | |||
| 459 | (defun electric-pair-backward-delete-char (n &optional killflag untabify) | ||
| 460 | "Delete characters backward, and maybe also two adjacent paired delimiters. | ||
| 461 | |||
| 462 | Remaining behaviour is given by `backward-delete-char' or, if UNTABIFY is | ||
| 463 | non-nil, `backward-delete-char-untabify'." | ||
| 464 | (interactive "*p\nP") | ||
| 465 | (let* ((prev (char-before)) | ||
| 466 | (next (char-after)) | ||
| 467 | (syntax-info (electric-pair-syntax-info prev)) | ||
| 468 | (syntax (car syntax-info)) | ||
| 469 | (pair (cadr syntax-info))) | ||
| 470 | (when (and (if (functionp electric-pair-delete-adjacent-pairs) | ||
| 471 | (funcall electric-pair-delete-adjacent-pairs) | ||
| 472 | electric-pair-delete-adjacent-pairs) | ||
| 473 | next | ||
| 474 | (memq syntax '(?\( ?\" ?\$)) | ||
| 475 | (eq pair next)) | ||
| 476 | (delete-char 1 killflag)) | ||
| 477 | (if untabify | ||
| 478 | (backward-delete-char-untabify n killflag) | ||
| 479 | (backward-delete-char n killflag)))) | ||
| 480 | |||
| 481 | (defun electric-pair-backward-delete-char-untabify (n &optional killflag) | ||
| 482 | "Delete characters backward, and maybe also two adjacent paired delimiters. | ||
| 483 | |||
| 484 | Remaining behaviour is given by `backward-delete-char-untabify'." | ||
| 485 | (interactive "*p\nP") | ||
| 486 | (electric-pair-backward-delete-char n killflag t)) | ||
| 487 | |||
| 488 | (defun electric-pair-conservative-inhibit (char) | ||
| 356 | (or | 489 | (or |
| 357 | ;; I find it more often preferable not to pair when the | 490 | ;; I find it more often preferable not to pair when the |
| 358 | ;; same char is next. | 491 | ;; same char is next. |
| @@ -363,14 +496,40 @@ closer." | |||
| 363 | ;; I also find it often preferable not to pair next to a word. | 496 | ;; I also find it often preferable not to pair next to a word. |
| 364 | (eq (char-syntax (following-char)) ?w))) | 497 | (eq (char-syntax (following-char)) ?w))) |
| 365 | 498 | ||
| 366 | (defun electric-pair-syntax (command-event) | 499 | (defun electric-pair-syntax-info (command-event) |
| 367 | (let ((x (assq command-event electric-pair-pairs))) | 500 | "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). |
| 501 | |||
| 502 | SYNTAX is COMMAND-EVENT's syntax character. PAIR is | ||
| 503 | COMMAND-EVENT's pair. UNCONDITIONAL indicates the variables | ||
| 504 | `electric-pair-pairs' or `electric-pair-text-pairs' were used to | ||
| 505 | lookup syntax. STRING-OR-COMMENT-START indicates that point is | ||
| 506 | inside a comment of string." | ||
| 507 | (let* ((pre-string-or-comment (nth 8 (save-excursion | ||
| 508 | (syntax-ppss (1- (point)))))) | ||
| 509 | (post-string-or-comment (nth 8 (syntax-ppss (point)))) | ||
| 510 | (string-or-comment (and post-string-or-comment | ||
| 511 | pre-string-or-comment)) | ||
| 512 | (table (if string-or-comment | ||
| 513 | electric-pair-text-syntax-table | ||
| 514 | (syntax-table))) | ||
| 515 | (table-syntax-and-pair (with-syntax-table table | ||
| 516 | (list (char-syntax command-event) | ||
| 517 | (or (matching-paren command-event) | ||
| 518 | command-event)))) | ||
| 519 | (fallback (if string-or-comment | ||
| 520 | (append electric-pair-text-pairs | ||
| 521 | electric-pair-pairs) | ||
| 522 | electric-pair-pairs)) | ||
| 523 | (direct (assq command-event fallback)) | ||
| 524 | (reverse (rassq command-event fallback))) | ||
| 368 | (cond | 525 | (cond |
| 369 | (x (if (eq (car x) (cdr x)) ?\" ?\()) | 526 | ((memq (car table-syntax-and-pair) |
| 370 | ((rassq command-event electric-pair-pairs) ?\)) | 527 | '(?\" ?\( ?\) ?\$)) |
| 371 | ((nth 8 (syntax-ppss)) | 528 | (append table-syntax-and-pair (list nil string-or-comment))) |
| 372 | (with-syntax-table text-mode-syntax-table (char-syntax command-event))) | 529 | (direct (if (eq (car direct) (cdr direct)) |
| 373 | (t (char-syntax command-event))))) | 530 | (list ?\" command-event t string-or-comment) |
| 531 | (list ?\( (cdr direct) t string-or-comment))) | ||
| 532 | (reverse (list ?\) (car reverse) t string-or-comment))))) | ||
| 374 | 533 | ||
| 375 | (defun electric-pair--insert (char) | 534 | (defun electric-pair--insert (char) |
| 376 | (let ((last-command-event char) | 535 | (let ((last-command-event char) |
| @@ -378,56 +537,297 @@ closer." | |||
| 378 | (electric-pair-mode nil)) | 537 | (electric-pair-mode nil)) |
| 379 | (self-insert-command 1))) | 538 | (self-insert-command 1))) |
| 380 | 539 | ||
| 540 | (defun electric-pair--syntax-ppss (&optional pos where) | ||
| 541 | "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. | ||
| 542 | |||
| 543 | WHERE is list defaulting to '(string comment) and indicates | ||
| 544 | when to fallback to `parse-partial-sexp'." | ||
| 545 | (let* ((pos (or pos (point))) | ||
| 546 | (where (or where '(string comment))) | ||
| 547 | (quick-ppss (syntax-ppss)) | ||
| 548 | (quick-ppss-at-pos (syntax-ppss pos))) | ||
| 549 | (if (or (and (nth 3 quick-ppss) (memq 'string where)) | ||
| 550 | (and (nth 4 quick-ppss) (memq 'comment where))) | ||
| 551 | (with-syntax-table electric-pair-text-syntax-table | ||
| 552 | (parse-partial-sexp (1+ (nth 8 quick-ppss)) pos)) | ||
| 553 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs | ||
| 554 | (if (memq major-mode '(c-mode c++ mode)) | ||
| 555 | (parse-partial-sexp (point-min) pos) | ||
| 556 | quick-ppss-at-pos)))) | ||
| 557 | |||
| 558 | ;; Balancing means controlling pairing and skipping of parentheses so | ||
| 559 | ;; that, if possible, the buffer ends up at least as balanced as | ||
| 560 | ;; before, if not more. The algorithm is slightly complex because some | ||
| 561 | ;; situations like "()))" need pairing to occur at the end but not at | ||
| 562 | ;; the beginning. Balancing should also happen independently for | ||
| 563 | ;; different types of parentheses, so that having your {}'s unbalanced | ||
| 564 | ;; doesn't keep `electric-pair-mode' from balancing your ()'s and your | ||
| 565 | ;; []'s. | ||
| 566 | (defun electric-pair--balance-info (direction string-or-comment) | ||
| 567 | "Examine lists forward or backward according to DIRECTIONS's sign. | ||
| 568 | |||
| 569 | STRING-OR-COMMENT is info suitable for running `parse-partial-sexp'. | ||
| 570 | |||
| 571 | Return a cons of two descritions (MATCHED-P . PAIR) for the | ||
| 572 | innermost and outermost lists that enclose point. The outermost | ||
| 573 | list enclosing point is either the first top-level or first | ||
| 574 | mismatched list found by uplisting. | ||
| 575 | |||
| 576 | If the outermost list is matched, don't rely on its PAIR. If | ||
| 577 | point is not enclosed by any lists, return ((T) (T))." | ||
| 578 | (let* (innermost | ||
| 579 | outermost | ||
| 580 | (table (if string-or-comment | ||
| 581 | electric-pair-text-syntax-table | ||
| 582 | (syntax-table))) | ||
| 583 | (at-top-level-or-equivalent-fn | ||
| 584 | ;; called when `scan-sexps' ran perfectly, when when it | ||
| 585 | ;; found a parenthesis pointing in the direction of | ||
| 586 | ;; travel. Also when travel started inside a comment and | ||
| 587 | ;; exited it | ||
| 588 | #'(lambda () | ||
| 589 | (setq outermost (list t)) | ||
| 590 | (unless innermost | ||
| 591 | (setq innermost (list t))))) | ||
| 592 | (ended-prematurely-fn | ||
| 593 | ;; called when `scan-sexps' crashed against a parenthesis | ||
| 594 | ;; pointing opposite the direction of travel. After | ||
| 595 | ;; traversing that character, the idea is to travel one sexp | ||
| 596 | ;; in the opposite direction looking for a matching | ||
| 597 | ;; delimiter. | ||
| 598 | #'(lambda () | ||
| 599 | (let* ((pos (point)) | ||
| 600 | (matched | ||
| 601 | (save-excursion | ||
| 602 | (cond ((< direction 0) | ||
| 603 | (condition-case nil | ||
| 604 | (eq (char-after pos) | ||
| 605 | (with-syntax-table table | ||
| 606 | (matching-paren | ||
| 607 | (char-before | ||
| 608 | (scan-sexps (point) 1))))) | ||
| 609 | (scan-error nil))) | ||
| 610 | (t | ||
| 611 | ;; In this case, no need to use | ||
| 612 | ;; `scan-sexps', we can use some | ||
| 613 | ;; `electric-pair--syntax-ppss' in this | ||
| 614 | ;; case (which uses the quicker | ||
| 615 | ;; `syntax-ppss' in some cases) | ||
| 616 | (let* ((ppss (electric-pair--syntax-ppss | ||
| 617 | (1- (point)))) | ||
| 618 | (start (car (last (nth 9 ppss)))) | ||
| 619 | (opener (char-after start))) | ||
| 620 | (and start | ||
| 621 | (eq (char-before pos) | ||
| 622 | (or (with-syntax-table table | ||
| 623 | (matching-paren opener)) | ||
| 624 | opener)))))))) | ||
| 625 | (actual-pair (if (> direction 0) | ||
| 626 | (char-before (point)) | ||
| 627 | (char-after (point))))) | ||
| 628 | (unless innermost | ||
| 629 | (setq innermost (cons matched actual-pair))) | ||
| 630 | (unless matched | ||
| 631 | (setq outermost (cons matched actual-pair))))))) | ||
| 632 | (save-excursion | ||
| 633 | (while (not outermost) | ||
| 634 | (condition-case err | ||
| 635 | (with-syntax-table table | ||
| 636 | (scan-sexps (point) (if (> direction 0) | ||
| 637 | (point-max) | ||
| 638 | (- (point-max)))) | ||
| 639 | (funcall at-top-level-or-equivalent-fn)) | ||
| 640 | (scan-error | ||
| 641 | (cond ((or | ||
| 642 | ;; some error happened and it is not of the "ended | ||
| 643 | ;; prematurely" kind"... | ||
| 644 | (not (string-match "ends prematurely" (nth 1 err))) | ||
| 645 | ;; ... or we were in a comment and just came out of | ||
| 646 | ;; it. | ||
| 647 | (and string-or-comment | ||
| 648 | (not (nth 8 (syntax-ppss))))) | ||
| 649 | (funcall at-top-level-or-equivalent-fn)) | ||
| 650 | (t | ||
| 651 | ;; exit the sexp | ||
| 652 | (goto-char (nth 3 err)) | ||
| 653 | (funcall ended-prematurely-fn))))))) | ||
| 654 | (cons innermost outermost))) | ||
| 655 | |||
| 656 | (defun electric-pair--looking-at-unterminated-string-p (char) | ||
| 657 | "Say if following string starts with CHAR and is unterminated." | ||
| 658 | ;; FIXME: ugly/naive | ||
| 659 | (save-excursion | ||
| 660 | (skip-chars-forward (format "^%c" char)) | ||
| 661 | (while (not (zerop (% (save-excursion (skip-syntax-backward "\\")) 2))) | ||
| 662 | (unless (eobp) | ||
| 663 | (forward-char 1) | ||
| 664 | (skip-chars-forward (format "^%c" char)))) | ||
| 665 | (and (not (eobp)) | ||
| 666 | (condition-case err | ||
| 667 | (progn (forward-sexp) nil) | ||
| 668 | (scan-error t))))) | ||
| 669 | |||
| 670 | (defun electric-pair--inside-string-p (char) | ||
| 671 | "Say if point is inside a string started by CHAR. | ||
| 672 | |||
| 673 | A comments text is parsed with `electric-pair-text-syntax-table'. | ||
| 674 | Also consider strings within comments, but not strings within | ||
| 675 | strings." | ||
| 676 | ;; FIXME: could also consider strings within strings by examining | ||
| 677 | ;; delimiters. | ||
| 678 | (let* ((ppss (electric-pair--syntax-ppss (point) '(comment)))) | ||
| 679 | (memq (nth 3 ppss) (list t char)))) | ||
| 680 | |||
| 681 | (defun electric-pair-inhibit-if-helps-balance (char) | ||
| 682 | "Return non-nil if auto-pairing of CHAR would hurt parentheses' balance. | ||
| 683 | |||
| 684 | Works by first removing the character from the buffer, then doing | ||
| 685 | some list calculations, finally restoring the situation as if nothing | ||
| 686 | happened." | ||
| 687 | (pcase (electric-pair-syntax-info char) | ||
| 688 | (`(,syntax ,pair ,_ ,s-or-c) | ||
| 689 | (unwind-protect | ||
| 690 | (progn | ||
| 691 | (delete-char -1) | ||
| 692 | (cond ((eq ?\( syntax) | ||
| 693 | (let* ((pair-data | ||
| 694 | (electric-pair--balance-info 1 s-or-c)) | ||
| 695 | (innermost (car pair-data)) | ||
| 696 | (outermost (cdr pair-data))) | ||
| 697 | (cond ((car outermost) | ||
| 698 | nil) | ||
| 699 | (t | ||
| 700 | (eq (cdr outermost) pair))))) | ||
| 701 | ((eq syntax ?\") | ||
| 702 | (electric-pair--looking-at-unterminated-string-p char)))) | ||
| 703 | (insert-char char))))) | ||
| 704 | |||
| 705 | (defun electric-pair-skip-if-helps-balance (char) | ||
| 706 | "Return non-nil if skipping CHAR would benefit parentheses' balance. | ||
| 707 | |||
| 708 | Works by first removing the character from the buffer, then doing | ||
| 709 | some list calculations, finally restoring the situation as if nothing | ||
| 710 | happened." | ||
| 711 | (pcase (electric-pair-syntax-info char) | ||
| 712 | (`(,syntax ,pair ,_ ,s-or-c) | ||
| 713 | (unwind-protect | ||
| 714 | (progn | ||
| 715 | (delete-char -1) | ||
| 716 | (cond ((eq syntax ?\)) | ||
| 717 | (let* ((pair-data | ||
| 718 | (electric-pair--balance-info | ||
| 719 | -1 s-or-c)) | ||
| 720 | (innermost (car pair-data)) | ||
| 721 | (outermost (cdr pair-data))) | ||
| 722 | (and | ||
| 723 | (cond ((car outermost) | ||
| 724 | (car innermost)) | ||
| 725 | ((car innermost) | ||
| 726 | (not (eq (cdr outermost) pair))))))) | ||
| 727 | ((eq syntax ?\") | ||
| 728 | (electric-pair--inside-string-p char)))) | ||
| 729 | (insert-char char))))) | ||
| 730 | |||
| 731 | (defun electric-pair-default-skip-self (char) | ||
| 732 | (if electric-pair-preserve-balance | ||
| 733 | (electric-pair-skip-if-helps-balance char) | ||
| 734 | t)) | ||
| 735 | |||
| 736 | (defun electric-pair-default-inhibit (char) | ||
| 737 | (if electric-pair-preserve-balance | ||
| 738 | (electric-pair-inhibit-if-helps-balance char) | ||
| 739 | (electric-pair-conservative-inhibit char))) | ||
| 740 | |||
| 381 | (defun electric-pair-post-self-insert-function () | 741 | (defun electric-pair-post-self-insert-function () |
| 382 | (let* ((pos (and electric-pair-mode (electric--after-char-pos))) | 742 | (let* ((pos (and electric-pair-mode (electric--after-char-pos))) |
| 383 | (syntax (and pos (electric-pair-syntax last-command-event))) | 743 | (skip-whitespace-info)) |
| 384 | (closer (if (eq syntax ?\() | 744 | (pcase (electric-pair-syntax-info last-command-event) |
| 385 | (cdr (or (assq last-command-event electric-pair-pairs) | 745 | (`(,syntax ,pair ,unconditional ,_) |
| 386 | (aref (syntax-table) last-command-event))) | 746 | (cond |
| 387 | last-command-event))) | 747 | ((null pos) nil) |
| 388 | (cond | 748 | ;; Wrap a pair around the active region. |
| 389 | ((null pos) nil) | 749 | ;; |
| 390 | ;; Wrap a pair around the active region. | 750 | ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p)) |
| 391 | ((and (memq syntax '(?\( ?\" ?\$)) (use-region-p)) | 751 | ;; FIXME: To do this right, we'd need a post-self-insert-function |
| 392 | ;; FIXME: To do this right, we'd need a post-self-insert-function | 752 | ;; so we could add-function around it and insert the closer after |
| 393 | ;; so we could add-function around it and insert the closer after | 753 | ;; all the rest of the hook has run. |
| 394 | ;; all the rest of the hook has run. | 754 | (if (or (eq syntax ?\") |
| 395 | (if (>= (mark) (point)) | 755 | (and (eq syntax ?\)) |
| 396 | (goto-char (mark)) | 756 | (>= (point) (mark))) |
| 397 | ;; We already inserted the open-paren but at the end of the | 757 | (and (not (eq syntax ?\))) |
| 398 | ;; region, so we have to remove it and start over. | 758 | (>= (mark) (point)))) |
| 399 | (delete-region (1- pos) (point)) | 759 | (save-excursion |
| 400 | (save-excursion | 760 | (goto-char (mark)) |
| 401 | (goto-char (mark)) | 761 | (electric-pair--insert pair)) |
| 402 | (electric-pair--insert last-command-event))) | 762 | (delete-region pos (1- pos)) |
| 403 | ;; Since we're right after the closer now, we could tell the rest of | 763 | (electric-pair--insert pair) |
| 404 | ;; post-self-insert-hook that we inserted `closer', but then we'd get | 764 | (goto-char (mark)) |
| 405 | ;; blink-paren to kick in, which is annoying. | 765 | (electric-pair--insert last-command-event))) |
| 406 | ;;(setq last-command-event closer) | 766 | ;; Backslash-escaped: no pairing, no skipping. |
| 407 | (insert closer)) | 767 | ((save-excursion |
| 408 | ;; Backslash-escaped: no pairing, no skipping. | 768 | (goto-char (1- pos)) |
| 409 | ((save-excursion | 769 | (not (zerop (% (skip-syntax-backward "\\") 2)))) |
| 410 | (goto-char (1- pos)) | 770 | nil) |
| 411 | (not (zerop (% (skip-syntax-backward "\\") 2)))) | 771 | ;; Skip self. |
| 412 | nil) | 772 | ((and (memq syntax '(?\) ?\" ?\$)) |
| 413 | ;; Skip self. | 773 | (and (or unconditional |
| 414 | ((and (memq syntax '(?\) ?\" ?\$)) | 774 | (if (functionp electric-pair-skip-self) |
| 415 | electric-pair-skip-self | 775 | (funcall electric-pair-skip-self last-command-event) |
| 416 | (eq (char-after pos) last-command-event)) | 776 | electric-pair-skip-self)) |
| 417 | ;; This is too late: rather than insert&delete we'd want to only skip (or | 777 | (save-excursion |
| 418 | ;; insert in overwrite mode). The difference is in what goes in the | 778 | (when (setq skip-whitespace-info |
| 419 | ;; undo-log and in the intermediate state which might be visible to other | 779 | (if (functionp electric-pair-skip-whitespace) |
| 420 | ;; post-self-insert-hook. We'll just have to live with it for now. | 780 | (funcall electric-pair-skip-whitespace) |
| 421 | (delete-char 1)) | 781 | electric-pair-skip-whitespace)) |
| 422 | ;; Insert matching pair. | 782 | (electric-pair--skip-whitespace)) |
| 423 | ((not (or (not (memq syntax `(?\( ?\" ?\$))) | 783 | (eq (char-after) last-command-event)))) |
| 424 | overwrite-mode | 784 | ;; This is too late: rather than insert&delete we'd want to only |
| 425 | (funcall electric-pair-inhibit-predicate last-command-event))) | 785 | ;; skip (or insert in overwrite mode). The difference is in what |
| 426 | (save-excursion (electric-pair--insert closer)))))) | 786 | ;; goes in the undo-log and in the intermediate state which might |
| 787 | ;; be visible to other post-self-insert-hook. We'll just have to | ||
| 788 | ;; live with it for now. | ||
| 789 | (when skip-whitespace-info | ||
| 790 | (electric-pair--skip-whitespace)) | ||
| 791 | (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp) | ||
| 792 | (point) | ||
| 793 | pos)) | ||
| 794 | (forward-char)) | ||
| 795 | ;; Insert matching pair. | ||
| 796 | ((and (memq syntax `(?\( ?\" ?\$)) | ||
| 797 | (not overwrite-mode) | ||
| 798 | (or unconditional | ||
| 799 | (not (funcall electric-pair-inhibit-predicate | ||
| 800 | last-command-event)))) | ||
| 801 | (save-excursion (electric-pair--insert pair))))) | ||
| 802 | (t | ||
| 803 | (when (and (if (functionp electric-pair-open-newline-between-pairs) | ||
| 804 | (funcall electric-pair-open-newline-between-pairs) | ||
| 805 | electric-pair-open-newline-between-pairs) | ||
| 806 | (eq last-command-event ?\n) | ||
| 807 | (not (eobp)) | ||
| 808 | (eq (save-excursion | ||
| 809 | (skip-chars-backward "\t\s") | ||
| 810 | (char-before (1- (point)))) | ||
| 811 | (matching-paren (char-after)))) | ||
| 812 | (save-excursion (newline 1 t))))))) | ||
| 813 | |||
| 814 | (put 'electric-pair-post-self-insert-function 'priority 20) | ||
| 427 | 815 | ||
| 428 | (defun electric-pair-will-use-region () | 816 | (defun electric-pair-will-use-region () |
| 429 | (and (use-region-p) | 817 | (and (use-region-p) |
| 430 | (memq (electric-pair-syntax last-command-event) '(?\( ?\" ?\$)))) | 818 | (memq (car (electric-pair-syntax-info last-command-event)) |
| 819 | '(?\( ?\) ?\" ?\$)))) | ||
| 820 | |||
| 821 | (defvar electric-pair-mode-map | ||
| 822 | (let ((map (make-sparse-keymap))) | ||
| 823 | (define-key map [remap backward-delete-char-untabify] | ||
| 824 | 'electric-pair-backward-delete-char-untabify) | ||
| 825 | (define-key map [remap backward-delete-char] | ||
| 826 | 'electric-pair-backward-delete-char) | ||
| 827 | (define-key map [remap delete-backward-char] | ||
| 828 | 'electric-pair-backward-delete-char) | ||
| 829 | map) | ||
| 830 | "Keymap used by `electric-pair-mode'.") | ||
| 431 | 831 | ||
| 432 | ;;;###autoload | 832 | ;;;###autoload |
| 433 | (define-minor-mode electric-pair-mode | 833 | (define-minor-mode electric-pair-mode |
| @@ -438,29 +838,33 @@ the mode if ARG is omitted or nil. | |||
| 438 | 838 | ||
| 439 | Electric Pair mode is a global minor mode. When enabled, typing | 839 | Electric Pair mode is a global minor mode. When enabled, typing |
| 440 | an open parenthesis automatically inserts the corresponding | 840 | an open parenthesis automatically inserts the corresponding |
| 441 | closing parenthesis. \(Likewise for brackets, etc.) | 841 | closing parenthesis. \(Likewise for brackets, etc.)." |
| 442 | |||
| 443 | See options `electric-pair-pairs' and `electric-pair-skip-self'." | ||
| 444 | :global t :group 'electricity | 842 | :global t :group 'electricity |
| 445 | (if electric-pair-mode | 843 | (if electric-pair-mode |
| 446 | (progn | 844 | (progn |
| 447 | (add-hook 'post-self-insert-hook | 845 | (add-hook 'post-self-insert-hook |
| 448 | #'electric-pair-post-self-insert-function) | 846 | #'electric-pair-post-self-insert-function) |
| 847 | (electric--sort-post-self-insertion-hook) | ||
| 449 | (add-hook 'self-insert-uses-region-functions | 848 | (add-hook 'self-insert-uses-region-functions |
| 450 | #'electric-pair-will-use-region)) | 849 | #'electric-pair-will-use-region)) |
| 451 | (remove-hook 'post-self-insert-hook | 850 | (remove-hook 'post-self-insert-hook |
| 452 | #'electric-pair-post-self-insert-function) | 851 | #'electric-pair-post-self-insert-function) |
| 453 | (remove-hook 'self-insert-uses-region-functions | 852 | (remove-hook 'self-insert-uses-region-functions |
| 454 | #'electric-pair-will-use-region))) | 853 | #'electric-pair-will-use-region))) |
| 455 | 854 | ||
| 456 | ;;; Electric newlines after/before/around some chars. | 855 | ;;; Electric newlines after/before/around some chars. |
| 457 | 856 | ||
| 458 | (defvar electric-layout-rules '() | 857 | (defvar electric-layout-rules nil |
| 459 | "List of rules saying where to automatically insert newlines. | 858 | "List of rules saying where to automatically insert newlines. |
| 460 | Each rule has the form (CHAR . WHERE) where CHAR is the char | 859 | |
| 461 | that was just inserted and WHERE specifies where to insert newlines | 860 | Each rule has the form (CHAR . WHERE) where CHAR is the char that |
| 462 | and can be: nil, `before', `after', `around', or a function of no | 861 | was just inserted and WHERE specifies where to insert newlines |
| 463 | arguments that returns one of those symbols.") | 862 | and can be: nil, `before', `after', `around', `after-stay', or a |
| 863 | function of no arguments that returns one of those symbols. | ||
| 864 | |||
| 865 | The symbols specify where in relation to CHAR the newline | ||
| 866 | character(s) should be inserted. `after-stay' means insert a | ||
| 867 | newline after CHAR but stay in the same place.") | ||
| 464 | 868 | ||
| 465 | (defun electric-layout-post-self-insert-function () | 869 | (defun electric-layout-post-self-insert-function () |
| 466 | (let* ((rule (cdr (assq last-command-event electric-layout-rules))) | 870 | (let* ((rule (cdr (assq last-command-event electric-layout-rules))) |
| @@ -469,23 +873,32 @@ arguments that returns one of those symbols.") | |||
| 469 | (setq pos (electric--after-char-pos)) | 873 | (setq pos (electric--after-char-pos)) |
| 470 | ;; Not in a string or comment. | 874 | ;; Not in a string or comment. |
| 471 | (not (nth 8 (save-excursion (syntax-ppss pos))))) | 875 | (not (nth 8 (save-excursion (syntax-ppss pos))))) |
| 472 | (let ((end (copy-marker (point) t))) | 876 | (let ((end (copy-marker (point))) |
| 877 | (sym (if (functionp rule) (funcall rule) rule))) | ||
| 878 | (set-marker-insertion-type end (not (eq sym 'after-stay))) | ||
| 473 | (goto-char pos) | 879 | (goto-char pos) |
| 474 | (pcase (if (functionp rule) (funcall rule) rule) | 880 | (pcase sym |
| 475 | ;; FIXME: we used `newline' down here which called | 881 | ;; FIXME: we used `newline' down here which called |
| 476 | ;; self-insert-command and ran post-self-insert-hook recursively. | 882 | ;; self-insert-command and ran post-self-insert-hook recursively. |
| 477 | ;; It happened to make electric-indent-mode work automatically with | 883 | ;; It happened to make electric-indent-mode work automatically with |
| 478 | ;; electric-layout-mode (at the cost of re-indenting lines | 884 | ;; electric-layout-mode (at the cost of re-indenting lines |
| 479 | ;; multiple times), but I'm not sure it's what we want. | 885 | ;; multiple times), but I'm not sure it's what we want. |
| 886 | ;; | ||
| 887 | ;; FIXME: check eolp before inserting \n? | ||
| 480 | (`before (goto-char (1- pos)) (skip-chars-backward " \t") | 888 | (`before (goto-char (1- pos)) (skip-chars-backward " \t") |
| 481 | (unless (bolp) (insert "\n"))) | 889 | (unless (bolp) (insert "\n"))) |
| 482 | (`after (insert "\n")) ; FIXME: check eolp before inserting \n? | 890 | (`after (insert "\n")) |
| 891 | (`after-stay (save-excursion | ||
| 892 | (let ((electric-layout-rules nil)) | ||
| 893 | (newline 1 t)))) | ||
| 483 | (`around (save-excursion | 894 | (`around (save-excursion |
| 484 | (goto-char (1- pos)) (skip-chars-backward " \t") | 895 | (goto-char (1- pos)) (skip-chars-backward " \t") |
| 485 | (unless (bolp) (insert "\n"))) | 896 | (unless (bolp) (insert "\n"))) |
| 486 | (insert "\n"))) ; FIXME: check eolp before inserting \n? | 897 | (insert "\n"))) ; FIXME: check eolp before inserting \n? |
| 487 | (goto-char end))))) | 898 | (goto-char end))))) |
| 488 | 899 | ||
| 900 | (put 'electric-layout-post-self-insert-function 'priority 40) | ||
| 901 | |||
| 489 | ;;;###autoload | 902 | ;;;###autoload |
| 490 | (define-minor-mode electric-layout-mode | 903 | (define-minor-mode electric-layout-mode |
| 491 | "Automatically insert newlines around some chars. | 904 | "Automatically insert newlines around some chars. |
| @@ -494,11 +907,13 @@ positive, and disable it otherwise. If called from Lisp, enable | |||
| 494 | the mode if ARG is omitted or nil. | 907 | the mode if ARG is omitted or nil. |
| 495 | The variable `electric-layout-rules' says when and how to insert newlines." | 908 | The variable `electric-layout-rules' says when and how to insert newlines." |
| 496 | :global t :group 'electricity | 909 | :global t :group 'electricity |
| 497 | (if electric-layout-mode | 910 | (cond (electric-layout-mode |
| 498 | (add-hook 'post-self-insert-hook | 911 | (add-hook 'post-self-insert-hook |
| 499 | #'electric-layout-post-self-insert-function) | 912 | #'electric-layout-post-self-insert-function) |
| 500 | (remove-hook 'post-self-insert-hook | 913 | (electric--sort-post-self-insertion-hook)) |
| 501 | #'electric-layout-post-self-insert-function))) | 914 | (t |
| 915 | (remove-hook 'post-self-insert-hook | ||
| 916 | #'electric-layout-post-self-insert-function)))) | ||
| 502 | 917 | ||
| 503 | (provide 'electric) | 918 | (provide 'electric) |
| 504 | 919 | ||
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index b7bd33f628f..f1eae18c507 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el | |||
| @@ -472,7 +472,13 @@ font-lock keywords will not be case sensitive." | |||
| 472 | (font-lock-mark-block-function . mark-defun) | 472 | (font-lock-mark-block-function . mark-defun) |
| 473 | (font-lock-syntactic-face-function | 473 | (font-lock-syntactic-face-function |
| 474 | . lisp-font-lock-syntactic-face-function))) | 474 | . lisp-font-lock-syntactic-face-function))) |
| 475 | (setq-local prettify-symbols-alist lisp--prettify-symbols-alist)) | 475 | (setq-local prettify-symbols-alist lisp--prettify-symbols-alist) |
| 476 | ;; electric | ||
| 477 | (when elisp | ||
| 478 | (setq-local electric-pair-text-pairs | ||
| 479 | (cons '(?\` . ?\') electric-pair-text-pairs))) | ||
| 480 | (setq-local electric-pair-skip-whitespace 'chomp) | ||
| 481 | (setq-local electric-pair-open-newline-between-pairs nil)) | ||
| 476 | 482 | ||
| 477 | (defun lisp-outline-level () | 483 | (defun lisp-outline-level () |
| 478 | "Lisp mode `outline-level' function." | 484 | "Lisp mode `outline-level' function." |
diff --git a/lisp/simple.el b/lisp/simple.el index a6543516a9c..624d87fd655 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -610,7 +610,7 @@ In some text modes, where TAB inserts a tab, this command indents to the | |||
| 610 | column specified by the function `current-left-margin'." | 610 | column specified by the function `current-left-margin'." |
| 611 | (interactive "*") | 611 | (interactive "*") |
| 612 | (delete-horizontal-space t) | 612 | (delete-horizontal-space t) |
| 613 | (newline) | 613 | (newline 1 t) |
| 614 | (indent-according-to-mode)) | 614 | (indent-according-to-mode)) |
| 615 | 615 | ||
| 616 | (defun reindent-then-newline-and-indent () | 616 | (defun reindent-then-newline-and-indent () |
| @@ -6448,10 +6448,14 @@ More precisely, a char with closeparen syntax is self-inserted.") | |||
| 6448 | (point)))))) | 6448 | (point)))))) |
| 6449 | (funcall blink-paren-function))) | 6449 | (funcall blink-paren-function))) |
| 6450 | 6450 | ||
| 6451 | (put 'blink-paren-post-self-insert-function 'priority 100) | ||
| 6452 | |||
| 6451 | (add-hook 'post-self-insert-hook #'blink-paren-post-self-insert-function | 6453 | (add-hook 'post-self-insert-hook #'blink-paren-post-self-insert-function |
| 6452 | ;; Most likely, this hook is nil, so this arg doesn't matter, | 6454 | ;; Most likely, this hook is nil, so this arg doesn't matter, |
| 6453 | ;; but I use it as a reminder that this function usually | 6455 | ;; but I use it as a reminder that this function usually |
| 6454 | ;; likes to be run after others since it does `sit-for'. | 6456 | ;; likes to be run after others since it does |
| 6457 | ;; `sit-for'. That's also the reason it get a `priority' prop | ||
| 6458 | ;; of 100. | ||
| 6455 | 'append) | 6459 | 'append) |
| 6456 | 6460 | ||
| 6457 | ;; This executes C-g typed while Emacs is waiting for a command. | 6461 | ;; This executes C-g typed while Emacs is waiting for a command. |