diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2019-05-29 15:56:14 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2019-05-29 15:56:14 -0400 |
commit | fe0cb43fb80db52a79ef898f8de49560cc5cdd90 (patch) | |
tree | 4825956db223eb96d69583e707cbf13a4d280789 /lisp/subr.el | |
parent | 49cdbb4a35f8d1d2139e8469bffcf33f65679094 (diff) | |
download | emacs-fe0cb43fb80db52a79ef898f8de49560cc5cdd90.tar.gz |
* 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.
Diffstat (limited to 'lisp/subr.el')
-rw-r--r-- | lisp/subr.el | 39 |
1 files changed, 32 insertions, 7 deletions
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'." ;;;; Hook manipulation functions. -(defun add-hook (hook function &optional append local) +(defun add-hook (hook function &optional depth local) + ;; Note: the -100..100 depth range is arbitrary and was chosen to match the + ;; range used in add-function. "Add to the value of HOOK the function FUNCTION. FUNCTION is not added if already present. -FUNCTION is added (if necessary) at the beginning of the hook list -unless the optional argument APPEND is non-nil, in which case -FUNCTION is added at the end. + +The place where the function is added depends on the DEPTH +parameter. DEPTH defaults to 0. By convention, it should be +a number between -100 and 100 where 100 means that the function +should be at the very end of the list, whereas -100 means that +the function should always come first. +Since nothing is \"always\" true, don't use 100 nor -100. +When two functions have the same depth, the new one gets added after the +old one if depth is strictly positive and before otherwise. + +For backward compatibility reasons, a symbol other than nil is +interpreted as a DEPTH of 90. The optional fourth argument, LOCAL, if non-nil, says to modify 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 function, it is changed to a list of functions." (or (boundp hook) (set hook nil)) (or (default-boundp hook) (set-default hook nil)) + (unless (numberp depth) (setq depth (if depth 90 0))) (if local (unless (local-variable-if-set-p hook) (set (make-local-variable hook) (list t))) ;; 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." (setq hook-value (list hook-value))) ;; Do the actual addition if necessary (unless (member function hook-value) - (when (stringp function) + (when (stringp function) ;FIXME: Why? (setq function (purecopy function))) + (when (or (get hook 'hook--depth-alist) (not (zerop depth))) + ;; Note: The main purpose of the above `when' test is to avoid running + ;; this `setf' before `gv' is loaded during bootstrap. + (setf (alist-get function (get hook 'hook--depth-alist) + 0 'remove #'equal) + depth)) (setq hook-value - (if append + (if (< 0 depth) (append hook-value (list function)) - (cons function hook-value)))) + (cons function hook-value))) + (let ((depth-alist (get hook 'hook--depth-alist))) + (when depth-alist + (setq hook-value + (sort (if (< 0 depth) hook-value (copy-sequence hook-value)) + (lambda (f1 f2) + (< (alist-get f1 depth-alist 0 nil #'equal) + (alist-get f2 depth-alist 0 nil #'equal)))))))) ;; Set the actual variable (if local (progn |