diff options
| author | Stefan Monnier | 2019-05-29 15:56:14 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2019-05-29 15:56:14 -0400 |
| commit | fe0cb43fb80db52a79ef898f8de49560cc5cdd90 (patch) | |
| tree | 4825956db223eb96d69583e707cbf13a4d280789 | |
| parent | 49cdbb4a35f8d1d2139e8469bffcf33f65679094 (diff) | |
| download | emacs-fe0cb43fb80db52a79ef898f8de49560cc5cdd90.tar.gz emacs-fe0cb43fb80db52a79ef898f8de49560cc5cdd90.zip | |
* lisp/subr.el (add-hook): Turn `append` into `depth` (bug#35508)
Make it possible to control the relative ordering of functions on hooks by
specifying `depth` in the same was as was possible with `add-function`.
* lisp/electric.el (electric--sort-post-self-insertion-hook):
Delete function.
(electric-indent-mode, electric-layout-mode, electric-quote-mode):
* lisp/elec-pair.el (electric-pair-mode): Use new `depth` arg instead of
electric--sort-post-self-insertion-hook.
* lisp/emacs-lisp/syntax.el (syntax-propertize, syntax-ppss):
Use new `depth` arg to make sure noone accidentally gets added
after syntax-ppss-flush-cache.
* doc/lispref/modes.texi (Setting Hooks): Document new `depth` arg.
* test/lisp/subr-tests.el (subr-tests-add-hook-depth): New test.
| -rw-r--r-- | doc/lispref/modes.texi | 17 | ||||
| -rw-r--r-- | etc/NEWS | 13 | ||||
| -rw-r--r-- | lisp/elec-pair.el | 19 | ||||
| -rw-r--r-- | lisp/electric.el | 29 | ||||
| -rw-r--r-- | lisp/emacs-lisp/syntax.el | 13 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 3 | ||||
| -rw-r--r-- | lisp/subr.el | 39 | ||||
| -rw-r--r-- | test/lisp/subr-tests.el | 33 |
8 files changed, 113 insertions, 53 deletions
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 97e9be9918f..27c5d77579f 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi | |||
| @@ -142,7 +142,7 @@ in Lisp Interaction mode: | |||
| 142 | (add-hook 'lisp-interaction-mode-hook 'auto-fill-mode) | 142 | (add-hook 'lisp-interaction-mode-hook 'auto-fill-mode) |
| 143 | @end example | 143 | @end example |
| 144 | 144 | ||
| 145 | @defun add-hook hook function &optional append local | 145 | @defun add-hook hook function &optional depth local |
| 146 | This function is the handy way to add function @var{function} to hook | 146 | This function is the handy way to add function @var{function} to hook |
| 147 | variable @var{hook}. You can use it for abnormal hooks as well as for | 147 | variable @var{hook}. You can use it for abnormal hooks as well as for |
| 148 | normal hooks. @var{function} can be any Lisp function that can accept | 148 | normal hooks. @var{function} can be any Lisp function that can accept |
| @@ -167,9 +167,18 @@ For a normal hook, hook functions should be designed so that the order | |||
| 167 | in which they are executed does not matter. Any dependence on the order | 167 | in which they are executed does not matter. Any dependence on the order |
| 168 | is asking for trouble. However, the order is predictable: normally, | 168 | is asking for trouble. However, the order is predictable: normally, |
| 169 | @var{function} goes at the front of the hook list, so it is executed | 169 | @var{function} goes at the front of the hook list, so it is executed |
| 170 | first (barring another @code{add-hook} call). If the optional argument | 170 | first (barring another @code{add-hook} call). |
| 171 | @var{append} is non-@code{nil}, the new hook function goes at the end of | 171 | |
| 172 | the hook list and is executed last. | 172 | In some cases, it is important to control the relative ordering of functions |
| 173 | on the hook. The optional argument @var{depth} lets you indicate where the | ||
| 174 | function should be inserted in the list: it should then be a number | ||
| 175 | between -100 and 100 where the higher the value, the closer to the end of the | ||
| 176 | list the function should go. The @var{depth} defaults to 0 and for backward | ||
| 177 | compatibility when @var{depth} is a non-nil symbol it is interpreted as a depth | ||
| 178 | of 90. Furthermore, when @var{depth} is strictly greater than 0 the function | ||
| 179 | is added @emph{after} rather than before functions of the same depth. | ||
| 180 | One should never use a depth of 100 (or -100), because one can never be | ||
| 181 | sure that no other function will ever need to come before (or after) us. | ||
| 173 | 182 | ||
| 174 | @code{add-hook} can handle the cases where @var{hook} is void or its | 183 | @code{add-hook} can handle the cases where @var{hook} is void or its |
| 175 | value is a single function; it sets or changes the value to a list of | 184 | value is a single function; it sets or changes the value to a list of |
| @@ -1508,6 +1508,13 @@ documentation of the new mode and its commands. | |||
| 1508 | 1508 | ||
| 1509 | * Incompatible Lisp Changes in Emacs 27.1 | 1509 | * Incompatible Lisp Changes in Emacs 27.1 |
| 1510 | 1510 | ||
| 1511 | +++ | ||
| 1512 | ** add-hook does not always add to the front or the end any more. | ||
| 1513 | The replacement of `append` with `depth` implies that the function is not | ||
| 1514 | always added to the very front (when append/depth is nil) or the very end (when | ||
| 1515 | append/depth is t) any more because other functions on the hook may have | ||
| 1516 | specified higher/lower depths. | ||
| 1517 | |||
| 1511 | ** In 'compilation-error-regexp-alist' the old undocumented feature | 1518 | ** In 'compilation-error-regexp-alist' the old undocumented feature |
| 1512 | where 'line' could be a function of 2 arguments has been dropped. | 1519 | where 'line' could be a function of 2 arguments has been dropped. |
| 1513 | 1520 | ||
| @@ -1639,6 +1646,12 @@ valid event type. | |||
| 1639 | 1646 | ||
| 1640 | * Lisp Changes in Emacs 27.1 | 1647 | * Lisp Changes in Emacs 27.1 |
| 1641 | 1648 | ||
| 1649 | +++ | ||
| 1650 | ** The 'append' arg of 'add-hook' is generalized to a finer notion of 'depth' | ||
| 1651 | This makes it possible to control the ordering of functions more precisely, | ||
| 1652 | as was already possible in 'add-function' and `advice-add`. | ||
| 1653 | |||
| 1654 | --- | ||
| 1642 | ** New 'help-fns-describe-variable-functions' hook. | 1655 | ** New 'help-fns-describe-variable-functions' hook. |
| 1643 | Makes it possible to add metadata information to 'describe-variable'. | 1656 | Makes it possible to add metadata information to 'describe-variable'. |
| 1644 | 1657 | ||
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 3be09d87b4f..5fb9d751e25 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el | |||
| @@ -246,7 +246,7 @@ functions when `parse-sexp-lookup-properties' is non-nil. The | |||
| 246 | cache is flushed from position START, defaulting to point." | 246 | cache is flushed from position START, defaulting to point." |
| 247 | (declare (debug ((form &optional form) body)) (indent 1)) | 247 | (declare (debug ((form &optional form) body)) (indent 1)) |
| 248 | (let ((start-var (make-symbol "start"))) | 248 | (let ((start-var (make-symbol "start"))) |
| 249 | `(let ((syntax-propertize-function nil) | 249 | `(let ((syntax-propertize-function #'ignore) |
| 250 | (,start-var ,(or start '(point)))) | 250 | (,start-var ,(or start '(point)))) |
| 251 | (unwind-protect | 251 | (unwind-protect |
| 252 | (with-syntax-table ,table | 252 | (with-syntax-table ,table |
| @@ -564,13 +564,6 @@ happened." | |||
| 564 | (matching-paren (char-after)))) | 564 | (matching-paren (char-after)))) |
| 565 | (save-excursion (newline 1 t))))))) | 565 | (save-excursion (newline 1 t))))))) |
| 566 | 566 | ||
| 567 | ;; Prioritize this to kick in after | ||
| 568 | ;; `electric-layout-post-self-insert-function': that considerably | ||
| 569 | ;; simplifies interoperation when `electric-pair-mode', | ||
| 570 | ;; `electric-layout-mode' and `electric-indent-mode' are used | ||
| 571 | ;; together. Use `vc-region-history' on these lines for more info. | ||
| 572 | (put 'electric-pair-post-self-insert-function 'priority 50) | ||
| 573 | |||
| 574 | (defun electric-pair-will-use-region () | 567 | (defun electric-pair-will-use-region () |
| 575 | (and (use-region-p) | 568 | (and (use-region-p) |
| 576 | (memq (car (electric-pair-syntax-info last-command-event)) | 569 | (memq (car (electric-pair-syntax-info last-command-event)) |
| @@ -622,8 +615,14 @@ To toggle the mode in a single buffer, use `electric-pair-local-mode'." | |||
| 622 | (if electric-pair-mode | 615 | (if electric-pair-mode |
| 623 | (progn | 616 | (progn |
| 624 | (add-hook 'post-self-insert-hook | 617 | (add-hook 'post-self-insert-hook |
| 625 | #'electric-pair-post-self-insert-function) | 618 | #'electric-pair-post-self-insert-function |
| 626 | (electric--sort-post-self-insertion-hook) | 619 | ;; Prioritize this to kick in after |
| 620 | ;; `electric-layout-post-self-insert-function': that | ||
| 621 | ;; considerably simplifies interoperation when | ||
| 622 | ;; `electric-pair-mode', `electric-layout-mode' and | ||
| 623 | ;; `electric-indent-mode' are used together. | ||
| 624 | ;; Use `vc-region-history' on these lines for more info. | ||
| 625 | 50) | ||
| 627 | (add-hook 'self-insert-uses-region-functions | 626 | (add-hook 'self-insert-uses-region-functions |
| 628 | #'electric-pair-will-use-region)) | 627 | #'electric-pair-will-use-region)) |
| 629 | (remove-hook 'post-self-insert-hook | 628 | (remove-hook 'post-self-insert-hook |
diff --git a/lisp/electric.el b/lisp/electric.el index 07da2f1d9e7..53e53bd975c 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -190,17 +190,6 @@ Returns nil when we can't find this char." | |||
| 190 | (eq (char-before) last-command-event))))) | 190 | (eq (char-before) last-command-event))))) |
| 191 | pos))) | 191 | pos))) |
| 192 | 192 | ||
| 193 | (defun electric--sort-post-self-insertion-hook () | ||
| 194 | "Ensure order of electric functions in `post-self-insertion-hook'. | ||
| 195 | |||
| 196 | Hooks in this variable interact in non-trivial ways, so a | ||
| 197 | relative order must be maintained within it." | ||
| 198 | (setq-default post-self-insert-hook | ||
| 199 | (sort (default-value 'post-self-insert-hook) | ||
| 200 | #'(lambda (fn1 fn2) | ||
| 201 | (< (or (if (symbolp fn1) (get fn1 'priority)) 0) | ||
| 202 | (or (if (symbolp fn2) (get fn2 'priority)) 0)))))) | ||
| 203 | |||
| 204 | ;;; Electric indentation. | 193 | ;;; Electric indentation. |
| 205 | 194 | ||
| 206 | ;; Autoloading variables is generally undesirable, but major modes | 195 | ;; Autoloading variables is generally undesirable, but major modes |
| @@ -297,8 +286,6 @@ or comment." | |||
| 297 | (indent-according-to-mode) | 286 | (indent-according-to-mode) |
| 298 | (error (throw 'indent-error nil))))))))) | 287 | (error (throw 'indent-error nil))))))))) |
| 299 | 288 | ||
| 300 | (put 'electric-indent-post-self-insert-function 'priority 60) | ||
| 301 | |||
| 302 | (defun electric-indent-just-newline (arg) | 289 | (defun electric-indent-just-newline (arg) |
| 303 | "Insert just a newline, without any auto-indentation." | 290 | "Insert just a newline, without any auto-indentation." |
| 304 | (interactive "*P") | 291 | (interactive "*P") |
| @@ -341,8 +328,8 @@ use `electric-indent-local-mode'." | |||
| 341 | (remove-hook 'post-self-insert-hook | 328 | (remove-hook 'post-self-insert-hook |
| 342 | #'electric-indent-post-self-insert-function)) | 329 | #'electric-indent-post-self-insert-function)) |
| 343 | (add-hook 'post-self-insert-hook | 330 | (add-hook 'post-self-insert-hook |
| 344 | #'electric-indent-post-self-insert-function) | 331 | #'electric-indent-post-self-insert-function |
| 345 | (electric--sort-post-self-insertion-hook))) | 332 | 60))) |
| 346 | 333 | ||
| 347 | ;;;###autoload | 334 | ;;;###autoload |
| 348 | (define-minor-mode electric-indent-local-mode | 335 | (define-minor-mode electric-indent-local-mode |
| @@ -472,8 +459,6 @@ If multiple rules match, only first one is executed.") | |||
| 472 | ('after-stay (save-excursion (funcall nl-after))) | 459 | ('after-stay (save-excursion (funcall nl-after))) |
| 473 | ('around (funcall nl-before) (funcall nl-after)))))))) | 460 | ('around (funcall nl-before) (funcall nl-after)))))))) |
| 474 | 461 | ||
| 475 | (put 'electric-layout-post-self-insert-function 'priority 40) | ||
| 476 | |||
| 477 | ;;;###autoload | 462 | ;;;###autoload |
| 478 | (define-minor-mode electric-layout-mode | 463 | (define-minor-mode electric-layout-mode |
| 479 | "Automatically insert newlines around some chars. | 464 | "Automatically insert newlines around some chars. |
| @@ -482,8 +467,8 @@ The variable `electric-layout-rules' says when and how to insert newlines." | |||
| 482 | :global t :group 'electricity | 467 | :global t :group 'electricity |
| 483 | (cond (electric-layout-mode | 468 | (cond (electric-layout-mode |
| 484 | (add-hook 'post-self-insert-hook | 469 | (add-hook 'post-self-insert-hook |
| 485 | #'electric-layout-post-self-insert-function) | 470 | #'electric-layout-post-self-insert-function |
| 486 | (electric--sort-post-self-insertion-hook)) | 471 | 40)) |
| 487 | (t | 472 | (t |
| 488 | (remove-hook 'post-self-insert-hook | 473 | (remove-hook 'post-self-insert-hook |
| 489 | #'electric-layout-post-self-insert-function)))) | 474 | #'electric-layout-post-self-insert-function)))) |
| @@ -623,8 +608,6 @@ This requotes when a quoting key is typed." | |||
| 623 | (replace-match (string q>>)) | 608 | (replace-match (string q>>)) |
| 624 | (setq last-command-event q>>)))))))))) | 609 | (setq last-command-event q>>)))))))))) |
| 625 | 610 | ||
| 626 | (put 'electric-quote-post-self-insert-function 'priority 10) | ||
| 627 | |||
| 628 | ;;;###autoload | 611 | ;;;###autoload |
| 629 | (define-minor-mode electric-quote-mode | 612 | (define-minor-mode electric-quote-mode |
| 630 | "Toggle on-the-fly requoting (Electric Quote mode). | 613 | "Toggle on-the-fly requoting (Electric Quote mode). |
| @@ -651,8 +634,8 @@ use `electric-quote-local-mode'." | |||
| 651 | (remove-hook 'post-self-insert-hook | 634 | (remove-hook 'post-self-insert-hook |
| 652 | #'electric-quote-post-self-insert-function)) | 635 | #'electric-quote-post-self-insert-function)) |
| 653 | (add-hook 'post-self-insert-hook | 636 | (add-hook 'post-self-insert-hook |
| 654 | #'electric-quote-post-self-insert-function) | 637 | #'electric-quote-post-self-insert-function |
| 655 | (electric--sort-post-self-insertion-hook))) | 638 | 10))) |
| 656 | 639 | ||
| 657 | ;;;###autoload | 640 | ;;;###autoload |
| 658 | (define-minor-mode electric-quote-local-mode | 641 | (define-minor-mode electric-quote-local-mode |
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index f1904e64efb..9c6d5b5829f 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el | |||
| @@ -298,7 +298,7 @@ END) suitable for `syntax-propertize-function'." | |||
| 298 | ;; between syntax-ppss and syntax-propertize, we also have to make | 298 | ;; between syntax-ppss and syntax-propertize, we also have to make |
| 299 | ;; sure the flush function is installed here (bug#29767). | 299 | ;; sure the flush function is installed here (bug#29767). |
| 300 | (add-hook 'before-change-functions | 300 | (add-hook 'before-change-functions |
| 301 | #'syntax-ppss-flush-cache t t)) | 301 | #'syntax-ppss-flush-cache 99 t)) |
| 302 | (save-excursion | 302 | (save-excursion |
| 303 | (with-silent-modifications | 303 | (with-silent-modifications |
| 304 | (make-local-variable 'syntax-propertize--done) ;Just in case! | 304 | (make-local-variable 'syntax-propertize--done) ;Just in case! |
| @@ -430,7 +430,7 @@ These are valid when the buffer has no restriction.") | |||
| 430 | ;; Unregister if there's no cache left. Sadly this doesn't work | 430 | ;; Unregister if there's no cache left. Sadly this doesn't work |
| 431 | ;; because `before-change-functions' is temporarily bound to nil here. | 431 | ;; because `before-change-functions' is temporarily bound to nil here. |
| 432 | ;; (unless cache | 432 | ;; (unless cache |
| 433 | ;; (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t)) | 433 | ;; (remove-hook 'before-change-functions #'syntax-ppss-flush-cache t)) |
| 434 | (setcar cell last) | 434 | (setcar cell last) |
| 435 | (setcdr cell cache))) | 435 | (setcdr cell cache))) |
| 436 | )) | 436 | )) |
| @@ -534,13 +534,14 @@ running the hook." | |||
| 534 | 534 | ||
| 535 | ;; Setup the before-change function if necessary. | 535 | ;; Setup the before-change function if necessary. |
| 536 | (unless (or ppss-cache ppss-last) | 536 | (unless (or ppss-cache ppss-last) |
| 537 | ;; We should be either the very last function on | ||
| 538 | ;; before-change-functions or the very first on | ||
| 539 | ;; after-change-functions. | ||
| 540 | ;; Note: combine-change-calls-1 needs to be kept in sync | 537 | ;; Note: combine-change-calls-1 needs to be kept in sync |
| 541 | ;; with this! | 538 | ;; with this! |
| 542 | (add-hook 'before-change-functions | 539 | (add-hook 'before-change-functions |
| 543 | 'syntax-ppss-flush-cache t t)) | 540 | #'syntax-ppss-flush-cache |
| 541 | ;; We should be either the very last function on | ||
| 542 | ;; before-change-functions or the very first on | ||
| 543 | ;; after-change-functions. | ||
| 544 | 99 t)) | ||
| 544 | 545 | ||
| 545 | ;; Use the best of OLD-POS and CACHE. | 546 | ;; Use the best of OLD-POS and CACHE. |
| 546 | (if (or (not old-pos) (< old-pos pt-min)) | 547 | (if (or (not old-pos) (< old-pos pt-min)) |
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index e4ff9f019d3..74fcc97226c 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -653,6 +653,9 @@ that requires a literal mode spec at compile time." | |||
| 653 | (make-local-hook 'after-change-functions)) | 653 | (make-local-hook 'after-change-functions)) |
| 654 | (add-hook 'before-change-functions 'c-before-change nil t) | 654 | (add-hook 'before-change-functions 'c-before-change nil t) |
| 655 | (setq c-just-done-before-change nil) | 655 | (setq c-just-done-before-change nil) |
| 656 | ;; FIXME: We should use the new `depth' arg in Emacs-27 (e.g. a depth of -10 | ||
| 657 | ;; would do since font-lock uses a(n implicit) depth of 0) so we don't need | ||
| 658 | ;; c-after-font-lock-init. | ||
| 656 | (add-hook 'after-change-functions 'c-after-change nil t) | 659 | (add-hook 'after-change-functions 'c-after-change nil t) |
| 657 | (when (boundp 'font-lock-extend-after-change-region-function) | 660 | (when (boundp 'font-lock-extend-after-change-region-function) |
| 658 | (set (make-local-variable 'font-lock-extend-after-change-region-function) | 661 | (set (make-local-variable 'font-lock-extend-after-change-region-function) |
diff --git a/lisp/subr.el b/lisp/subr.el index 05fb9fea68f..fd60ec87cca 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -1604,12 +1604,23 @@ be a list of the form returned by `event-start' and `event-end'." | |||
| 1604 | 1604 | ||
| 1605 | ;;;; Hook manipulation functions. | 1605 | ;;;; Hook manipulation functions. |
| 1606 | 1606 | ||
| 1607 | (defun add-hook (hook function &optional append local) | 1607 | (defun add-hook (hook function &optional depth local) |
| 1608 | ;; Note: the -100..100 depth range is arbitrary and was chosen to match the | ||
| 1609 | ;; range used in add-function. | ||
| 1608 | "Add to the value of HOOK the function FUNCTION. | 1610 | "Add to the value of HOOK the function FUNCTION. |
| 1609 | FUNCTION is not added if already present. | 1611 | FUNCTION is not added if already present. |
| 1610 | FUNCTION is added (if necessary) at the beginning of the hook list | 1612 | |
| 1611 | unless the optional argument APPEND is non-nil, in which case | 1613 | The place where the function is added depends on the DEPTH |
| 1612 | FUNCTION is added at the end. | 1614 | parameter. DEPTH defaults to 0. By convention, it should be |
| 1615 | a number between -100 and 100 where 100 means that the function | ||
| 1616 | should be at the very end of the list, whereas -100 means that | ||
| 1617 | the function should always come first. | ||
| 1618 | Since nothing is \"always\" true, don't use 100 nor -100. | ||
| 1619 | When two functions have the same depth, the new one gets added after the | ||
| 1620 | old one if depth is strictly positive and before otherwise. | ||
| 1621 | |||
| 1622 | For backward compatibility reasons, a symbol other than nil is | ||
| 1623 | interpreted as a DEPTH of 90. | ||
| 1613 | 1624 | ||
| 1614 | The optional fourth argument, LOCAL, if non-nil, says to modify | 1625 | The optional fourth argument, LOCAL, if non-nil, says to modify |
| 1615 | the hook's buffer-local value rather than its global value. | 1626 | the hook's buffer-local value rather than its global value. |
| @@ -1622,6 +1633,7 @@ HOOK is void, it is first set to nil. If HOOK's value is a single | |||
| 1622 | function, it is changed to a list of functions." | 1633 | function, it is changed to a list of functions." |
| 1623 | (or (boundp hook) (set hook nil)) | 1634 | (or (boundp hook) (set hook nil)) |
| 1624 | (or (default-boundp hook) (set-default hook nil)) | 1635 | (or (default-boundp hook) (set-default hook nil)) |
| 1636 | (unless (numberp depth) (setq depth (if depth 90 0))) | ||
| 1625 | (if local (unless (local-variable-if-set-p hook) | 1637 | (if local (unless (local-variable-if-set-p hook) |
| 1626 | (set (make-local-variable hook) (list t))) | 1638 | (set (make-local-variable hook) (list t))) |
| 1627 | ;; Detect the case where make-local-variable was used on a hook | 1639 | ;; Detect the case where make-local-variable was used on a hook |
| @@ -1634,12 +1646,25 @@ function, it is changed to a list of functions." | |||
| 1634 | (setq hook-value (list hook-value))) | 1646 | (setq hook-value (list hook-value))) |
| 1635 | ;; Do the actual addition if necessary | 1647 | ;; Do the actual addition if necessary |
| 1636 | (unless (member function hook-value) | 1648 | (unless (member function hook-value) |
| 1637 | (when (stringp function) | 1649 | (when (stringp function) ;FIXME: Why? |
| 1638 | (setq function (purecopy function))) | 1650 | (setq function (purecopy function))) |
| 1651 | (when (or (get hook 'hook--depth-alist) (not (zerop depth))) | ||
| 1652 | ;; Note: The main purpose of the above `when' test is to avoid running | ||
| 1653 | ;; this `setf' before `gv' is loaded during bootstrap. | ||
| 1654 | (setf (alist-get function (get hook 'hook--depth-alist) | ||
| 1655 | 0 'remove #'equal) | ||
| 1656 | depth)) | ||
| 1639 | (setq hook-value | 1657 | (setq hook-value |
| 1640 | (if append | 1658 | (if (< 0 depth) |
| 1641 | (append hook-value (list function)) | 1659 | (append hook-value (list function)) |
| 1642 | (cons function hook-value)))) | 1660 | (cons function hook-value))) |
| 1661 | (let ((depth-alist (get hook 'hook--depth-alist))) | ||
| 1662 | (when depth-alist | ||
| 1663 | (setq hook-value | ||
| 1664 | (sort (if (< 0 depth) hook-value (copy-sequence hook-value)) | ||
| 1665 | (lambda (f1 f2) | ||
| 1666 | (< (alist-get f1 depth-alist 0 nil #'equal) | ||
| 1667 | (alist-get f2 depth-alist 0 nil #'equal)))))))) | ||
| 1643 | ;; Set the actual variable | 1668 | ;; Set the actual variable |
| 1644 | (if local | 1669 | (if local |
| 1645 | (progn | 1670 | (progn |
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index c458eef2f93..06db8f5c902 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el | |||
| @@ -61,6 +61,9 @@ | |||
| 61 | (quote | 61 | (quote |
| 62 | (0 font-lock-keyword-face)))))))) | 62 | (0 font-lock-keyword-face)))))))) |
| 63 | 63 | ||
| 64 | (defalias 'subr-tests--parent-mode | ||
| 65 | (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)) | ||
| 66 | |||
| 64 | (ert-deftest provided-mode-derived-p () | 67 | (ert-deftest provided-mode-derived-p () |
| 65 | ;; base case: `derived-mode' directly derives `prog-mode' | 68 | ;; base case: `derived-mode' directly derives `prog-mode' |
| 66 | (should (progn | 69 | (should (progn |
| @@ -68,9 +71,7 @@ | |||
| 68 | (provided-mode-derived-p 'derived-mode 'prog-mode))) | 71 | (provided-mode-derived-p 'derived-mode 'prog-mode))) |
| 69 | ;; edge case: `derived-mode' derives an alias of `prog-mode' | 72 | ;; edge case: `derived-mode' derives an alias of `prog-mode' |
| 70 | (should (progn | 73 | (should (progn |
| 71 | (defalias 'parent-mode | 74 | (define-derived-mode derived-mode subr-tests--parent-mode "test") |
| 72 | (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)) | ||
| 73 | (define-derived-mode derived-mode parent-mode "test") | ||
| 74 | (provided-mode-derived-p 'derived-mode 'prog-mode)))) | 75 | (provided-mode-derived-p 'derived-mode 'prog-mode)))) |
| 75 | 76 | ||
| 76 | (ert-deftest number-sequence-test () | 77 | (ert-deftest number-sequence-test () |
| @@ -373,5 +374,31 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350." | |||
| 373 | (should (equal (flatten-tree '(1 ("foo" "bar") 2)) | 374 | (should (equal (flatten-tree '(1 ("foo" "bar") 2)) |
| 374 | '(1 "foo" "bar" 2)))) | 375 | '(1 "foo" "bar" 2)))) |
| 375 | 376 | ||
| 377 | (defvar subr-tests--hook nil) | ||
| 378 | |||
| 379 | (ert-deftest subr-tests-add-hook-depth () | ||
| 380 | "Test the `depth' arg of `add-hook'." | ||
| 381 | (setq-default subr-tests--hook nil) | ||
| 382 | (add-hook 'subr-tests--hook 'f1) | ||
| 383 | (add-hook 'subr-tests--hook 'f2) | ||
| 384 | (should (equal subr-tests--hook '(f2 f1))) | ||
| 385 | (add-hook 'subr-tests--hook 'f3 t) | ||
| 386 | (should (equal subr-tests--hook '(f2 f1 f3))) | ||
| 387 | (add-hook 'subr-tests--hook 'f4 50) | ||
| 388 | (should (equal subr-tests--hook '(f2 f1 f4 f3))) | ||
| 389 | (add-hook 'subr-tests--hook 'f5 -50) | ||
| 390 | (should (equal subr-tests--hook '(f5 f2 f1 f4 f3))) | ||
| 391 | (add-hook 'subr-tests--hook 'f6) | ||
| 392 | (should (equal subr-tests--hook '(f5 f6 f2 f1 f4 f3))) | ||
| 393 | ;; Make sure `t' is equivalent to 90. | ||
| 394 | (add-hook 'subr-tests--hook 'f7 90) | ||
| 395 | (add-hook 'subr-tests--hook 'f8 t) | ||
| 396 | (should (equal subr-tests--hook '(f5 f6 f2 f1 f4 f3 f7 f8))) | ||
| 397 | ;; Make sue `nil' is equivalent to 0. | ||
| 398 | (add-hook 'subr-tests--hook 'f9 0) | ||
| 399 | (add-hook 'subr-tests--hook 'f10) | ||
| 400 | (should (equal subr-tests--hook '(f5 f10 f9 f6 f2 f1 f4 f3 f7 f8))) | ||
| 401 | ) | ||
| 402 | |||
| 376 | (provide 'subr-tests) | 403 | (provide 'subr-tests) |
| 377 | ;;; subr-tests.el ends here | 404 | ;;; subr-tests.el ends here |