summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Sainty <psainty@orcon.net.nz>2019-04-22 18:14:55 +1200
committerPhil Sainty <psainty@orcon.net.nz>2019-04-22 18:14:55 +1200
commit196b9760e3218c19478628213796900e35fffb74 (patch)
treeae74954d42c3cfcf4dc5a25636ca208d3919075f
parente85bff0bbb60e1d819f8f5e00f8496026f27f7ea (diff)
downloademacs-196b9760e3218c19478628213796900e35fffb74.tar.gz
Add :before-hook keyword to define-derived-mode
* lisp/emacs-lisp/derived.el (define-derived-mode): New keyword * doc/lispref/modes.texi: Update "(elisp) Derived Modes" * etc/NEWS: Include under "Lisp Changes in Emacs 27.1"
-rw-r--r--doc/lispref/modes.texi12
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/emacs-lisp/derived.el8
3 files changed, 24 insertions, 2 deletions
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 4315b70ed72..925017dbc0c 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -807,8 +807,8 @@ 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,
-except for @code{:after-hook}'s, are evaluated. The following
-keywords are currently supported:
+except for those of @code{:before-hook} and @code{:after-hook}, are
+evaluated. The following keywords are currently supported:
@table @code
@item :syntax-table
@@ -832,6 +832,14 @@ this mode. (Not all major modes have one.) The command
@code{customize-mode} uses this. @code{define-derived-mode} does
@emph{not} automatically define the specified customization group.
+@item :before-hook
+This optional keyword specifies a single Lisp form to evaluate as the
+very first act of the mode function, before any of the functions in
+@code{change-major-mode-hook} have been called. It should not be
+quoted. A @code{:before-hook} form is useful when the mode needs to
+see the original buffer state, before @code{kill-all-local-variables}
+has taken effect.
+
@item :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.
diff --git a/etc/NEWS b/etc/NEWS
index 4d76143b134..00fc933acb9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1633,6 +1633,12 @@ The function now returns non-nil when the argument MODE is derived
from any alias of any of MODES.
+++
+** 'define-derived-mode' can now specify a :before-hook form, which
+is evaluated before the 'change-major-mode-hook' functions. This allows
+the macro to be used to define mode functions which need to act before
+'kill-all-local-variables'.
+
++++
** New frame focus state inspection interface.
The hooks 'focus-in-hook' and 'focus-out-hook' are now obsolete.
Instead, attach to 'after-focus-change-function' using 'add-function'
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index 6db0584b987..00aa70a10aa 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.
+:before-hook FORM
+ A single lisp form which will be evaluated before anything else
+ happens in `change-major-mode-hook'. It should not be quoted.
:after-hook FORM
A single lisp form which is evaluated after the mode hooks have been
run. It should not be quoted.
@@ -188,6 +191,7 @@ See Info node `(elisp)Derived Modes' for more details."
(declare-syntax t)
(hook (derived-mode-hook-name child))
(group nil)
+ (before-hook nil)
(after-hook nil))
;; Process the keyword args.
@@ -196,6 +200,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))
+ (:before-hook (setq before-hook (pop body)))
(:after-hook (setq after-hook (pop body)))
(_ (pop body))))
@@ -241,6 +246,9 @@ No problems result if this variable is not bound.
(defun ,child ()
,docstring
(interactive)
+ ,@(when before-hook
+ `((add-hook 'change-major-mode-hook (lambda () ,before-hook)
+ nil t)))
; Run the parent.
(delay-mode-hooks