[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 2eb6817: Add :after-hook facility to define-derived
From: |
Alan Mackenzie |
Subject: |
[Emacs-diffs] master 2eb6817: Add :after-hook facility to define-derived-mode. |
Date: |
Sun, 8 May 2016 13:27:08 +0000 (UTC) |
branch: master
commit 2eb6817ba971184cc109f8530f4b3b38f65650ea
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>
Add :after-hook facility to define-derived-mode.
This allow a form to be evaluated _after_ a major mode's hooks have been
run.
It is needed to solve some problems in CC Mode, including bug #16759 and
bug #23476.
* lisp/emacs-lisp/derived.el (define-derived-mode): introduce the new
argument
`:after-hook', and generate the requisite code for it.
(derived-mode-make-docstring): Take account of the possibility of
:after-hook.
* lisp/subr.el (delayed-after-hook-forms): New variable.
(run-mode-hooks): As the last thing evaluate the forms in
delayed-after-hook-forms.
* doc/lispref/modes.texi (Derived Modes): Document :after-hook.
(Mode Hooks): Document the new feature in run-mode-hooks.
* etc/NEWS: Note the new feature.
---
doc/lispref/modes.texi | 26 ++++++++++++++++++++------
etc/NEWS | 6 ++++++
lisp/emacs-lisp/derived.el | 15 ++++++++++++---
lisp/subr.el | 19 +++++++++++++++----
4 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 76e5174..7b76e6a 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -752,7 +752,8 @@ The new mode has its own abbrev table, kept in the variable
@item
The new mode has its own mode hook, @address@hidden It
runs this hook, after running the hooks of its ancestor modes, with
address@hidden, as the last thing it does. @xref{Mode Hooks}.
address@hidden, as the last thing it does, apart from running
+any @code{:after-hook} form it may have. @xref{Mode Hooks}.
@end itemize
In addition, you can specify how to override other aspects of
@@ -776,8 +777,9 @@ about the mode's hook, followed by the mode's keymap, at
the end of this
documentation string. If you omit @var{docstring},
@code{define-derived-mode} generates a documentation string.
-The @var{keyword-args} are pairs of keywords and values. The values
-are evaluated. The following keywords are currently supported:
+The @var{keyword-args} are pairs of keywords and values. The values,
+except for @code{:after-hook}'s, are evaluated. The following
+keywords are currently supported:
@table @code
@item :syntax-table
@@ -801,6 +803,15 @@ this mode. (Not all major modes have one.) Only the
(still
experimental and unadvertised) command @code{customize-mode} currently
uses this. @code{define-derived-mode} does @emph{not} automatically
define the specified customization group.
+
address@hidden :after-hook
+This optional keyword specifies a single Lisp form to evaluate as the
+final act of the mode function, after the mode hooks have been run.
+It should not be quoted. Since the form might be evaluated after the
+mode function has terminated, it should not access any element of the
+mode function's local state. An @code{:after-hook} form is useful for
+setting up aspects of the mode which depend on the user's settings,
+which in turn may have been changed in a mode hook.
@end table
Here is a hypothetical example:
@@ -912,12 +923,15 @@ Major modes should run their mode hook using this
function. It is
similar to @code{run-hooks} (@pxref{Hooks}), but it also runs
@code{change-major-mode-after-body-hook}, @code{hack-local-variables}
(when the buffer is visiting a file) (@pxref{File Local Variables}),
-and @code{after-change-major-mode-hook}.
+and @code{after-change-major-mode-hook}. The last thing it does is to
+evaluate any @code{:after-hook} forms declared by parent modes
+(@pxref{Derived Modes}).
When this function is called during the execution of a
@code{delay-mode-hooks} form, it does not run the hooks or
address@hidden immediately. Instead, it arranges for the
-next call to @code{run-mode-hooks} to run them.
address@hidden or evaluate the forms immediately.
+Instead, it arranges for the next call to @code{run-mode-hooks} to run
+them.
@end defun
@defmac delay-mode-hooks address@hidden
diff --git a/etc/NEWS b/etc/NEWS
index 92d301e..22eb2ea 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -369,6 +369,12 @@ variable.
** New var syntax-ppss-table to control the syntax-table used in syntax-ppss.
++++
+** `define-derived-mode' can now specify an :after-hook form, which
+gets evaluated after the new mode's hook has run. This can be used to
+incorporate configuration changes made in the mode hook into the
+mode's setup.
+
** Autoload files can be generated without timestamps,
by setting 'autoload-timestamps' to nil.
FIXME As an experiment, nil is the current default.
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index a615f9a..0f7691a 100644
--- a/lisp/emacs-lisp/derived.el
+++ b/lisp/emacs-lisp/derived.el
@@ -137,6 +137,9 @@ BODY can start with a bunch of keyword arguments. The
following keyword
:abbrev-table TABLE
Use TABLE instead of the default (CHILD-abbrev-table).
A nil value means to simply use the same abbrev-table as the parent.
+:after-hook FORM
+ A single lisp form which is evaluated after the mode hooks have been
+ run. It should not be quoted.
Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode:
@@ -184,7 +187,8 @@ See Info node `(elisp)Derived Modes' for more details."
(declare-abbrev t)
(declare-syntax t)
(hook (derived-mode-hook-name child))
- (group nil))
+ (group nil)
+ (after-hook nil))
;; Process the keyword args.
(while (keywordp (car body))
@@ -192,6 +196,7 @@ See Info node `(elisp)Derived Modes' for more details."
(`:group (setq group (pop body)))
(`:abbrev-table (setq abbrev (pop body)) (setq declare-abbrev nil))
(`:syntax-table (setq syntax (pop body)) (setq declare-syntax nil))
+ (`:after-hook (setq after-hook (pop body)))
(_ (pop body))))
(setq docstring (derived-mode-make-docstring
@@ -272,7 +277,11 @@ No problems result if this variable is not bound.
,@body
)
;; Run the hooks, if any.
- (run-mode-hooks ',hook)))))
+ (run-mode-hooks ',hook)
+ ,@(when after-hook
+ `((if delay-mode-hooks
+ (push ',after-hook delayed-after-hook-forms)
+ ,after-hook)))))))
;; PUBLIC: find the ultimate class of a derived mode.
@@ -344,7 +353,7 @@ which more-or-less shadow%s %s's corresponding table%s."
(format "`%s' " parent))
"might have run,\nthis mode "))
(format "runs the hook `%s'" hook)
- ", as the final step\nduring initialization.")))
+ ", as the final or penultimate step\nduring
initialization.")))
(unless (string-match "\\\\[{[]" docstring)
;; And don't forget to put the mode's keymap.
diff --git a/lisp/subr.el b/lisp/subr.el
index 094710b..0fa6404 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1736,6 +1736,11 @@ if it is empty or a duplicate."
(make-variable-buffer-local 'delayed-mode-hooks)
(put 'delay-mode-hooks 'permanent-local t)
+(defvar delayed-after-hook-forms nil
+ "List of delayed :after-hook forms waiting to be run.
+These forms come from `define-derived-mode'.")
+(make-variable-buffer-local 'delayed-after-hook-forms)
+
(defvar change-major-mode-after-body-hook nil
"Normal hook run in major mode functions, before the mode hooks.")
@@ -1751,9 +1756,12 @@ If the variable `delay-mode-hooks' is non-nil, does not
do anything,
just adds the HOOKS to the list `delayed-mode-hooks'.
Otherwise, runs hooks in the sequence: `change-major-mode-after-body-hook',
`delayed-mode-hooks' (in reverse order), HOOKS, then runs
-`hack-local-variables' and finally runs the hook
-`after-change-major-mode-hook'. Major mode functions should use
-this instead of `run-hooks' when running their FOO-mode-hook."
+`hack-local-variables', runs the hook `after-change-major-mode-hook', and
+finally evaluates the forms in `delayed-after-hook-forms' (see
+`define-derived-mode').
+
+Major mode functions should use this instead of `run-hooks' when
+running their FOO-mode-hook."
(if delay-mode-hooks
;; Delaying case.
(dolist (hook hooks)
@@ -1765,7 +1773,10 @@ this instead of `run-hooks' when running their
FOO-mode-hook."
(if (buffer-file-name)
(with-demoted-errors "File local-variables error: %s"
(hack-local-variables 'no-mode)))
- (run-hooks 'after-change-major-mode-hook)))
+ (run-hooks 'after-change-major-mode-hook)
+ (dolist (form (nreverse delayed-after-hook-forms))
+ (eval form))
+ (setq delayed-after-hook-forms nil)))
(defmacro delay-mode-hooks (&rest body)
"Execute BODY, but delay any `run-mode-hooks'.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master 2eb6817: Add :after-hook facility to define-derived-mode.,
Alan Mackenzie <=