summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2019-05-29 15:56:14 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2019-05-29 15:56:14 -0400
commitfe0cb43fb80db52a79ef898f8de49560cc5cdd90 (patch)
tree4825956db223eb96d69583e707cbf13a4d280789 /lisp
parent49cdbb4a35f8d1d2139e8469bffcf33f65679094 (diff)
downloademacs-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')
-rw-r--r--lisp/elec-pair.el19
-rw-r--r--lisp/electric.el29
-rw-r--r--lisp/emacs-lisp/syntax.el13
-rw-r--r--lisp/progmodes/cc-mode.el3
-rw-r--r--lisp/subr.el39
5 files changed, 57 insertions, 46 deletions
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
cache is flushed from position START, defaulting to point."
(declare (debug ((form &optional form) body)) (indent 1))
(let ((start-var (make-symbol "start")))
- `(let ((syntax-propertize-function nil)
+ `(let ((syntax-propertize-function #'ignore)
(,start-var ,(or start '(point))))
(unwind-protect
(with-syntax-table ,table
@@ -564,13 +564,6 @@ happened."
(matching-paren (char-after))))
(save-excursion (newline 1 t)))))))
-;; Prioritize this to kick in after
-;; `electric-layout-post-self-insert-function': that considerably
-;; simplifies interoperation when `electric-pair-mode',
-;; `electric-layout-mode' and `electric-indent-mode' are used
-;; together. Use `vc-region-history' on these lines for more info.
-(put 'electric-pair-post-self-insert-function 'priority 50)
-
(defun electric-pair-will-use-region ()
(and (use-region-p)
(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'."
(if electric-pair-mode
(progn
(add-hook 'post-self-insert-hook
- #'electric-pair-post-self-insert-function)
- (electric--sort-post-self-insertion-hook)
+ #'electric-pair-post-self-insert-function
+ ;; Prioritize this to kick in after
+ ;; `electric-layout-post-self-insert-function': that
+ ;; considerably simplifies interoperation when
+ ;; `electric-pair-mode', `electric-layout-mode' and
+ ;; `electric-indent-mode' are used together.
+ ;; Use `vc-region-history' on these lines for more info.
+ 50)
(add-hook 'self-insert-uses-region-functions
#'electric-pair-will-use-region))
(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."
(eq (char-before) last-command-event)))))
pos)))
-(defun electric--sort-post-self-insertion-hook ()
- "Ensure order of electric functions in `post-self-insertion-hook'.
-
-Hooks in this variable interact in non-trivial ways, so a
-relative order must be maintained within it."
- (setq-default post-self-insert-hook
- (sort (default-value 'post-self-insert-hook)
- #'(lambda (fn1 fn2)
- (< (or (if (symbolp fn1) (get fn1 'priority)) 0)
- (or (if (symbolp fn2) (get fn2 'priority)) 0))))))
-
;;; Electric indentation.
;; Autoloading variables is generally undesirable, but major modes
@@ -297,8 +286,6 @@ or comment."
(indent-according-to-mode)
(error (throw 'indent-error nil)))))))))
-(put 'electric-indent-post-self-insert-function 'priority 60)
-
(defun electric-indent-just-newline (arg)
"Insert just a newline, without any auto-indentation."
(interactive "*P")
@@ -341,8 +328,8 @@ use `electric-indent-local-mode'."
(remove-hook 'post-self-insert-hook
#'electric-indent-post-self-insert-function))
(add-hook 'post-self-insert-hook
- #'electric-indent-post-self-insert-function)
- (electric--sort-post-self-insertion-hook)))
+ #'electric-indent-post-self-insert-function
+ 60)))
;;;###autoload
(define-minor-mode electric-indent-local-mode
@@ -472,8 +459,6 @@ If multiple rules match, only first one is executed.")
('after-stay (save-excursion (funcall nl-after)))
('around (funcall nl-before) (funcall nl-after))))))))
-(put 'electric-layout-post-self-insert-function 'priority 40)
-
;;;###autoload
(define-minor-mode electric-layout-mode
"Automatically insert newlines around some chars.
@@ -482,8 +467,8 @@ The variable `electric-layout-rules' says when and how to insert newlines."
:global t :group 'electricity
(cond (electric-layout-mode
(add-hook 'post-self-insert-hook
- #'electric-layout-post-self-insert-function)
- (electric--sort-post-self-insertion-hook))
+ #'electric-layout-post-self-insert-function
+ 40))
(t
(remove-hook 'post-self-insert-hook
#'electric-layout-post-self-insert-function))))
@@ -623,8 +608,6 @@ This requotes when a quoting key is typed."
(replace-match (string q>>))
(setq last-command-event q>>))))))))))
-(put 'electric-quote-post-self-insert-function 'priority 10)
-
;;;###autoload
(define-minor-mode electric-quote-mode
"Toggle on-the-fly requoting (Electric Quote mode).
@@ -651,8 +634,8 @@ use `electric-quote-local-mode'."
(remove-hook 'post-self-insert-hook
#'electric-quote-post-self-insert-function))
(add-hook 'post-self-insert-hook
- #'electric-quote-post-self-insert-function)
- (electric--sort-post-self-insertion-hook)))
+ #'electric-quote-post-self-insert-function
+ 10)))
;;;###autoload
(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'."
;; between syntax-ppss and syntax-propertize, we also have to make
;; sure the flush function is installed here (bug#29767).
(add-hook 'before-change-functions
- #'syntax-ppss-flush-cache t t))
+ #'syntax-ppss-flush-cache 99 t))
(save-excursion
(with-silent-modifications
(make-local-variable 'syntax-propertize--done) ;Just in case!
@@ -430,7 +430,7 @@ These are valid when the buffer has no restriction.")
;; Unregister if there's no cache left. Sadly this doesn't work
;; because `before-change-functions' is temporarily bound to nil here.
;; (unless cache
- ;; (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t))
+ ;; (remove-hook 'before-change-functions #'syntax-ppss-flush-cache t))
(setcar cell last)
(setcdr cell cache)))
))
@@ -534,13 +534,14 @@ running the hook."
;; Setup the before-change function if necessary.
(unless (or ppss-cache ppss-last)
- ;; We should be either the very last function on
- ;; before-change-functions or the very first on
- ;; after-change-functions.
;; Note: combine-change-calls-1 needs to be kept in sync
;; with this!
(add-hook 'before-change-functions
- 'syntax-ppss-flush-cache t t))
+ #'syntax-ppss-flush-cache
+ ;; We should be either the very last function on
+ ;; before-change-functions or the very first on
+ ;; after-change-functions.
+ 99 t))
;; Use the best of OLD-POS and CACHE.
(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."
(make-local-hook 'after-change-functions))
(add-hook 'before-change-functions 'c-before-change nil t)
(setq c-just-done-before-change nil)
+ ;; FIXME: We should use the new `depth' arg in Emacs-27 (e.g. a depth of -10
+ ;; would do since font-lock uses a(n implicit) depth of 0) so we don't need
+ ;; c-after-font-lock-init.
(add-hook 'after-change-functions 'c-after-change nil t)
(when (boundp 'font-lock-extend-after-change-region-function)
(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'."
;;;; 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