master 7c8c769a4d4 7/9: Set major-mode before updating modules in erc-open
"F. Jason Park" <[email protected]> Tue, 30 Jun 2026 23:37:22 -0400 (EDT)
| Newsgroups | gmane.emacs.diffs |
|---|---|
| Message-ID | <[email protected]> |
branch: master commit 7c8c769a4d487b6b0cdb909444a10c7cc484a528 Author: F. Jason Park <[email protected]> Commit: F. Jason Park <[email protected]> Set major-mode before updating modules in erc-open * etc/ERC-NEWS: Mention change. * lisp/erc/erc-button.el (erc-button-mode, erc-button-enable) (erc-button-disable): Use `erc-with-initialized-session' instead of `erc-mode-hook'. * lisp/erc/erc-common.el (erc-with-initialized-session): New macro. * lisp/erc/erc-goodies.el (erc-scrolltobottom-mode) (erc-scrolltobottom-enable, erc-scrolltobottom-disable) (erc-move-to-prompt-mode, erc-move-to-prompt-enable) (erc-move-to-prompt-disable): Use `erc-with-initialized-session' instead of `erc-mode-hook'. * lisp/erc/erc-imenu.el (erc-imenu-mode, erc-imenu-enable) (erc-imenu-disable): Use macro instead of `erc-mode-hook'. * lisp/erc/erc-stamp.el (erc-stamp-mode, erc-stamp-enable) (erc-stamp-disable): Use macro instead of `erc-mode-hook'. * lisp/erc/erc-track.el (erc-track-mode, erc-track-enable) (erc-track-disable): Use macro instead of `erc-mode-hook'. * lisp/erc/erc-truncate.el (erc-truncate-mode, erc-truncate-enable) (erc-truncate-disable): Use macro instead of `erc-mode-hook'. * lisp/erc/erc.el (erc--set-modules-functions): New variable, an internal hook to modify erc-modules membership. (erc-open): Set major mode before updating modules and run `erc--set-modules-functions'. (Bug#76019) --- etc/ERC-NEWS | 10 ++++++++++ lisp/erc/erc-button.el | 4 +--- lisp/erc/erc-common.el | 16 ++++++++++++++++ lisp/erc/erc-goodies.el | 14 +++++--------- lisp/erc/erc-imenu.el | 8 +++----- lisp/erc/erc-stamp.el | 8 +++----- lisp/erc/erc-track.el | 4 +--- lisp/erc/erc-truncate.el | 4 +--- lisp/erc/erc.el | 10 ++++++++-- 9 files changed, 48 insertions(+), 30 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 2088345f97e..68655ecd4bd 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -51,6 +51,16 @@ were simply reversed as given. Now, just like with global modules, ERC preserves the preferred order when activating local modules for new sessions. +*** Major-mode setup runs before global-module setup in 'erc-open'. +The "enable" body of a global module's minor-mode command will now see +'erc-mode' as the 'major-mode'. Although ERC still delays its +major-mode hook until after it has initialized its main session +variables, a module can also now set any of its own variables that don't +depend on such initialization immediately and without fear of their +being killed. For modules still needing to run delayed, session-aware +code, a new convenience macro called 'erc-with-initialized-session' is +now available to automate any 'erc-mode-hook' wrangling for you. + * Changes in ERC 5.6.2 diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index a7b5855e9eb..0fbd43ad22f 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -54,13 +54,11 @@ "This mode buttonizes all messages according to `erc-button-alist'." ((add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 30) (add-hook 'erc-send-modify-hook #'erc-button-add-buttons 30) - (add-hook 'erc-mode-hook #'erc-button-setup 91) - (unless erc--updating-modules-p (erc-buffer-do #'erc-button-setup)) + (erc-with-initialized-session (erc-button-setup)) (add-hook 'erc--tab-functions #'erc-button-next) (erc--modify-local-map t "<backtab>" #'erc-button-previous)) ((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons) (remove-hook 'erc-send-modify-hook #'erc-button-add-buttons) - (remove-hook 'erc-mode-hook #'erc-button-setup) (remove-hook 'erc--tab-functions #'erc-button-next) (erc--modify-local-map nil "<backtab>" #'erc-button-previous))) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index aa176a14b46..481b6084a6a 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -434,6 +434,22 @@ if ARG is omitted or nil. (put ',enable 'definition-name ',name) (put ',disable 'definition-name ',name)))) +(defmacro erc-with-initialized-session (&rest body) + "Run BODY in all ERC buffers if outside `erc-open' and soon otherwise. +When inside `erc-open', run BODY after session variables have been +initialzied and after all `erc-mode-hook' members but before any +`after-change-major-mode-hook' members. Expect caller to know this is +only useful in global-module setup and that they're still responsible +for teardown, which is often done with `erc-buffer-do' or similar." + (let ((fn (make-symbol "fn")) + (hook-var (make-symbol "hook-var"))) + `(let ((,fn (lambda () ,@body))) + (if erc--updating-modules-p + (let ((,hook-var (gensym "erc--oneoff-major-mode-hook-"))) + (set ,hook-var ,fn) + (push ,hook-var delayed-mode-hooks)) + (erc-buffer-do ,fn))))) + (defmacro erc-with-buffer (spec &rest body) "Execute BODY in the buffer associated with SPEC. diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index ec110b65b8c..ddb5a24bd0d 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -79,12 +79,11 @@ be experimental. It currently only works with Emacs 28+." ;;;###autoload(autoload 'erc-scrolltobottom-mode "erc-goodies" nil t) (define-erc-module scrolltobottom nil "This mode causes the prompt to stay at the end of the window." - ((add-hook 'erc-mode-hook #'erc--scrolltobottom-setup) - (when (and erc-scrolltobottom-all (< emacs-major-version 28)) + ((when (and erc-scrolltobottom-all (< emacs-major-version 28)) (erc-button--display-error-notice-with-keys "Option `erc-scrolltobottom-all' requires Emacs 28+. Disabling.") (setq erc-scrolltobottom-all nil)) - (unless erc--updating-modules-p (erc-buffer-do #'erc--scrolltobottom-setup)) + (erc-with-initialized-session (erc--scrolltobottom-setup)) (if erc-scrolltobottom-all (progn (remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom) @@ -97,8 +96,7 @@ be experimental. It currently only works with Emacs 28+." (remove-hook 'erc-insert-done-hook #'erc--scrolltobottom-all) (remove-hook 'erc-send-completed-hook #'erc--scrolltobottom-all) (add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom))) - ((remove-hook 'erc-mode-hook #'erc--scrolltobottom-setup) - (erc-buffer-do #'erc--scrolltobottom-setup) + ((erc-buffer-do #'erc--scrolltobottom-setup) (remove-hook 'erc-insert-pre-hook #'erc--scrolltobottom-on-pre-insert) (remove-hook 'erc-send-completed-hook #'erc--scrolltobottom-all) (remove-hook 'erc-insert-done-hook #'erc--scrolltobottom-all) @@ -258,10 +256,8 @@ Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'." ;;;###autoload(autoload 'erc-move-to-prompt-mode "erc-goodies" nil t) (define-erc-module move-to-prompt nil "This mode causes the point to be moved to the prompt when typing text." - ((add-hook 'erc-mode-hook #'erc-move-to-prompt-setup) - (unless erc--updating-modules-p (erc-buffer-do #'erc-move-to-prompt-setup))) - ((remove-hook 'erc-mode-hook #'erc-move-to-prompt-setup) - (dolist (buffer (erc-buffer-list)) + ((erc-with-initialized-session (erc-move-to-prompt-setup))) + ((dolist (buffer (erc-buffer-list)) (with-current-buffer buffer (remove-hook 'pre-command-hook #'erc-move-to-prompt t))))) diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el index 965e8ead14c..669d8bf42b1 100644 --- a/lisp/erc/erc-imenu.el +++ b/lisp/erc/erc-imenu.el @@ -135,11 +135,9 @@ Don't rely on this function, read it first!" ;;;###autoload(autoload 'erc-imenu-mode "erc-imenu" nil t) (define-erc-module imenu nil "Simple Imenu integration for ERC." - ((add-hook 'erc-mode-hook #'erc-imenu-setup) - (add-hook 'which-function-mode-hook #'erc-imenu--disable-which-func) - (unless erc--updating-modules-p (erc-buffer-do #'erc-imenu-setup))) - ((remove-hook 'erc-mode-hook #'erc-imenu-setup) - (remove-hook 'which-function-mode-hook #'erc-imenu--disable-which-func) + ((add-hook 'which-function-mode-hook #'erc-imenu--disable-which-func) + (erc-with-initialized-session (erc-imenu-setup))) + ((remove-hook 'which-function-mode-hook #'erc-imenu--disable-which-func) (erc-buffer-do #'erc-imenu-setup))) (defun erc-imenu-setup () diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el index fa4b829b4cf..f80d49ca343 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -178,13 +178,11 @@ from entering them and instead jump over them." ;;;###autoload(autoload 'erc-timestamp-mode "erc-stamp" nil t) (define-erc-module stamp timestamp "This mode timestamps messages in the channel buffers." - ((add-hook 'erc-mode-hook #'erc-stamp--setup) - (add-hook 'erc-insert-modify-hook #'erc-add-timestamp 70) + ((add-hook 'erc-insert-modify-hook #'erc-add-timestamp 70) (add-hook 'erc-send-modify-hook #'erc-add-timestamp 70) (add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect) - (unless erc--updating-modules-p (erc-buffer-do #'erc-stamp--setup))) - ((remove-hook 'erc-mode-hook #'erc-stamp--setup) - (remove-hook 'erc-insert-modify-hook #'erc-add-timestamp) + (erc-with-initialized-session (erc-stamp--setup))) + ((remove-hook 'erc-insert-modify-hook #'erc-add-timestamp) (remove-hook 'erc-send-modify-hook #'erc-add-timestamp) (remove-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect) (erc-buffer-do #'erc-stamp--setup))) diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index 91466b9d5e3..53213217f7c 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -607,8 +607,7 @@ keybindings will not do anything useful." ;; enable the tracking keybindings (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) (erc-track-minor-mode-maybe)) - (add-hook 'erc-mode-hook #'erc-track--setup) - (unless erc--updating-modules-p (erc-buffer-do #'erc-track--setup)) + (erc-with-initialized-session (erc-track--setup)) (add-hook 'erc-networks--copy-server-buffer-functions #'erc-track--replace-killed-buffer)) ;; Disable: @@ -630,7 +629,6 @@ keybindings will not do anything useful." (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) (when erc-track-minor-mode (erc-track-minor-mode -1))) - (remove-hook 'erc-mode-hook #'erc-track--setup) (erc-buffer-do #'erc-track--setup) (remove-hook 'erc-networks--copy-server-buffer-functions #'erc-track--replace-killed-buffer))) diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el index 340584e26db..d651d87d412 100644 --- a/lisp/erc/erc-truncate.el +++ b/lisp/erc/erc-truncate.el @@ -67,12 +67,10 @@ for other purposes should customize either `erc-enable-logging' or ;;enable ((add-hook 'erc-insert-done-hook #'erc-truncate-buffer) (add-hook 'erc-connect-pre-hook #'erc-truncate--warn-about-logging) - (add-hook 'erc-mode-hook #'erc-truncate--setup) - (unless erc--updating-modules-p (erc-buffer-do #'erc-truncate--setup))) + (erc-with-initialized-session (erc-truncate--setup))) ;; disable ((remove-hook 'erc-insert-done-hook #'erc-truncate-buffer) (remove-hook 'erc-connect-pre-hook #'erc-truncate--warn-about-logging) - (remove-hook 'erc-mode-hook #'erc-truncate--setup) (erc-buffer-do #'erc-truncate--setup))) (defvar-local erc-truncate--buffer-size nil diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 22f2a90de63..b661453fdce 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2497,6 +2497,11 @@ realizes it's missing some required module \"foo\", it can confidently call (erc-foo-mode 1) without having to learn anything about the dependency's implementation.") +(defvar erc--set-modules-functions nil + "Abnormal hook run before updating modules on major-mode init. +Calls members with ID and TARGET parameters of `erc-open', both possibly +nil, along with a non-nil TARGET's server buffer when applicable.") + (defvar erc--setup-buffer-hook '(erc--warn-about-aberrant-modules) "Internal hook for module setup involving windows and frames.") @@ -2652,6 +2657,9 @@ side effect of setting the current buffer to the one it returns. Use (when connect (run-hook-with-args 'erc-before-connect server port nick)) (set-buffer buffer) (setq old-point (point)) + (delay-mode-hooks (erc-mode)) + (run-hook-with-args 'erc--set-modules-functions id channel + (and channel old-buffer)) (setq delayed-modules (erc--merge-local-modes (let ((erc--updating-modules-p t)) (erc--update-modules @@ -2659,8 +2667,6 @@ side effect of setting the current buffer to the one it returns. Use (or erc--server-reconnecting erc--target-priors))) - (delay-mode-hooks (erc-mode)) - (setq erc-server-reconnect-count old-recon-count) (when (setq erc-server-connected (not connect))