diff options
| author | F. Jason Park | 2021-07-12 03:44:28 -0700 |
|---|---|---|
| committer | Amin Bandali | 2022-11-23 19:56:31 -0500 |
| commit | 4c4936fab2ecd97ff6e03e5cfe12def4626c718b (patch) | |
| tree | 573e992298f17fd23709fddafb2979a49646b2d9 | |
| parent | dc6ff142bc1c1a8596436e08ddbccb39d8fdcf39 (diff) | |
| download | emacs-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.texi | 39 | ||||
| -rw-r--r-- | etc/ERC-NEWS | 9 | ||||
| -rw-r--r-- | lisp/erc/erc-common.el | 82 | ||||
| -rw-r--r-- | lisp/erc/erc-goodies.el | 1 | ||||
| -rw-r--r-- | lisp/erc/erc.el | 104 | ||||
| -rw-r--r-- | test/lisp/erc/erc-tests.el | 156 |
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 | ||
| 391 | There is a spiffy customize interface, which may be reached by typing | 391 | There 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}}. |
| 393 | Alternatively, set @code{erc-modules} manually and then call | 393 | When removing a module outside of the Custom ecosystem, you may wish |
| 394 | @code{erc-update-modules}. | 394 | to ensure it's disabled by invoking its associated minor-mode toggle, |
| 395 | such as @kbd{M-x erc-spelling-mode @key{RET}}. Note that, these days, | ||
| 396 | calling @code{erc-update-modules} in an init file is typically | ||
| 397 | unnecessary. | ||
| 395 | 398 | ||
| 396 | The following is a list of available modules. | 399 | The 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 | |||
| 526 | All modules operate as minor modes under the hood, and some newer ones | ||
| 527 | may be defined as buffer-local. These so-called ``local modules'' are | ||
| 528 | a work in progress and their behavior and interface are subject to | ||
| 529 | change. 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 | ||
| 534 | IRC sessions and override @code{erc-module} membership when influencing | ||
| 535 | module activation in new sessions. | ||
| 536 | @item | ||
| 537 | Removing a local module from @code{erc-modules} via Customize not only | ||
| 538 | disables its mode but also kills its control variable in all ERC | ||
| 539 | buffers. | ||
| 540 | @item | ||
| 541 | ``Mode toggles,'' like @code{erc-sasl-mode} and | ||
| 542 | @code{erc-sasl-enable}, behave differently relative to each other and | ||
| 543 | to their global counterparts. (More on this just below.) | ||
| 544 | @end enumerate | ||
| 545 | |||
| 546 | By default, all local-mode toggles, like @code{erc-sasl-mode}, only | ||
| 547 | affect the current buffer, but their ``non-mode'' variants, such as | ||
| 548 | @code{erc-sasl-enable}, operate on all buffers belonging to a | ||
| 549 | connection when called interactively. Keep in mind that whether | ||
| 550 | enabled or not, a module may effectively be ``inert'' in certain types | ||
| 551 | of buffers, such as queries and channels. Whatever the case, a local | ||
| 552 | toggle 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 | |||
| 125 | through and has thus been deprecated with no public replacement; it | 125 | through and has thus been deprecated with no public replacement; it |
| 126 | has also been removed from the client code path. | 126 | has also been removed from the client code path. |
| 127 | 127 | ||
| 128 | The function 'erc-open' now delays running 'erc-mode-hook' members | ||
| 129 | until most local session variables have been initialized (minus those | ||
| 130 | connection-related ones in erc-backend). 'erc-open' also no longer | ||
| 131 | calls 'erc-update-modules', although modules are still activated | ||
| 132 | in an identical fashion. | ||
| 133 | |||
| 134 | Some groundwork has been laid for what may become a new breed of ERC | ||
| 135 | module, namely, "connection-local" (or simply "local") modules. | ||
| 136 | |||
| 128 | A few internal variables have been introduced that could just as well | 137 | A few internal variables have been introduced that could just as well |
| 129 | have been made public, possibly as user options. Likewise for some | 138 | have been made public, possibly as user options. Likewise for some |
| 130 | internal functions. As always, users needing such functionality | 139 | internal 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. | ||
| 101 | Keys need not be unique: a library may define more than one | ||
| 102 | module. Sometimes a module's downcased alias will be its | ||
| 103 | canonical 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 | |||
| 103 | an alias erc-ALIAS-mode, as well as the helper functions | 162 | an alias erc-ALIAS-mode, as well as the helper functions |
| 104 | erc-NAME-enable, and erc-NAME-disable. | 163 | erc-NAME-enable, and erc-NAME-disable. |
| 105 | 164 | ||
| 165 | With LOCAL-P, these helpers take on an optional argument that, | ||
| 166 | when non-nil, causes them to act on all buffers of a connection. | ||
| 167 | This feature is mainly intended for interactive use and does not | ||
| 168 | carry over to their respective minor-mode toggles. Beware that | ||
| 169 | for global modules, these helpers and toggles all mutate | ||
| 170 | `erc-modules'. | ||
| 171 | |||
| 106 | Example: | 172 | Example: |
| 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) | 1881 | Except 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. | ||
| 1929 | In the first, put modes to be enabled in a new ERC buffer by | ||
| 1930 | calling their associated functions. In the second, put modes to | ||
| 1931 | be marked as disabled by setting their associated variables to | ||
| 1932 | nil." | ||
| 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. | ||
| 1253 | With a prefix argument ARG, enable mname if ARG is positive, | ||
| 1254 | and disable it otherwise. If called from Lisp, enable the mode | ||
| 1255 | if ARG is omitted or nil. | ||
| 1256 | Some 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. | ||
| 1297 | With a prefix argument ARG, enable mname if ARG is positive, | ||
| 1298 | and disable it otherwise. If called from Lisp, enable the mode | ||
| 1299 | if ARG is omitted or nil. | ||
| 1300 | Some 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. | ||
| 1309 | With 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. | ||
| 1321 | With 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 |