aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorF. Jason Park2023-10-06 17:34:04 -0700
committerF. Jason Park2023-10-13 07:47:00 -0700
commitd46c016fbd09cbce9ef23fe2b49d4fb5fc3b2b16 (patch)
tree7f1acf7155396ca7324853051071b13447a8b6e6 /lisp
parent9120d7a32ea4906d7c9460add31d37c3ca38931e (diff)
downloademacs-d46c016fbd09cbce9ef23fe2b49d4fb5fc3b2b16.tar.gz
emacs-d46c016fbd09cbce9ef23fe2b49d4fb5fc3b2b16.zip
Sort and dedupe when loading modules in erc-open
* doc/misc/erc.texi: Add new subheading "Module Loading" under the "Modules" chapter. * lisp/erc/erc.el (erc--sort-modules): New utility function to sort and dedupe modules. (erc-modules): In `custom-set' function, factor out collation into separate utility `erc--sort-modules'. (erc-update-modules): Call `erc--update-modules' with an argument, the current value of `erc-modules'. (erc--aberrant-modules): New variable, a list of symbols whose modules ERC suspects of being incorrectly defined. (erc--warn-about-aberrant-modules): New function to print an error message and emit a warning prior to connecting when `erc--aberrant-modules' is non-nil. (erc--find-mode): Make heuristic more robust by always checking for a mode activation command rather than just a state variable. This fixes a compatibility bug, new in 5.6, affecting third-party modules that autoload module definitions instead of their corresponding mode-activation commands. (erc--update-modules): Add new positional argument `modules'. (erc--setup-buffer-hook): Add new default member, `erc--warn-about-aberrant-modules'. (erc-open): Pass sorted `erc-modules' to `erc--update-modules'. * test/lisp/erc/erc-tests.el (erc--sort-modules): New test. (erc-tests--update-modules): New fixture. (erc--update-modules): Remove and rework as three separate tests dedicated to specific contexts. The existing one had poor coverage and was difficult, if not impossible, to follow. (erc--update-modules/unknown, erc--update-modules/local, erc--update-modules/realistic): New tests. (Bug#57955)
Diffstat (limited to 'lisp')
-rw-r--r--lisp/erc/erc.el53
1 files changed, 35 insertions, 18 deletions
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 16651b41eef..87abe2a133b 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2004,6 +2004,14 @@ buffer rather than a server buffer.")
2004 ;; each item is in the format '(old . new) 2004 ;; each item is in the format '(old . new)
2005 (delete-dups (mapcar #'erc--normalize-module-symbol mods))) 2005 (delete-dups (mapcar #'erc--normalize-module-symbol mods)))
2006 2006
2007(defun erc--sort-modules (modules)
2008 "Return a copy of MODULES, deduped and led by sorted built-ins."
2009 (let (built-in third-party)
2010 (dolist (mod modules)
2011 (setq mod (erc--normalize-module-symbol mod))
2012 (cl-pushnew mod (if (get mod 'erc--module) built-in third-party)))
2013 `(,@(sort built-in #'string-lessp) ,@(nreverse third-party))))
2014
2007(defcustom erc-modules '( autojoin button completion fill imenu irccontrols 2015(defcustom erc-modules '( autojoin button completion fill imenu irccontrols
2008 list match menu move-to-prompt netsplit 2016 list match menu move-to-prompt netsplit
2009 networks noncommands readonly ring stamp track) 2017 networks noncommands readonly ring stamp track)
@@ -2039,16 +2047,10 @@ removed from the list will be disabled."
2039 (when (symbol-value f) 2047 (when (symbol-value f)
2040 (funcall f 0)) 2048 (funcall f 0))
2041 (kill-local-variable f))))))))) 2049 (kill-local-variable f)))))))))
2042 (let (built-in third-party) 2050 ;; Calling `set-default-toplevel-value' complicates testing.
2043 (dolist (v val) 2051 (set sym (erc--sort-modules val))
2044 (setq v (erc--normalize-module-symbol v))
2045 (if (get v 'erc--module)
2046 (push v built-in)
2047 (push v third-party)))
2048 ;; Calling `set-default-toplevel-value' complicates testing
2049 (set sym (append (sort built-in #'string-lessp)
2050 (nreverse third-party))))
2051 ;; this test is for the case where erc hasn't been loaded yet 2052 ;; this test is for the case where erc hasn't been loaded yet
2053 ;; FIXME explain how this ^ can occur or remove comment.
2052 (when (fboundp 'erc-update-modules) 2054 (when (fboundp 'erc-update-modules)
2053 (unless erc--inside-mode-toggle-p 2055 (unless erc--inside-mode-toggle-p
2054 (erc-update-modules)))) 2056 (erc-update-modules))))
@@ -2112,15 +2114,29 @@ removed from the list will be disabled."
2112(defun erc-update-modules () 2114(defun erc-update-modules ()
2113 "Enable minor mode for every module in `erc-modules'. 2115 "Enable minor mode for every module in `erc-modules'.
2114Except ignore all local modules, which were introduced in ERC 5.5." 2116Except ignore all local modules, which were introduced in ERC 5.5."
2115 (erc--update-modules) 2117 (erc--update-modules erc-modules)
2116 nil) 2118 nil)
2117 2119
2120(defvar erc--aberrant-modules nil
2121 "Modules suspected of being improperly loaded.")
2122
2123(defun erc--warn-about-aberrant-modules ()
2124 (when (and erc--aberrant-modules (not erc--target))
2125 (erc-button--display-error-notice-with-keys-and-warn
2126 "The following modules exhibited strange loading behavior: "
2127 (mapconcat (lambda (s) (format "`%s'" s)) erc--aberrant-modules ", ")
2128 ". Please contact ERC with \\[erc-bug] if you believe this to be untrue."
2129 " See Info:\"(erc) Module Loading\" for more.")
2130 (setq erc--aberrant-modules nil)))
2131
2118(defun erc--find-mode (sym) 2132(defun erc--find-mode (sym)
2119 (setq sym (erc--normalize-module-symbol sym)) 2133 (setq sym (erc--normalize-module-symbol sym))
2120 (if-let* ((mode (intern-soft (concat "erc-" (symbol-name sym) "-mode"))) 2134 (if-let ((mode (intern-soft (concat "erc-" (symbol-name sym) "-mode")))
2121 ((or (boundp mode) 2135 ((and (fboundp mode)
2122 (and (fboundp mode) 2136 (autoload-do-load (symbol-function mode) mode)))
2123 (autoload-do-load (symbol-function mode) mode))))) 2137 ((or (get sym 'erc--module)
2138 (symbol-file mode)
2139 (ignore (cl-pushnew sym erc--aberrant-modules)))))
2124 mode 2140 mode
2125 (and (require (or (get sym 'erc--feature) 2141 (and (require (or (get sym 'erc--feature)
2126 (intern (concat "erc-" (symbol-name sym)))) 2142 (intern (concat "erc-" (symbol-name sym))))
@@ -2129,9 +2145,9 @@ Except ignore all local modules, which were introduced in ERC 5.5."
2129 (fboundp mode) 2145 (fboundp mode)
2130 mode))) 2146 mode)))
2131 2147
2132(defun erc--update-modules () 2148(defun erc--update-modules (modules)
2133 (let (local-modes) 2149 (let (local-modes)
2134 (dolist (module erc-modules local-modes) 2150 (dolist (module modules local-modes)
2135 (if-let ((mode (erc--find-mode module))) 2151 (if-let ((mode (erc--find-mode module)))
2136 (if (custom-variable-p mode) 2152 (if (custom-variable-p mode)
2137 (funcall mode 1) 2153 (funcall mode 1)
@@ -2158,7 +2174,7 @@ realizes it's missing some required module \"foo\", it can
2158confidently call (erc-foo-mode 1) without having to learn 2174confidently call (erc-foo-mode 1) without having to learn
2159anything about the dependency's implementation.") 2175anything about the dependency's implementation.")
2160 2176
2161(defvar erc--setup-buffer-hook nil 2177(defvar erc--setup-buffer-hook '(erc--warn-about-aberrant-modules)
2162 "Internal hook for module setup involving windows and frames.") 2178 "Internal hook for module setup involving windows and frames.")
2163 2179
2164(defvar erc--display-context nil 2180(defvar erc--display-context nil
@@ -2315,7 +2331,8 @@ Returns the buffer for the given server or channel."
2315 (setq old-point (point)) 2331 (setq old-point (point))
2316 (setq delayed-modules 2332 (setq delayed-modules
2317 (erc--merge-local-modes (let ((erc--updating-modules-p t)) 2333 (erc--merge-local-modes (let ((erc--updating-modules-p t))
2318 (erc--update-modules)) 2334 (erc--update-modules
2335 (erc--sort-modules erc-modules)))
2319 (or erc--server-reconnecting 2336 (or erc--server-reconnecting
2320 erc--target-priors))) 2337 erc--target-priors)))
2321 2338