From: Phil Sainty Date: Mon, 22 Apr 2019 06:14:55 +0000 (+1200) Subject: Add :before-hook keyword to define-derived-mode X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=196b9760e3218c19478628213796900e35fffb74;p=emacs.git 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" --- 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 @@ -1632,6 +1632,12 @@ be deleted has been made dead and removed from the frame list. 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. 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