aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorF. Jason Park2021-07-12 03:44:28 -0700
committerAmin Bandali2022-11-23 19:56:31 -0500
commit4c4936fab2ecd97ff6e03e5cfe12def4626c718b (patch)
tree573e992298f17fd23709fddafb2979a49646b2d9
parentdc6ff142bc1c1a8596436e08ddbccb39d8fdcf39 (diff)
downloademacs-4c4936fab2ecd97ff6e03e5cfe12def4626c718b.tar.gz
emacs-4c4936fab2ecd97ff6e03e5cfe12def4626c718b.zip
Support local ERC modules in erc-mode buffers
* doc/misc/erc.texi: Mention local modules in Modules chapter. * etc/ERC-NEWS: Mention changes to `erc-update-modules'. * lisp/erc/erc.el (erc-migrate-modules): Add some missing mappings. (erc-modules): When a user removes a module, disable it and kill its local variable in all ERC buffers. (erc-update-modules): Move body of `erc-update-modules' to new internal function. (erc--update-modules): Add new function, a renamed and slightly modified version of `erc-update-modules'. Specifically, change return value from nil to a list of minor-mode commands for local modules. Use `custom-variable-p' to detect flavor. (erc--merge-local-modes): Add helper for finding local modules already active as minor modes in an ERC buffer. (erc-open): Replace `erc-update-modules' with `erc--update-modules'. Defer enabling of local modules via `erc--update-modules' until after buffer is initialized with other local vars. Also defer major-mode hooks so they can detect things like whether the buffer is a server or target buffer. Also ensure local module setup code can detect when `erc-open' was called with a non-nil `erc--server-reconnecting'. * lisp/erc/erc-common.el (erc--module-name-migrations, erc--features-to-modules, erc--modules-to-features): Add alists of old-to-new module names to support module-name migrations. (erc--assemble-toggle): Add new helper for constructing mode toggles, like `erc-sasl-enable'. (define-erc-modules): Defer to `erc--assemble-toggle' to create toggle commands. (erc--normalize-module-symbol): Add helper for `erc-migrate-modules'. * lisp/erc/erc-goodies.el: Require cl-lib. * test/lisp/erc/erc-tests.el (erc-migrate-modules, erc--update-modules): Add rudimentary unit tests asserting correct module-name mappings. (erc--merge-local-modes): Add test for helper. (define-erc-module--global, define-erc-module--local): Add tests asserting module-creation macro. (Bug#57955.)
-rw-r--r--doc/misc/erc.texi39
-rw-r--r--etc/ERC-NEWS9
-rw-r--r--lisp/erc/erc-common.el82
-rw-r--r--lisp/erc/erc-goodies.el1
-rw-r--r--lisp/erc/erc.el104
-rw-r--r--test/lisp/erc/erc-tests.el156
6 files changed, 338 insertions, 53 deletions
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index 0d807e323e6..b9c6e33d36d 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -390,8 +390,11 @@ modules are loaded.
390 390
391There is a spiffy customize interface, which may be reached by typing 391There is a spiffy customize interface, which may be reached by typing
392@kbd{M-x customize-option @key{RET} erc-modules @key{RET}}. 392@kbd{M-x customize-option @key{RET} erc-modules @key{RET}}.
393Alternatively, set @code{erc-modules} manually and then call 393When removing a module outside of the Custom ecosystem, you may wish
394@code{erc-update-modules}. 394to ensure it's disabled by invoking its associated minor-mode toggle,
395such as @kbd{M-x erc-spelling-mode @key{RET}}. Note that, these days,
396calling @code{erc-update-modules} in an init file is typically
397unnecessary.
395 398
396The following is a list of available modules. 399The following is a list of available modules.
397 400
@@ -517,6 +520,38 @@ Translate morse code in messages
517 520
518@end table 521@end table
519 522
523@subheading Local Modules
524@cindex local modules
525
526All modules operate as minor modes under the hood, and some newer ones
527may be defined as buffer-local. These so-called ``local modules'' are
528a work in progress and their behavior and interface are subject to
529change. As of ERC 5.5, the only practical differences are
530
531@enumerate
532@item
533``Control variables,'' like @code{erc-sasl-mode}, are stateful across
534IRC sessions and override @code{erc-module} membership when influencing
535module activation in new sessions.
536@item
537Removing a local module from @code{erc-modules} via Customize not only
538disables its mode but also kills its control variable in all ERC
539buffers.
540@item
541``Mode toggles,'' like @code{erc-sasl-mode} and
542@code{erc-sasl-enable}, behave differently relative to each other and
543to their global counterparts. (More on this just below.)
544@end enumerate
545
546By default, all local-mode toggles, like @code{erc-sasl-mode}, only
547affect the current buffer, but their ``non-mode'' variants, such as
548@code{erc-sasl-enable}, operate on all buffers belonging to a
549connection when called interactively. Keep in mind that whether
550enabled or not, a module may effectively be ``inert'' in certain types
551of buffers, such as queries and channels. Whatever the case, a local
552toggle never mutates @code{erc-modules}.
553
554
520@c PRE5_4: Document every option of every module in its own subnode 555@c PRE5_4: Document every option of every module in its own subnode
521 556
522 557
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index f638d4717a1..15f7fe84dd9 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -125,6 +125,15 @@ The function 'erc-auto-query' was deemed too difficult to reason
125through and has thus been deprecated with no public replacement; it 125through and has thus been deprecated with no public replacement; it
126has also been removed from the client code path. 126has also been removed from the client code path.
127 127
128The function 'erc-open' now delays running 'erc-mode-hook' members
129until most local session variables have been initialized (minus those
130connection-related ones in erc-backend). 'erc-open' also no longer
131calls 'erc-update-modules', although modules are still activated
132in an identical fashion.
133
134Some groundwork has been laid for what may become a new breed of ERC
135module, namely, "connection-local" (or simply "local") modules.
136
128A few internal variables have been introduced that could just as well 137A few internal variables have been introduced that could just as well
129have been made public, possibly as user options. Likewise for some 138have been made public, possibly as user options. Likewise for some
130internal functions. As always, users needing such functionality 139internal functions. As always, users needing such functionality
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index 23a19337986..a4046ba9b39 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -88,6 +88,65 @@
88 (contents "" :type string) 88 (contents "" :type string)
89 (tags '() :type list)) 89 (tags '() :type list))
90 90
91;; TODO move goodies modules here after 29 is released.
92(defconst erc--features-to-modules
93 '((erc-pcomplete completion pcomplete)
94 (erc-capab capab-identify)
95 (erc-join autojoin)
96 (erc-page page ctcp-page)
97 (erc-sound sound ctcp-sound)
98 (erc-stamp stamp timestamp)
99 (erc-services services nickserv))
100 "Migration alist mapping a library feature to module names.
101Keys need not be unique: a library may define more than one
102module. Sometimes a module's downcased alias will be its
103canonical name.")
104
105(defconst erc--modules-to-features
106 (let (pairs)
107 (pcase-dolist (`(,feature . ,names) erc--features-to-modules)
108 (dolist (name names)
109 (push (cons name feature) pairs)))
110 (nreverse pairs))
111 "Migration alist mapping a module's name to its home library feature.")
112
113(defconst erc--module-name-migrations
114 (let (pairs)
115 (pcase-dolist (`(,_ ,canonical . ,rest) erc--features-to-modules)
116 (dolist (obsolete rest)
117 (push (cons obsolete canonical) pairs)))
118 pairs)
119 "Association list of obsolete module names to canonical names.")
120
121(defun erc--normalize-module-symbol (symbol)
122 "Return preferred SYMBOL for `erc-modules'."
123 (setq symbol (intern (downcase (symbol-name symbol))))
124 (or (cdr (assq symbol erc--module-name-migrations)) symbol))
125
126(defun erc--assemble-toggle (localp name ablsym mode val body)
127 (let ((arg (make-symbol "arg")))
128 `(defun ,ablsym ,(if localp `(&optional ,arg) '())
129 ,(concat
130 (if val "Enable" "Disable")
131 " ERC " (symbol-name name) " mode."
132 (when localp
133 "\nWith ARG, do so in all buffers for the current connection."))
134 (interactive ,@(when localp '("p")))
135 ,@(if localp
136 `((when (derived-mode-p 'erc-mode)
137 (if ,arg
138 (erc-with-all-buffers-of-server erc-server-process nil
139 (,ablsym))
140 (setq ,mode ,val)
141 ,@body)))
142 `(,(if val
143 `(cl-pushnew ',(erc--normalize-module-symbol name)
144 erc-modules)
145 `(setq erc-modules (delq ',(erc--normalize-module-symbol name)
146 erc-modules)))
147 (setq ,mode ,val)
148 ,@body)))))
149
91(defmacro define-erc-module (name alias doc enable-body disable-body 150(defmacro define-erc-module (name alias doc enable-body disable-body
92 &optional local-p) 151 &optional local-p)
93 "Define a new minor mode using ERC conventions. 152 "Define a new minor mode using ERC conventions.
@@ -103,6 +162,13 @@ This will define a minor mode called erc-NAME-mode, possibly
103an alias erc-ALIAS-mode, as well as the helper functions 162an alias erc-ALIAS-mode, as well as the helper functions
104erc-NAME-enable, and erc-NAME-disable. 163erc-NAME-enable, and erc-NAME-disable.
105 164
165With LOCAL-P, these helpers take on an optional argument that,
166when non-nil, causes them to act on all buffers of a connection.
167This feature is mainly intended for interactive use and does not
168carry over to their respective minor-mode toggles. Beware that
169for global modules, these helpers and toggles all mutate
170`erc-modules'.
171
106Example: 172Example:
107 173
108 ;;;###autoload(autoload \\='erc-replace-mode \"erc-replace\") 174 ;;;###autoload(autoload \\='erc-replace-mode \"erc-replace\")
@@ -133,20 +199,8 @@ if ARG is omitted or nil.
133 (if ,mode 199 (if ,mode
134 (,enable) 200 (,enable)
135 (,disable))) 201 (,disable)))
136 (defun ,enable () 202 ,(erc--assemble-toggle local-p name enable mode t enable-body)
137 ,(format "Enable ERC %S mode." 203 ,(erc--assemble-toggle local-p name disable mode nil disable-body)
138 name)
139 (interactive)
140 (add-to-list 'erc-modules (quote ,name))
141 (setq ,mode t)
142 ,@enable-body)
143 (defun ,disable ()
144 ,(format "Disable ERC %S mode."
145 name)
146 (interactive)
147 (setq erc-modules (delq (quote ,name) erc-modules))
148 (setq ,mode nil)
149 ,@disable-body)
150 ,(when (and alias (not (eq name alias))) 204 ,(when (and alias (not (eq name alias)))
151 `(defalias 205 `(defalias
152 ',(intern 206 ',(intern
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 59b5f01f236..1af83b58ba7 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -31,6 +31,7 @@
31 31
32;;; Imenu support 32;;; Imenu support
33 33
34(eval-when-compile (require 'cl-lib))
34(require 'erc-common) 35(require 'erc-common)
35 36
36(defvar erc-controls-highlight-regexp) 37(defvar erc-controls-highlight-regexp)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 352f72e6178..384d92e624f 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1791,10 +1791,7 @@ buffer rather than a server buffer.")
1791 "Migrate old names of ERC modules to new ones." 1791 "Migrate old names of ERC modules to new ones."
1792 ;; modify `transforms' to specify what needs to be changed 1792 ;; modify `transforms' to specify what needs to be changed
1793 ;; each item is in the format '(old . new) 1793 ;; each item is in the format '(old . new)
1794 (let ((transforms '((pcomplete . completion)))) 1794 (delete-dups (mapcar #'erc--normalize-module-symbol mods)))
1795 (delete-dups
1796 (mapcar (lambda (m) (or (cdr (assoc m transforms)) m))
1797 mods))))
1798 1795
1799(defcustom erc-modules '(netsplit fill button match track completion readonly 1796(defcustom erc-modules '(netsplit fill button match track completion readonly
1800 networks ring autojoin noncommands irccontrols 1797 networks ring autojoin noncommands irccontrols
@@ -1813,9 +1810,16 @@ removed from the list will be disabled."
1813 (dolist (module erc-modules) 1810 (dolist (module erc-modules)
1814 (unless (member module val) 1811 (unless (member module val)
1815 (let ((f (intern-soft (format "erc-%s-mode" module)))) 1812 (let ((f (intern-soft (format "erc-%s-mode" module))))
1816 (when (and (fboundp f) (boundp f) (symbol-value f)) 1813 (when (and (fboundp f) (boundp f))
1817 (message "Disabling `erc-%s'" module) 1814 (when (symbol-value f)
1818 (funcall f 0)))))) 1815 (message "Disabling `erc-%s'" module)
1816 (funcall f 0))
1817 (unless (or (custom-variable-p f)
1818 (not (fboundp 'erc-buffer-filter)))
1819 (erc-buffer-filter (lambda ()
1820 (when (symbol-value f)
1821 (funcall f 0))
1822 (kill-local-variable f)))))))))
1819 (set sym val) 1823 (set sym val)
1820 ;; this test is for the case where erc hasn't been loaded yet 1824 ;; this test is for the case where erc hasn't been loaded yet
1821 (when (fboundp 'erc-update-modules) 1825 (when (fboundp 'erc-update-modules)
@@ -1873,27 +1877,23 @@ removed from the list will be disabled."
1873 :group 'erc) 1877 :group 'erc)
1874 1878
1875(defun erc-update-modules () 1879(defun erc-update-modules ()
1876 "Run this to enable erc-foo-mode for all modules in `erc-modules'." 1880 "Enable minor mode for every module in `erc-modules'.
1877 (let (req) 1881Except ignore all local modules, which were introduced in ERC 5.5."
1878 (dolist (mod erc-modules) 1882 (erc--update-modules)
1879 (setq req (concat "erc-" (symbol-name mod))) 1883 nil)
1880 (cond 1884
1881 ;; yuck. perhaps we should bring the filenames into sync? 1885(defun erc--update-modules ()
1882 ((string= req "erc-capab-identify") 1886 (let (local-modes)
1883 (setq req "erc-capab")) 1887 (dolist (module erc-modules local-modes)
1884 ((string= req "erc-completion") 1888 (require (or (alist-get module erc--modules-to-features)
1885 (setq req "erc-pcomplete")) 1889 (intern (concat "erc-" (symbol-name module))))
1886 ((string= req "erc-pcomplete") 1890 nil 'noerror) ; some modules don't have a corresponding feature
1887 (setq mod 'completion)) 1891 (let ((mode (intern-soft (concat "erc-" (symbol-name module) "-mode"))))
1888 ((string= req "erc-autojoin") 1892 (unless (and mode (fboundp mode))
1889 (setq req "erc-join"))) 1893 (error "`%s' is not a known ERC module" module))
1890 (condition-case nil 1894 (if (custom-variable-p mode)
1891 (require (intern req)) 1895 (funcall mode 1)
1892 (error nil)) 1896 (push mode local-modes))))))
1893 (let ((sym (intern-soft (concat "erc-" (symbol-name mod) "-mode"))))
1894 (if (fboundp sym)
1895 (funcall sym 1)
1896 (error "`%s' is not a known ERC module" mod))))))
1897 1897
1898(defun erc-setup-buffer (buffer) 1898(defun erc-setup-buffer (buffer)
1899 "Consults `erc-join-buffer' to find out how to display `BUFFER'." 1899 "Consults `erc-join-buffer' to find out how to display `BUFFER'."
@@ -1924,6 +1924,24 @@ removed from the list will be disabled."
1924 (display-buffer buffer) 1924 (display-buffer buffer)
1925 (switch-to-buffer buffer))))) 1925 (switch-to-buffer buffer)))))
1926 1926
1927(defun erc--merge-local-modes (new-modes old-vars)
1928 "Return a cons of two lists, each containing local-module modes.
1929In the first, put modes to be enabled in a new ERC buffer by
1930calling their associated functions. In the second, put modes to
1931be marked as disabled by setting their associated variables to
1932nil."
1933 (if old-vars
1934 (let ((out (list (reverse new-modes))))
1935 (pcase-dolist (`(,k . ,v) old-vars)
1936 (when (and (string-prefix-p "erc-" (symbol-name k))
1937 (string-suffix-p "-mode" (symbol-name k)))
1938 (if v
1939 (cl-pushnew k (car out))
1940 (setf (car out) (delq k (car out)))
1941 (cl-pushnew k (cdr out)))))
1942 (cons (nreverse (car out)) (nreverse (cdr out))))
1943 (list new-modes)))
1944
1927(defun erc-open (&optional server port nick full-name 1945(defun erc-open (&optional server port nick full-name
1928 connect passwd tgt-list channel process 1946 connect passwd tgt-list channel process
1929 client-certificate user id) 1947 client-certificate user id)
@@ -1951,18 +1969,25 @@ Returns the buffer for the given server or channel."
1951 (let* ((target (and channel (erc--target-from-string channel))) 1969 (let* ((target (and channel (erc--target-from-string channel)))
1952 (buffer (erc-get-buffer-create server port nil target id)) 1970 (buffer (erc-get-buffer-create server port nil target id))
1953 (old-buffer (current-buffer)) 1971 (old-buffer (current-buffer))
1954 old-point 1972 (old-vars (and (not connect) (buffer-local-variables)))
1973 (old-recon-count erc-server-reconnect-count)
1974 (old-point nil)
1975 (delayed-modules nil)
1955 (continued-session (and erc--server-reconnecting 1976 (continued-session (and erc--server-reconnecting
1956 (with-suppressed-warnings 1977 (with-suppressed-warnings
1957 ((obsolete erc-reuse-buffers)) 1978 ((obsolete erc-reuse-buffers))
1958 erc-reuse-buffers)))) 1979 erc-reuse-buffers))))
1959 (when connect (run-hook-with-args 'erc-before-connect server port nick)) 1980 (when connect (run-hook-with-args 'erc-before-connect server port nick))
1960 (erc-update-modules)
1961 (set-buffer buffer) 1981 (set-buffer buffer)
1962 (setq old-point (point)) 1982 (setq old-point (point))
1963 (let ((old-recon-count erc-server-reconnect-count)) 1983 (setq delayed-modules
1964 (erc-mode) 1984 (erc--merge-local-modes (erc--update-modules)
1965 (setq erc-server-reconnect-count old-recon-count)) 1985 (or erc--server-reconnecting old-vars)))
1986
1987 (delay-mode-hooks (erc-mode))
1988
1989 (setq erc-server-reconnect-count old-recon-count)
1990
1966 (when (setq erc-server-connected (not connect)) 1991 (when (setq erc-server-connected (not connect))
1967 (setq erc-server-announced-name 1992 (setq erc-server-announced-name
1968 (buffer-local-value 'erc-server-announced-name old-buffer))) 1993 (buffer-local-value 'erc-server-announced-name old-buffer)))
@@ -2019,14 +2044,21 @@ Returns the buffer for the given server or channel."
2019 (setq erc-session-client-certificate client-certificate) 2044 (setq erc-session-client-certificate client-certificate)
2020 (setq erc-networks--id 2045 (setq erc-networks--id
2021 (if connect 2046 (if connect
2022 (or (and continued-session 2047 (or (and erc--server-reconnecting
2023 (buffer-local-value 'erc-networks--id old-buffer)) 2048 (alist-get 'erc-networks--id erc--server-reconnecting))
2024 (and id (erc-networks--id-create id))) 2049 (and id (erc-networks--id-create id)))
2025 (buffer-local-value 'erc-networks--id old-buffer))) 2050 (buffer-local-value 'erc-networks--id old-buffer)))
2026 ;; debug output buffer 2051 ;; debug output buffer
2027 (setq erc-dbuf 2052 (setq erc-dbuf
2028 (when erc-log-p 2053 (when erc-log-p
2029 (get-buffer-create (concat "*ERC-DEBUG: " server "*")))) 2054 (get-buffer-create (concat "*ERC-DEBUG: " server "*"))))
2055
2056 (erc-determine-parameters server port nick full-name user passwd)
2057
2058 (save-excursion (run-mode-hooks))
2059 (dolist (mod (car delayed-modules)) (funcall mod +1))
2060 (dolist (var (cdr delayed-modules)) (set var nil))
2061
2030 ;; set up prompt 2062 ;; set up prompt
2031 (unless continued-session 2063 (unless continued-session
2032 (goto-char (point-max)) 2064 (goto-char (point-max))
@@ -2038,8 +2070,6 @@ Returns the buffer for the given server or channel."
2038 (erc-display-prompt) 2070 (erc-display-prompt)
2039 (goto-char (point-max))) 2071 (goto-char (point-max)))
2040 2072
2041 (erc-determine-parameters server port nick full-name user passwd)
2042
2043 ;; Saving log file on exit 2073 ;; Saving log file on exit
2044 (run-hook-with-args 'erc-connect-pre-hook buffer) 2074 (run-hook-with-args 'erc-connect-pre-hook buffer)
2045 2075
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index ff5d8026973..b185d850a6f 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1178,4 +1178,160 @@
1178 (kill-buffer "baznet") 1178 (kill-buffer "baznet")
1179 (kill-buffer "#chan"))) 1179 (kill-buffer "#chan")))
1180 1180
1181(ert-deftest erc-migrate-modules ()
1182 (should (equal (erc-migrate-modules '(autojoin timestamp button))
1183 '(autojoin stamp button)))
1184 ;; Default unchanged
1185 (should (equal (erc-migrate-modules erc-modules) erc-modules)))
1186
1187(ert-deftest erc--update-modules ()
1188 (let (calls
1189 erc-modules
1190 erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
1191 (cl-letf (((symbol-function 'require)
1192 (lambda (s &rest _) (push s calls)))
1193
1194 ;; Local modules
1195 ((symbol-function 'erc-fake-bar-mode)
1196 (lambda (n) (push (cons 'fake-bar n) calls)))
1197
1198 ;; Global modules
1199 ((symbol-function 'erc-fake-foo-mode)
1200 (lambda (n) (push (cons 'fake-foo n) calls)))
1201 ((get 'erc-fake-foo-mode 'standard-value) 'ignore)
1202 ((symbol-function 'erc-autojoin-mode)
1203 (lambda (n) (push (cons 'autojoin n) calls)))
1204 ((get 'erc-autojoin-mode 'standard-value) 'ignore)
1205 ((symbol-function 'erc-networks-mode)
1206 (lambda (n) (push (cons 'networks n) calls)))
1207 ((get 'erc-networks-mode 'standard-value) 'ignore)
1208 ((symbol-function 'erc-completion-mode)
1209 (lambda (n) (push (cons 'completion n) calls)))
1210 ((get 'erc-completion-mode 'standard-value) 'ignore))
1211
1212 (ert-info ("Local modules")
1213 (setq erc-modules '(fake-foo fake-bar))
1214 (should (equal (erc--update-modules) '(erc-fake-bar-mode)))
1215 ;; Bar the feature is still required but the mode is not activated
1216 (should (equal (nreverse calls)
1217 '(erc-fake-foo (fake-foo . 1) erc-fake-bar)))
1218 (setq calls nil))
1219
1220 (ert-info ("Module name overrides")
1221 (setq erc-modules '(completion autojoin networks))
1222 (should-not (erc--update-modules)) ; no locals
1223 (should (equal (nreverse calls) '( erc-pcomplete (completion . 1)
1224 erc-join (autojoin . 1)
1225 erc-networks (networks . 1))))
1226 (setq calls nil)))))
1227
1228(ert-deftest erc--merge-local-modes ()
1229
1230 (ert-info ("No existing modes")
1231 (let ((old '((a) (b . t)))
1232 (new '(erc-c-mode erc-d-mode)))
1233 (should (equal (erc--merge-local-modes new old)
1234 '((erc-c-mode erc-d-mode))))))
1235
1236 (ert-info ("Active existing added, inactive existing removed, deduped")
1237 (let ((old '((a) (erc-b-mode) (c . t) (erc-d-mode . t) (erc-e-mode . t)))
1238 (new '(erc-b-mode erc-d-mode)))
1239 (should (equal (erc--merge-local-modes new old)
1240 '((erc-d-mode erc-e-mode) . (erc-b-mode)))))))
1241
1242(ert-deftest define-erc-module--global ()
1243 (let ((global-module '(define-erc-module mname malias
1244 "Some docstring"
1245 ((ignore a) (ignore b))
1246 ((ignore c) (ignore d)))))
1247
1248 (should (equal (macroexpand global-module)
1249 `(progn
1250
1251 (define-minor-mode erc-mname-mode
1252 "Toggle ERC mname mode.
1253With a prefix argument ARG, enable mname if ARG is positive,
1254and disable it otherwise. If called from Lisp, enable the mode
1255if ARG is omitted or nil.
1256Some docstring"
1257 :global t
1258 :group 'erc-mname
1259 (if erc-mname-mode
1260 (erc-mname-enable)
1261 (erc-mname-disable)))
1262
1263 (defun erc-mname-enable ()
1264 "Enable ERC mname mode."
1265 (interactive)
1266 (cl-pushnew 'mname erc-modules)
1267 (setq erc-mname-mode t)
1268 (ignore a) (ignore b))
1269
1270 (defun erc-mname-disable ()
1271 "Disable ERC mname mode."
1272 (interactive)
1273 (setq erc-modules (delq 'mname erc-modules))
1274 (setq erc-mname-mode nil)
1275 (ignore c) (ignore d))
1276
1277 (defalias 'erc-malias-mode #'erc-mname-mode)
1278
1279 (put 'erc-mname-mode 'definition-name 'mname)
1280 (put 'erc-mname-enable 'definition-name 'mname)
1281 (put 'erc-mname-disable 'definition-name 'mname))))))
1282
1283(ert-deftest define-erc-module--local ()
1284 (let* ((global-module '(define-erc-module mname malias
1285 "Some docstring"
1286 ((ignore a) (ignore b))
1287 ((ignore c) (ignore d))
1288 'local))
1289 (got (macroexpand global-module))
1290 (arg-en (cadr (nth 2 (nth 2 got))))
1291 (arg-dis (cadr (nth 2 (nth 3 got)))))
1292
1293 (should (equal got
1294 `(progn
1295 (define-minor-mode erc-mname-mode
1296 "Toggle ERC mname mode.
1297With a prefix argument ARG, enable mname if ARG is positive,
1298and disable it otherwise. If called from Lisp, enable the mode
1299if ARG is omitted or nil.
1300Some docstring"
1301 :global nil
1302 :group 'erc-mname
1303 (if erc-mname-mode
1304 (erc-mname-enable)
1305 (erc-mname-disable)))
1306
1307 (defun erc-mname-enable (&optional ,arg-en)
1308 "Enable ERC mname mode.
1309With ARG, do so in all buffers for the current connection."
1310 (interactive "p")
1311 (when (derived-mode-p 'erc-mode)
1312 (if ,arg-en
1313 (erc-with-all-buffers-of-server
1314 erc-server-process nil
1315 (erc-mname-enable))
1316 (setq erc-mname-mode t)
1317 (ignore a) (ignore b))))
1318
1319 (defun erc-mname-disable (&optional ,arg-dis)
1320 "Disable ERC mname mode.
1321With ARG, do so in all buffers for the current connection."
1322 (interactive "p")
1323 (when (derived-mode-p 'erc-mode)
1324 (if ,arg-dis
1325 (erc-with-all-buffers-of-server
1326 erc-server-process nil
1327 (erc-mname-disable))
1328 (setq erc-mname-mode nil)
1329 (ignore c) (ignore d))))
1330
1331 (defalias 'erc-malias-mode #'erc-mname-mode)
1332
1333 (put 'erc-mname-mode 'definition-name 'mname)
1334 (put 'erc-mname-enable 'definition-name 'mname)
1335 (put 'erc-mname-disable 'definition-name 'mname))))))
1336
1181;;; erc-tests.el ends here 1337;;; erc-tests.el ends here