summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorF. Jason Park <jp@neverwas.me>2023-05-07 19:43:57 -0700
committerF. Jason Park <jp@neverwas.me>2023-05-13 07:05:22 -0700
commit867b104010760c4b7cd700078884cc774a01860a (patch)
tree60e980b56bfb33169d792422ebf985c89bd8680e
parent75a412d78b6f4b4b68a7c649047cd28320110c09 (diff)
downloademacs-867b104010760c4b7cd700078884cc774a01860a.tar.gz
Make some module toggles more resilient in ERC
* lisp/erc/erc-goodies.el (erc-scrolltobottom-mode, erc-scrolltobottom-enable, erc-move-to-prompt-mode, erc-move-to-prompt-enable): Guard setup procedure behind `erc--updating-modules-p'. * lisp/erc/erc-imenu.el (erc-imenu-mode, erc-imenu-enable, erc-imenu-disable): Don't run setup when `erc--updating-modules-p' is non-nil. Also, don't restrict teardown to buffers of the same process. * lisp/erc/erc-match.el (erc-match-mode, erc-match-enable): Run major-mode hook member immediately outside of `erc-update-modules' in `erc-open'. * lisp/erc/erc-spelling.el (erc-spelling-mode, erc-spelling-enable): Only conditionally run setup immediately. * lisp/erc/erc-stamp.el (erc-stamp-mode, erc-stamp-enable, erc-stamp-disable): Run setup hook immediately. Don't forget to kill local vars in all ERC buffers during teardown. * lisp/erc/erc.el (erc--updating-modules-p): New variable that global modules can use to provide their `erc-mode-hook'-deferred code on demand while shielding it from running during early ERC buffer initialization. (erc-open): Make `erc--updating-modules-p' non-nil while activating global modules. (Bug#60936)
-rw-r--r--lisp/erc/erc-goodies.el10
-rw-r--r--lisp/erc/erc-imenu.el5
-rw-r--r--lisp/erc/erc-match.el2
-rw-r--r--lisp/erc/erc-spelling.el5
-rw-r--r--lisp/erc/erc-stamp.el10
-rw-r--r--lisp/erc/erc.el23
6 files changed, 42 insertions, 13 deletions
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 4558ff7c076..01eae4b63c5 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -53,9 +53,8 @@ argument to `recenter'."
"This mode causes the prompt to stay at the end of the window."
((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
(add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
- (dolist (buffer (erc-buffer-list))
- (with-current-buffer buffer
- (erc-add-scroll-to-bottom))))
+ (unless erc--updating-modules-p
+ (erc-buffer-filter #'erc-add-scroll-to-bottom)))
((remove-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
(remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
(dolist (buffer (erc-buffer-list))
@@ -120,9 +119,8 @@ Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
(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)
- (dolist (buffer (erc-buffer-list))
- (with-current-buffer buffer
- (erc-move-to-prompt-setup))))
+ (unless erc--updating-modules-p
+ (erc-buffer-filter #'erc-move-to-prompt-setup)))
((remove-hook 'erc-mode-hook #'erc-move-to-prompt-setup)
(dolist (buffer (erc-buffer-list))
(with-current-buffer buffer
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 526afd32249..9864d7c4042 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -138,9 +138,10 @@ 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 'erc-mode-hook #'erc-imenu-setup)
+ (unless erc--updating-modules-p (erc-buffer-filter #'erc-imenu-setup)))
((remove-hook 'erc-mode-hook #'erc-imenu-setup)
- (erc-with-all-buffers-of-server erc-server-process nil
+ (erc-with-all-buffers-of-server nil nil
(when erc-imenu--create-index-function
(setq imenu-create-index-function erc-imenu--create-index-function)
(kill-local-variable 'erc-imenu--create-index-function)))))
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index c08a640260c..86883260413 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -54,6 +54,8 @@ you can decide whether the entire message or only the sending nick is
highlighted."
((add-hook 'erc-insert-modify-hook #'erc-match-message 'append)
(add-hook 'erc-mode-hook #'erc-match--modify-invisibility-spec)
+ (unless erc--updating-modules-p
+ (erc-buffer-filter #'erc-match--modify-invisibility-spec))
(erc--modify-local-map t "C-c C-k" #'erc-go-to-log-matches-buffer))
((remove-hook 'erc-insert-modify-hook #'erc-match-message)
(remove-hook 'erc-mode-hook #'erc-match--modify-invisibility-spec)
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 8fce2508ceb..8e5424f4162 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -39,8 +39,9 @@
;; Use erc-connect-pre-hook instead of erc-mode-hook as pre-hook is
;; called AFTER the server buffer is initialized.
((add-hook 'erc-connect-pre-hook #'erc-spelling-init)
- (dolist (buffer (erc-buffer-list))
- (erc-spelling-init buffer)))
+ (unless erc--updating-modules-p
+ (erc-with-all-buffers-of-server nil nil
+ (erc-spelling-init (current-buffer)))))
((remove-hook 'erc-connect-pre-hook #'erc-spelling-init)
(dolist (buffer (erc-buffer-list))
(with-current-buffer buffer (flyspell-mode 0)))))
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index f90a8fc50b1..9191bbe5a2a 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -165,11 +165,17 @@ from entering them and instead jump over them."
((add-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
(add-hook 'erc-insert-modify-hook #'erc-add-timestamp t)
(add-hook 'erc-send-modify-hook #'erc-add-timestamp t)
- (add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect))
+ (add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
+ (unless erc--updating-modules-p
+ (erc-buffer-filter #'erc-munge-invisibility-spec)))
((remove-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
(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)))
+ (remove-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
+ (erc-with-all-buffers-of-server nil nil
+ (kill-local-variable 'erc-timestamp-last-inserted)
+ (kill-local-variable 'erc-timestamp-last-inserted-left)
+ (kill-local-variable 'erc-timestamp-last-inserted-right))))
(defun erc-stamp--recover-on-reconnect ()
(when-let ((priors (or erc--server-reconnecting erc--target-priors)))
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 5738ee92578..a104d7ad542 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2084,6 +2084,26 @@ Except ignore all local modules, which were introduced in ERC 5.5."
(push mode local-modes))
(error "`%s' is not a known ERC module" module)))))
+(defvar erc--updating-modules-p nil
+ "Non-nil when running `erc--update-modules' in `erc-open'.
+This allows global modules with known or likely dependents (or
+some other reason for activating after session initialization) to
+conditionally run setup code traditionally reserved for
+`erc-mode-hook' in the setup portion of their mode toggle. Note
+that being \"global\", they'll likely want to do so in all ERC
+buffers and ensure the code is idempotent. For example:
+
+ (add-hook \\='erc-mode-hook #\\='erc-foo-setup-fn)
+ (unless erc--updating-modules-p
+ (erc-with-all-buffers-of-server nil
+ (lambda () some-condition-p)
+ (erc-foo-setup-fn)))
+
+This means that when a dependent module is initializing and
+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.")
+
(defun erc--setup-buffer-first-window (frame a b)
(catch 'found
(walk-window-tree
@@ -2243,7 +2263,8 @@ Returns the buffer for the given server or channel."
(set-buffer buffer)
(setq old-point (point))
(setq delayed-modules
- (erc--merge-local-modes (erc--update-modules)
+ (erc--merge-local-modes (let ((erc--updating-modules-p t))
+ (erc--update-modules))
(or erc--server-reconnecting
erc--target-priors)))