From: Stefan Monnier Date: Sat, 13 Apr 2024 14:31:28 +0000 (-0400) Subject: (define-globalized-minor-mode): Require the use of `run-mode-hooks` X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=938c345b12a75fc5900f0368e303f850e45f0c95;p=emacs.git (define-globalized-minor-mode): Require the use of `run-mode-hooks` When `define-globalized-minor-mode` was introduced (Emacs-22), `run-mode-hooks` was brand new, so we could not expect all major modes to use it and we had to rely on brittle workarounds to try and approximate `after-change-major-mode-hook`. These workarounds have undesirable side effects, and (we hope) they're not needed any more now that virtually all major modes have been changed to use `run-mode-hooks` (or `define-derived-mode`). * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Rely only on `after-change-major-mode-hook`, remove the "cmhh" [typo for the intended "cmmh", BTW] workaround. * doc/lispref/modes.texi (Mode Hooks): Clarify the importance of `after-change-major-mode-hook` w.r.t `define-globalized-minor-mode`. (Defining Minor Modes): Rewrite the explanation of which buffers are affected, including adjusting it to the fact that `fundamental-mode` has used run `run-mode-hooks` for last 10 years. (cherry picked from commit 17e26cf57e18c5df2172a7049591d89fc53b3fb6) --- diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index b034fecd77b..ffede9e86f5 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -1109,7 +1109,10 @@ Versions before 24 did not have @code{change-major-mode-after-body-hook}. When user-implemented major modes do not use @code{run-mode-hooks} and have not been updated to use these newer features, they won't entirely follow these conventions: they may run the parent's mode hook too early, -or fail to run @code{after-change-major-mode-hook}. If you encounter +or fail to run @code{after-change-major-mode-hook}. This will +have undesirable effects such as preventing minor modes defined +with @code{define-globalized-minor-mode} from being enabled in +buffers using these major modes. If you encounter such a major mode, please correct it to follow these conventions. When you define a major mode using @code{define-derived-mode}, it @@ -1985,10 +1988,10 @@ turn on the minor mode in a buffer, it uses the function function so it could determine whether to enable the minor mode or not when it is not a priori clear that it should always be enabled.) -Globally enabling the mode also affects buffers subsequently created -by visiting files, and buffers that use a major mode other than -Fundamental mode; but it does not detect the creation of a new buffer -in Fundamental mode. +Globally enabling the mode affects only those buffers subsequently +created that use a major mode which follows the convention to run +@code{run-mode-hooks}. The minor mode will not be enabled in those +major modes which fail to follow this convention. This macro defines the customization option @var{global-mode} (@pxref{Customization}), which can be toggled via the Customize diff --git a/etc/NEWS b/etc/NEWS index 69dfc9643ef..09d47ccaafa 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1782,6 +1782,14 @@ documentation and examples. * Incompatible Lisp Changes in Emacs 30.1 ++++ +** 'define-globalized-minor-mode' requires that modes use 'run-mode-hooks'. +Minor modes defined with 'define-globalized-minor-mode', such as +'global-font-lock-mode', will not be enabled any more in those buffers +whose major modes fails to use 'run-mode-hooks'. Major modes defined +with 'define-derived-mode' are not affected. `run-mode-hooks` has been the +recommended way to run major mode hooks since Emacs-22. + --- ** Old derived.el functions removed. The following functions have been deleted because they were only used diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index b09466d79fc..eaad9646985 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -495,11 +495,6 @@ on if the hook has explicitly disabled it. (MODE-buffers (intern (concat global-mode-name "-buffers"))) (MODE-enable-in-buffer (intern (concat global-mode-name "-enable-in-buffer"))) - (MODE-enable-in-buffers - (intern (concat global-mode-name "-enable-in-buffers"))) - (MODE-check-buffers - (intern (concat global-mode-name "-check-buffers"))) - (MODE-cmhh (intern (concat global-mode-name "-cmhh"))) (minor-MODE-hook (intern (concat mode-name "-hook"))) (MODE-set-explicitly (intern (concat mode-name "-set-explicitly"))) (MODE-major-mode (intern (concat (symbol-name mode) "-major-mode"))) @@ -559,14 +554,9 @@ Disable the mode if ARG is a negative number.\n\n" ;; Setup hook to handle future mode changes and new buffers. (if ,global-mode - (progn - (add-hook 'after-change-major-mode-hook - #',MODE-enable-in-buffer) - (add-hook 'find-file-hook #',MODE-check-buffers) - (add-hook 'change-major-mode-hook #',MODE-cmhh)) - (remove-hook 'after-change-major-mode-hook #',MODE-enable-in-buffer) - (remove-hook 'find-file-hook #',MODE-check-buffers) - (remove-hook 'change-major-mode-hook #',MODE-cmhh)) + (add-hook 'after-change-major-mode-hook + #',MODE-enable-in-buffer) + (remove-hook 'after-change-major-mode-hook #',MODE-enable-in-buffer)) ;; Go through existing buffers. (dolist (buf (buffer-list)) @@ -623,51 +613,7 @@ list." (funcall ,turn-on-function)) (funcall ,turn-on-function)))) (setq ,MODE-major-mode major-mode)) - (put ',MODE-enable-in-buffer 'definition-name ',global-mode) - - ;; In the normal case, major modes run `after-change-major-mode-hook' - ;; which will have called `MODE-enable-in-buffer' for us. But some - ;; major modes don't use `run-mode-hooks' (customarily used via - ;; `define-derived-mode') and thus fail to run - ;; `after-change-major-mode-hook'. - ;; The functions below try to handle those major modes, with - ;; a combination of ugly hacks to try and catch those corner - ;; cases by listening to `change-major-mode-hook' to discover - ;; potential candidates and then checking in `post-command-hook' - ;; and `find-file-hook' if some of those still haven't run - ;; `after-change-major-mode-hook'. FIXME: We should try and get - ;; rid of this ugly hack and rely purely on - ;; `after-change-major-mode-hook' because they can (and do) end - ;; up running `MODE-enable-in-buffer' too early (when the major - ;; isn't yet fully setup) in some cases (see bug#58888). - - ;; The function that calls TURN-ON in each buffer. - (defun ,MODE-enable-in-buffers () - (let ((buffers ,MODE-buffers)) - ;; Clear MODE-buffers to avoid scanning the same list of - ;; buffers in recursive calls to MODE-enable-in-buffers. - ;; Otherwise it could lead to infinite recursion. - (setq ,MODE-buffers nil) - (dolist (buf buffers) - (when (buffer-live-p buf) - (with-current-buffer buf - (,MODE-enable-in-buffer)))))) - (put ',MODE-enable-in-buffers 'definition-name ',global-mode) - - (defun ,MODE-check-buffers () - (,MODE-enable-in-buffers) - (remove-hook 'post-command-hook #',MODE-check-buffers)) - (put ',MODE-check-buffers 'definition-name ',global-mode) - - ;; The function that catches kill-all-local-variables. - (defun ,MODE-cmhh () - ;; If `delay-mode-hooks' is set, it indicates that the current - ;; buffer's mode will run `run-mode-hooks' afterwards anyway, - ;; so we don't need to keep this buffer in MODE-buffers. - (unless delay-mode-hooks - (add-to-list ',MODE-buffers (current-buffer)) - (add-hook 'post-command-hook #',MODE-check-buffers))) - (put ',MODE-cmhh 'definition-name ',global-mode)))) + (put ',MODE-enable-in-buffer 'definition-name ',global-mode)))) (defun easy-mmode--globalized-predicate-p (predicate) (cond