emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 32c627a5ac3: Merge remote-tracking branch 'origin/master


From: Po Lu
Subject: feature/android 32c627a5ac3: Merge remote-tracking branch 'origin/master' into feature/android
Date: Mon, 12 Jun 2023 20:36:01 -0400 (EDT)

branch: feature/android
commit 32c627a5ac314ff0ca97ac99d2357f84565f2581
Merge: 1cd514c297f 410aac81832
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/android
---
 doc/misc/erc.texi                                  |  27 ++-
 etc/ERC-NEWS                                       |  50 ++++-
 lisp/emacs-lisp/macroexp.el                        |   6 +-
 lisp/erc/erc-backend.el                            |   4 +-
 lisp/erc/erc-button.el                             | 203 +++++++++++++--------
 lisp/erc/erc-dcc.el                                |   3 +-
 lisp/erc/erc-fill.el                               |  33 ++--
 lisp/erc/erc-goodies.el                            |   6 +-
 lisp/erc/erc-imenu.el                              |   6 +-
 lisp/erc/erc-match.el                              |   4 +-
 lisp/erc/erc-sound.el                              |   8 +-
 lisp/erc/erc-spelling.el                           |   4 +
 lisp/erc/erc-stamp.el                              |   6 +-
 lisp/erc/erc.el                                    | 126 +++++--------
 lisp/transient.el                                  |  52 +++---
 test/lisp/erc/erc-dcc-tests.el                     |  10 +-
 test/lisp/erc/erc-fill-tests.el                    |   6 +-
 test/lisp/erc/erc-networks-tests.el                |  24 +--
 test/lisp/erc/erc-scenarios-base-renick.el         |  43 -----
 test/lisp/erc/erc-stamp-tests.el                   |   7 +-
 test/lisp/erc/erc-tests.el                         | 144 +++++++++------
 .../resources/base/renick/regain/normal-again.eld  |  56 ------
 .../erc/resources/base/renick/regain/normal.eld    |  53 ------
 .../resources/fill/snapshots/merge-01-start.eld    |   2 +-
 .../resources/fill/snapshots/merge-02-right.eld    |   2 +-
 .../fill/snapshots/monospace-01-start.eld          |   2 +-
 .../fill/snapshots/monospace-02-right.eld          |   2 +-
 .../resources/fill/snapshots/monospace-03-left.eld |   2 +-
 .../fill/snapshots/monospace-04-reset.eld          |   2 +-
 .../resources/fill/snapshots/spacing-01-mono.eld   |   2 +-
 30 files changed, 421 insertions(+), 474 deletions(-)

diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index 14c6a457654..e848ed21a50 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -1281,20 +1281,23 @@ something appropriate, like @code{("tor" "127.0.0.1" 
9050 5)}.  For
 some networks, setting @code{erc-server-connect-function} to
 @code{socks-open-network-stream} might be enough.  Others, like
 @samp{Libera.Chat}, involve additional setup.  At the time of writing,
-connecting to @samp{Libera.Chat} requires both @acronym{TLS} and a
-non-@samp{PLAIN} @acronym{SASL} mechanism (@pxref{SASL}).  One way to
-achieve that is by using the @samp{EXTERNAL} mechanism, as shown in
-the following example:
+connecting to that network requires both @acronym{TLS} and a permitted
+@acronym{SASL} mechanism, like @samp{EXTERNAL} (@pxref{SASL}), as
+shown in the following example:
 
 @lisp
 (require 'erc)
 (require 'socks)
 
-(let* ((socks-password "")
-       (socks-server '("tor" "localhost" 9050 5))
-       (erc-modules (cons 'sasl erc-modules))
+(defun my-erc-open-socks-tls-stream (&rest args)
+  (let ((socks-username "")
+        (socks-password "")
+        (socks-server '("tor" "localhost" 9050 5)))
+    (apply #'erc-open-socks-tls-stream args)))
+
+(let* ((erc-modules (cons 'sasl erc-modules))
        (erc-sasl-mechanism 'external)
-       (erc-server-connect-function #'erc-open-socks-tls-stream))
+       (erc-server-connect-function #'my-erc-open-socks-tls-stream))
   (erc-tls
    :server "libera75jm6of4wxpxt4aynol3xjmbtxgfyjpu34ss4d7r7q2v5zrpyd.onion"
    :port 6697
@@ -1304,6 +1307,14 @@ the following example:
    :client-certificate (list "/home/jrh/key.pem" "/home/jrh/cert.pem")))
 @end lisp
 
+@noindent
+Here, the user-provided @code{my-erc-open-socks-tls-stream} ensures
+that the preferred values for @code{socks-server} and friends will be
+available when reconnecting.  If you plan on using @acronym{SOCKS}
+with ERC exclusively, you can just set those options and variables
+globally and bind @code{erc-server-connect-function} to
+@code{erc-open-socks-tls-stream} instead.
+
 @node auth-source
 @subsection auth-source
 @cindex auth-source
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index e9ec9e2caab..68f1083621c 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -1,4 +1,4 @@
-ERC NEWS                                                       -*- outline -*-
+ERC NEWS
 
 Copyright (C) 2006-2023 Free Software Foundation, Inc.
 See the end of the file for license conditions.
@@ -116,13 +116,19 @@ asking users who've customized this option to switch to
 that some other solution, like automatic migration, is justified,
 please make that known on the bug list.
 
-** The 'nicknames' entry in 'erc-button-alist' is officially exceptional.
+** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly.
 It's no secret that the 'buttons' module treats potential nicknames
-specially.  To simplify ERC's move to next-gen "rich UI" extensions,
-this special treatment is being canonized.  From now on, all values
-other than the symbol 'erc-button-buttonize-nicks' appearing in the
-"FORM" field (third element) of this entry are considered deprecated
-and will incur a warning.
+specially.  This is perhaps most evident in its treatment of the
+'nicknames' entry in 'erc-button-alist'.  Indeed, to simplify ERC's
+move to next-gen "rich UI" extensions, this special treatment is being
+canonized.  From here on out, this entry will no longer appear in the
+option's default value but will instead be applied implicitly so long
+as the option 'erc-button-buttonize-nicks' is non-nil, which it is by
+default.  Relatedly, the option 'erc-nick-popup-alist' now favors
+functions, which ERC calls non-interactively, over arbitrary
+s-expressions, which ERC will continue to honor.  Although the default
+lineup remains functionally equivalent, its members have all been
+updated accordingly.
 
 ** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed.
 This option was accidentally removed from the default client in ERC
@@ -172,6 +178,26 @@ impactfully, the value of the 'field' property for ERC's 
prompt has
 changed from 't' to the more useful 'erc-prompt', although the
 property of the same name has been retained.
 
+*** Members of insert- and send-related hooks have been reordered.
+Built-in and third-party modules rely on certain hooks for adjusting
+incoming and outgoing messages upon insertion.  And some modules only
+want to do so after others have done their damage.  Traditionally,
+this required various hacks and finagling to achieve.  And while this
+release makes an effort to load modules in a more consistent order,
+that alone isn't enough to ensure similar predictability among
+essential members of important hooks.
+
+Luckily, ERC now leverages a feature introduced in Emacs 27, "hook
+depth," to secure the positions of a few key members of
+'erc-insert-modify-hook' and 'erc-send-modify-hook'.  So far, this
+includes the functions 'erc-button-add-buttons', 'erc-fill',
+'erc-add-timestamp', and 'erc-match-message', which now appear in that
+order, when present, at depths beginning at 20 and ending below 80.
+Of most interest to module authors is the new relative positioning of
+the first two, 'erc-button-add-buttons' and 'erc-fill', which have
+been swapped with respect to their previous places in recent ERC
+versions.
+
 *** ERC now manages timestamp-related properties a bit differently.
 For starters, the 'cursor-sensor-functions' property no longer
 contains unique closures and thus no longer proves effective for
@@ -218,7 +244,14 @@ running hooks during message insertion, and the position 
of its
 "insert marker" (ERC's per-buffer process mark) was inconsistent
 during these spells.  To make insertion handling more predictable in
 preparation for incorporating various protocol extensions, the prompt
-and its bounding markers have become perennial fixtures.  In rare
+and its bounding markers have become perennial fixtures.  To effect
+this change, small behavioral differences in message insertion have
+been adopted.  Crucially, 'erc-insert-marker' now has an "insertion
+type" of t, and 'erc-display-line-1' now calls 'insert' instead of
+'insert-before-prompt'.  This allows user code to leave its own
+markers via 'erc-insert-modify-hook' and 'erc-insert-post-hook'
+instead of having to resort to workarounds.  Message insertion for
+outgoing messages, in 'erc-display-msg', remains as before.  In rare
 cases, these changes may mean third-party code needs tweaking, for
 example, requiring the use of 'insert-before-markers' instead of
 'insert'.  As always, users feeling unduly inconvenienced by these
@@ -1926,5 +1959,6 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.
 Local variables:
 coding: utf-8
 mode: outline
+mode: emacs-news
 paragraph-separate: "[         ]*$"
 end:
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index b05aba3e1a7..8a0185d597b 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -458,7 +458,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
                  ((and `#',f
                        (guard (not (or (special-form-p f) (macrop f))))) ;; 
bug#46636
                   (macroexp--expand-all `(,f . ,eargs)))
-                 (_ `(funcall ,eexp . ,eargs)))))
+                 (_ `(,fn ,eexp . ,eargs)))))
             (`(funcall . ,_) form)      ;bug#53227
             (`(,func . ,_)
              (let ((handler (function-get func 'compiler-macro))
@@ -479,9 +479,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
                ;; byte-optimize-form because the output of the compiler-macro 
can
                ;; use macros.
                (if (null handler)
-                   ;; No compiler macro.  We just expand each argument (for
-                   ;; setq/setq-default this works alright because the 
variable names
-                   ;; are symbols).
+                   ;; No compiler macro.  We just expand each argument.
                    (macroexp--all-forms form 1)
                  ;; If the handler is not loaded yet, try (auto)loading the
                  ;; function itself, which may in turn load the handler.
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 2de24e7cb25..b5bd96c189d 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -427,9 +427,7 @@ This only has an effect if `erc-server-auto-reconnect' is 
non-nil."
 If this value is too low, servers may reject your initial nick
 request upon reconnecting because they haven't yet noticed that
 your previous connection is dead.  If this happens, try setting
-this value to 120 or greater and/or exploring the option
-`erc-nickname-in-use-functions', which may provide a more
-proactive means of handling this situation on some servers."
+this value to 120 or greater."
   :type 'number)
 
 (defcustom erc-server-reconnect-function 'erc-server-delayed-reconnect
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 33b93ff6744..08610860630 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -52,13 +52,15 @@
 ;;;###autoload(autoload 'erc-button-mode "erc-button" nil t)
 (define-erc-module button nil
   "This mode buttonizes all messages according to `erc-button-alist'."
-  ((erc-button--check-nicknames-entry)
-   (add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 'append)
-   (add-hook 'erc-send-modify-hook #'erc-button-add-buttons 'append)
+  ((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))
    (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)))
 
@@ -103,7 +105,10 @@ longer than `erc-fill-column'."
   :type '(choice integer boolean))
 
 (defcustom erc-button-buttonize-nicks t
-  "Flag indicating whether nicks should be buttonized or not."
+  "Flag indicating whether nicks should be buttonized.
+Note that beginning in ERC 5.6, some functionality provided by
+other modules, such as `fill-wrap', may depend on this option
+being non-nil."
   :type 'boolean)
 
 (defcustom erc-button-rfc-url "https://tools.ietf.org/html/rfc%s";
@@ -126,8 +131,7 @@ longer than `erc-fill-column'."
   ;; a button, it makes no sense to optimize performance by
   ;; bytecompiling lambdas in this alist.  On the other hand, it makes
   ;; things hard to maintain.
-  '((nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
-    (erc-button-url-regexp 0 t browse-url-button-open-url 0)
+  '((erc-button-url-regexp 0 t browse-url-button-open-url 0)
     ;; ("<URL: *\\([^<> ]+\\) *>" 0 t browse-url-button-open-url 1)
 ;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
     ;; emacs internal
@@ -159,41 +163,45 @@ REGEXP is the string matching text around the button or a 
symbol
   strings, or an alist with the strings in the car.  Note that
   entries in lists or alists are considered to be nicks or other
   complete words.  Therefore they are enclosed in \\< and \\>
-  while searching.  REGEXP can also be the symbol
-  `nicknames', which matches the nickname of any user on the
-  current server.
+  while searching.  Also, use of the special symbol `nicknames'
+  for this slot was deprecated in ERC 5.6, but users can still
+  use `erc-button-buttonize-nicks' to control whether nicks get
+  buttonized.  And because customizing a corresponding CALLBACK
+  is no longer possible, an escape hatch has been provided via
+  the variable `erc-button-nickname-callback-function'.
 
 BUTTON is the number of the regexp grouping actually matching the
-  button.  This is ignored if REGEXP is `nicknames'.
+  button.
 
 FORM is either a boolean or a special variable whose value must
-  be non-nil for the button to be added.  When REGEXP is the
-  special symbol `nicknames', FORM must be the symbol
-  `erc-button-buttonize-nicks'.  Anything else is deprecated.
-  For all other entries, FORM can also be a function to call in
-  place of `erc-button-add-button' with the exact same arguments.
-  When FORM is also a special variable, ERC disregards the
-  variable and calls the function.
+  be non-nil for the button to be added.  It can also be a
+  function to call in place of `erc-button-add-button' with the
+  exact same arguments.  When FORM is also a special variable,
+  ERC disregards the variable and calls the function.  Note that
+  arbitrary s-expressions were deprecated in ERC 5.6 and may not
+  be respected in the future.  If necessary, users can instead
+  supply a function that calls `erc-button-add-button' when such
+  an expression is non-nil.
 
 CALLBACK is the function to call when the user push this button.
   CALLBACK can also be a symbol.  Its variable value will be used
   as the callback function.
 
 PAR is a number of a regexp grouping whose text will be passed to
-  CALLBACK.  There can be several PAR arguments.  If REGEXP is
-  `nicknames', these are ignored, and CALLBACK will be called with
-  the nickname matched as the argument."
+  CALLBACK.  There can be several PAR arguments."
   :package-version '(ERC . "5.6") ; FIXME sync on release
   :type '(repeat
           (list :tag "Button"
                 (choice :tag "Matches"
                         regexp
                         (variable :tag "Variable containing regexp")
-                        (const :tag "Nicknames" nicknames))
+                        (repeat :tag "List of words" string)
+                        (alist :key-type string :value-type sexp))
                 (integer :tag "Number of the regexp section that matches")
                 (choice :tag "When to buttonize"
                         (const :tag "Always" t)
-                        (sexp :tag "Only when this evaluates to non-nil"))
+                        (function :tag "Alternative buttonizing function")
+                        (variable :tag "Var with value treated as boolean"))
                 (function :tag "Function to call when button is pressed")
                 (repeat :tag "Sections of regexp to send to the function"
                         :inline t
@@ -239,15 +247,40 @@ constituents.")
 (defvar erc-button-keys-added nil
   "Internal variable used to keep track of whether we've added the
 global-level ERC button keys yet.")
+(make-obsolete-variable 'erc-button-keys-added "no longer relevant" "30.1")
+
+(defvar-local erc-button--has-nickname-entry nil
+  "Whether `erc-button-alist' contains a legacy `nicknames' entry.")
 
-;; Maybe deprecate this function and `erc-button-keys-added' if they
-;; continue to go unused for a another version (currently 5.6).
 (defun erc-button-setup ()
-  "Add ERC mode-level button movement keys.  This is only done once."
-  ;; Add keys.
-  (unless erc-button-keys-added
-    (define-key erc-mode-map (kbd "<backtab>") #'erc-button-previous)
-    (setq erc-button-keys-added t)))
+  "Perform major-mode setup for ERC's button module.
+Note that prior to ERC 5.6, this function used to modify
+`erc-mode-map', but that's now handled by the mode toggles
+themselves."
+  (setq erc-button-keys-added t)
+  (cl-assert (derived-mode-p 'erc-mode))
+  ;; It would probably suffice to run this in server buffers alone,
+  ;; even though buttonizing happens in all ERC buffers and users have
+  ;; been known to set `erc-button-alist' locally.
+  (dolist (entry erc-button-alist)
+    (pcase entry
+      ((or `(nicknames ,_ ,sym . ,_) `('nicknames ,_ ,sym . ,_))
+       (setq erc-button--has-nickname-entry t)
+       (unless (eq sym 'erc-button-buttonize-nicks)
+         (erc--warn-once-before-connect 'erc-button-mode
+           "The legacy `nicknames' entry in `erc-button-alist'"
+           " is deprecated.  See doc string for details.")))
+      ((and `(,_ ,_ ,form . ,_)
+            (guard (not (or (and (symbolp form)
+                                 (special-variable-p form))
+                            (functionp form)))))
+       (erc--warn-once-before-connect 'erc-button-mode
+         "Arbitrary sexps for the third, FORM slot of `erc-button-alist'"
+         " entries are deprecated. Either use a variable or a function"
+         " that conditionally calls `erc-button-add-button'.")))))
+
+(defvar erc-button-nickname-callback-function #'erc-nick-popup
+  "Escape hatch for those needing a different nickname callback.")
 
 (defun erc-button-add-buttons ()
   "Find external references in the current buffer and make buttons of them.
@@ -261,6 +294,11 @@ specified by `erc-button-alist'."
             (alist erc-button-alist)
             regexp)
         (erc-button-remove-old-buttons)
+        (unless (or erc-button--has-nickname-entry
+                    (not erc-button-buttonize-nicks))
+          (erc-button-add-nickname-buttons
+           `(_ _ erc-button--modify-nick-function
+               ,erc-button-nickname-callback-function)))
         (dolist (entry alist)
           (if (or (eq (car entry) 'nicknames)
                   ;; Old form retained for backward compatibility.
@@ -284,28 +322,18 @@ specified by `erc-button-alist'."
                         (concat "\\<" (regexp-quote (car elem)) "\\>")
                         entry)))))))))))
 
-(defun erc-button--maybe-warn-arbitrary-sexp (form)
-  (cl-assert (not (booleanp form))) ; covered by caller
+(defun erc-button--extract-form (form)
   ;; If a special-variable is also a function, favor the function.
-  (cond ((functionp form) form)
-        ((and (symbolp form) (special-variable-p form)) (symbol-value form))
-        (t (unless (get 'erc-button--maybe-warn-arbitrary-sexp
-                        'warned-arbitrary-sexp)
-             (put 'erc-button--maybe-warn-arbitrary-sexp
-                  'warned-arbitrary-sexp t)
-             (lwarn 'erc :warning (concat "Arbitrary sexps for the third FORM"
-                                          " slot of `erc-button-alist' entries"
-                                          " have been deprecated.")))
-           (eval form t))))
-
-(defun erc-button--check-nicknames-entry ()
-  ;; This helper exists because the module is defined after its options.
-  (when (eq major-mode 'erc-mode)
-    (unless (eq (nth 1 (alist-get 'nicknames erc-button-alist))
-                'erc-button-buttonize-nicks)
-      (erc-button--display-error-notice-with-keys-and-warn
-       "Values other than `erc-button-buttonize-nicks' in the third slot of "
-       "the `nicknames' entry of `erc-button-alist' are deprecated."))))
+  (cond ((eq t form) t)
+        ((functionp form) form)
+        ((and (symbolp form) (special-variable-p form))
+         (while (let ((val (symbol-value form)))
+                  (prog1 (and (not (eq val form))
+                              (symbolp val)
+                              (special-variable-p val))
+                    (setq form val))))
+         form)
+        (t (eval form t))))
 
 (cl-defstruct erc-button--nick
   ( bounds nil :type cons
@@ -405,12 +433,10 @@ retrieve it during buttonizing via
   "Search through the buffer for nicknames, and add buttons."
   (let ((form (nth 2 entry))
         (fun (nth 3 entry))
+        (erc-button-buttonize-nicks (and erc-button-buttonize-nicks
+                                         erc-button--modify-nick-function))
         bounds word)
-    (when (eq form 'erc-button-buttonize-nicks)
-      (setq form (and (symbol-value form) erc-button--modify-nick-function)))
-    (when (or (functionp form)
-              (eq t form)
-              (and form (erc-button--maybe-warn-arbitrary-sexp form)))
+    (when (and form (setq form (erc-button--extract-form form)))
       (goto-char (point-min))
       (while (erc-forward-word)
         (when (setq bounds (erc-bounds-of-word-at-point))
@@ -456,8 +482,7 @@ retrieve it during buttonizing via
                        (and-let*
                            ((raw-form (nth 2 entry))
                             (res (or (eq t raw-form)
-                                     (erc-button--maybe-warn-arbitrary-sexp
-                                      raw-form))))
+                                     (erc-button--extract-form raw-form))))
                          (if (functionp res) res #'erc-button-add-button)))))
       (let ((start (match-beginning (nth 1 entry)))
             (end (match-end (nth 1 entry)))
@@ -660,20 +685,20 @@ greater than `point-min' with a text property of 
`erc-callback'.")
 ;;; Nickname buttons:
 
 (defcustom erc-nick-popup-alist
-  '(("DeOp"  . (erc-cmd-DEOP nick))
-    ("Kick"  . (erc-cmd-KICK (concat nick " "
-                                     (read-from-minibuffer
-                                      (concat "Kick " nick ", reason: ")))))
-    ("Msg"   . (erc-cmd-MSG (concat nick " "
-                                    (read-from-minibuffer
-                                     (concat "Message to " nick ": ")))))
-    ("Op"    . (erc-cmd-OP nick))
-    ("Query" . (erc-cmd-QUERY nick))
-    ("Whois" . (erc-cmd-WHOIS nick))
-    ("Lastlog" . (erc-cmd-LASTLOG nick)))
+  '(("DeOp"  . erc-cmd-DEOP)
+    ("Kick"  . erc-button-cmd-KICK)
+    ("Msg"   . erc-button-cmd-MSG)
+    ("Op"    . erc-cmd-OP)
+    ("Query" . erc-cmd-QUERY)
+    ("Whois" . erc-cmd-WHOIS)
+    ("Lastlog" . erc-cmd-LASTLOG))
   "An alist of possible actions to take on a nickname.
-An entry looks like (\"Action\" . SEXP) where SEXP is evaluated with
-the variable `nick' bound to the nick in question.
+For all entries (ACTION . FUNC), ERC offers ACTION as a possible
+completion item and calls the selected entry's FUNC with the
+buttonized nickname at point as the only argument.  For
+historical reasons, FUNC can also be an arbitrary sexp, in which
+case, ERC binds the nick in question to the variable `nick' and
+evaluates the expression.
 
 Examples:
  (\"DebianDB\" .
@@ -681,18 +706,48 @@ Examples:
    (format
     \"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\"
     nick)))"
+  :package-version '(ERC . "5.6") ; FIXME sync on release
   :type '(repeat (cons (string :tag "Op")
-                       sexp)))
+                       (choice function sexp))))
+
+(defun erc-button-cmd-KICK (nick)
+  "Prompt for a reason, then kick NICK via `erc-cmd-KICK'.
+In server buffers, also prompt for a channel."
+  (erc-cmd-KICK
+   (or (and erc--target (erc-default-target))
+       (let ((targets (mapcar (lambda (b)
+                                (cons (erc--target-string
+                                       (buffer-local-value 'erc--target b))
+                                      b))
+                              (erc-channel-list erc-server-process))))
+         (completing-read (format "Channel (%s): " (caar targets))
+                          targets (pcase-lambda (`(,_ . ,buf))
+                                    (with-current-buffer buf
+                                      (erc-get-channel-user nick)))
+                          t nil t (caar targets))))
+   nick
+   (read-from-minibuffer "Reason: ")))
+
+(defun erc-button-cmd-MSG (nick)
+  "Prompt for a message to NICK, and send it via `erc-cmd-MSG'."
+  (let ((msg (read-from-minibuffer (concat "Message to " nick ": "))))
+    (erc-cmd-MSG (concat nick " " msg))))
+
+(defvar-local erc-button--nick-popup-alist nil
+  "Internally controlled items for `erc-nick-popup-alist'.")
 
 (defun erc-nick-popup (nick)
   (let* ((completion-ignore-case t)
+         (alist (append erc-nick-popup-alist erc-button--nick-popup-alist))
          (action (completing-read (format-message
                                    "What action to take on `%s'? " nick)
-                                  erc-nick-popup-alist))
-         (code (cdr (assoc action erc-nick-popup-alist))))
+                                  alist))
+         (code (cdr (assoc action alist))))
     (when code
       (erc-set-active-buffer (current-buffer))
-      (eval code `((nick . ,nick))))))
+      (if (functionp code)
+          (funcall code nick)
+        (eval code `((nick . ,nick)))))))
 
 ;;; Callback functions
 (defun erc-button-describe-symbol (symbol-name)
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 2012bcadae1..cc2dcc9a788 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -1213,9 +1213,8 @@ other client."
             erc-dcc-from nick
             erc-dcc-entry-data entry
             erc-dcc-unprocessed-output ""
-            erc-insert-marker (point-max-marker)
             erc-input-marker (make-marker))
-      (erc-display-prompt buffer (point-max))
+      (erc--initialize-markers (point) nil)
       (set-process-buffer proc buffer)
       (add-hook 'kill-buffer-hook #'erc-dcc-chat-buffer-killed nil t)
       (run-hook-with-args 'erc-dcc-chat-connect-hook proc))
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index 718e51a058c..5115e45210d 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -49,8 +49,8 @@ the channel buffers are filled."
   ;; other modules.  Ideally, this module's processing should happen
   ;; after "morphological" modifications to a message's text but
   ;; before superficial decorations.
-  ((add-hook 'erc-insert-modify-hook #'erc-fill)
-   (add-hook 'erc-send-modify-hook #'erc-fill))
+  ((add-hook 'erc-insert-modify-hook #'erc-fill 40)
+   (add-hook 'erc-send-modify-hook #'erc-fill 40))
   ((remove-hook 'erc-insert-modify-hook #'erc-fill)
    (remove-hook 'erc-send-modify-hook #'erc-fill)))
 
@@ -336,7 +336,7 @@ one of the minor-mode toggles if really necessary."
      erc-fill--wrap-value erc-fill-static-center)
    (setq erc-fill--function #'erc-fill-wrap)
    ;; Internal integrations.
-   (add-function :filter-args (local 'erc-stamp--insert-date-function)
+   (add-function :after (local 'erc-stamp--insert-date-function)
                  #'erc-fill--wrap-stamp-insert-prefixed-date)
    (when (or erc-stamp-mode (memq 'stamp erc-modules))
      (erc-stamp--display-margin-mode +1))
@@ -398,14 +398,24 @@ parties.")
               ((erc-nick-equal-p (car props) nick))))
     (set-marker erc-fill--wrap-last-msg (point-min))))
 
-(defun erc-fill--wrap-stamp-insert-prefixed-date (args)
+(defun erc-fill--wrap-stamp-insert-prefixed-date (&rest args)
   "Apply `line-prefix' property to args."
-  (let* ((ts-left (car args)))
-    (put-text-property 0 (length ts-left) 'line-prefix
-                       `(space :width
-                               (- erc-fill--wrap-value
-                                  ,(length (string-trim-left ts-left))))
-                       ts-left))
+  (let* ((ts-left (car args))
+         (start)
+         ;; Insert " " to simulate gap between <speaker> and msg beg.
+         (end (save-excursion (skip-chars-backward "\n")
+                              (setq start (pos-bol))
+                              (insert " ")
+                              (point)))
+         (width (if (and erc-fill-wrap-use-pixels
+                         (fboundp 'buffer-text-pixel-size))
+                    (save-restriction (narrow-to-region start end)
+                                      (list (car (buffer-text-pixel-size))))
+                  (length (string-trim-left ts-left)))))
+    (delete-region (1- end) end)
+    ;; Use `point-min' instead of `start' to cover leading newilnes.
+    (put-text-property (point-min) (point) 'line-prefix
+                       `(space :width (- erc-fill--wrap-value ,width))))
   args)
 
 (defun erc-fill-wrap ()
@@ -434,8 +444,7 @@ See `erc-fill-wrap-mode' for details."
                               (narrow-to-region (point-min) (point))
                               (list (car (buffer-text-pixel-size)))))
                            (t (- (point) (point-min))))))))
-      ;; Leaving out the final newline doesn't seem to affect anything.
-      (erc-put-text-properties (point-min) (point-max)
+      (erc-put-text-properties (point-min) (1- (point-max)) ; exclude "\n"
                                '(line-prefix wrap-prefix) nil
                                `((space :width (- erc-fill--wrap-value ,len))
                                  (space :width erc-fill--wrap-value))))))
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 01eae4b63c5..afc05148506 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -53,8 +53,7 @@ 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)
-   (unless erc--updating-modules-p
-     (erc-buffer-filter #'erc-add-scroll-to-bottom)))
+   (unless erc--updating-modules-p (erc-buffer-do #'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))
@@ -119,8 +118,7 @@ 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)
-   (unless erc--updating-modules-p
-     (erc-buffer-filter #'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))
      (with-current-buffer buffer
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 9864d7c4042..f053c6279b8 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -41,6 +41,10 @@
 (require 'erc)
 (require 'imenu)
 
+(defgroup erc-imenu nil
+  "Imenu integration for ERC."
+  :group 'erc)
+
 (defun erc-unfill-notice ()
   "Return text from point to a computed end as a string unfilled.
 Don't rely on this function, read it first!"
@@ -139,7 +143,7 @@ Don't rely on this function, read it first!"
 (define-erc-module imenu nil
   "Simple Imenu integration for ERC."
   ((add-hook 'erc-mode-hook #'erc-imenu-setup)
-   (unless erc--updating-modules-p (erc-buffer-filter #'erc-imenu-setup)))
+   (unless erc--updating-modules-p (erc-buffer-do #'erc-imenu-setup)))
   ((remove-hook 'erc-mode-hook #'erc-imenu-setup)
    (erc-with-all-buffers-of-server nil nil
      (when erc-imenu--create-index-function
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 86883260413..6ba524ef9a8 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -52,10 +52,10 @@ they are hidden or highlighted.  This is controlled via the 
variables
 `erc-current-nick-highlight-type'.  For all these highlighting types,
 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-insert-modify-hook #'erc-match-message 60)
    (add-hook 'erc-mode-hook #'erc-match--modify-invisibility-spec)
    (unless erc--updating-modules-p
-     (erc-buffer-filter #'erc-match--modify-invisibility-spec))
+     (erc-buffer-do #'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-sound.el b/lisp/erc/erc-sound.el
index 9da9202f0cf..083d72805df 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -47,6 +47,10 @@
 
 (require 'erc)
 
+(defgroup erc-sound nil
+  "Make ERC play bells and whistles while chatting with people."
+  :group 'erc)
+
 ;;;###autoload(put 'ctcp-sound 'erc--module 'sound)
 ;;;###autoload(autoload 'erc-sound-mode "erc-sound")
 (define-erc-module sound ctcp-sound
@@ -61,10 +65,6 @@ and play sound files as requested."
 
 (erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
 
-(defgroup erc-sound nil
-  "Make ERC play bells and whistles while chatting with people."
-  :group 'erc)
-
 (defcustom erc-play-sound t
   "Play sounds when you receive CTCP SOUND requests."
   :type 'boolean)
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 8e5424f4162..83eb849f1b4 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -33,6 +33,10 @@
 (require 'erc)
 (require 'flyspell)
 
+(defgroup erc-spelling nil
+  "Flyspell integration for ERC."
+  :group 'erc)
+
 ;;;###autoload(autoload 'erc-spelling-mode "erc-spelling" nil t)
 (define-erc-module spelling nil
   "Enable flyspell mode in ERC buffers."
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index 500f6f3c0c9..aac51135a07 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -163,12 +163,12 @@ from entering them and instead jump over them."
 (define-erc-module stamp timestamp
   "This mode timestamps messages in the channel buffers."
   ((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-insert-modify-hook #'erc-add-timestamp 50)
+   (add-hook 'erc-send-modify-hook #'erc-add-timestamp 50)
    (add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
    (add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
    (unless erc--updating-modules-p
-     (erc-buffer-filter #'erc-munge-invisibility-spec)))
+     (erc-buffer-do #'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)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 2c2df81fa6d..a1538962602 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -403,24 +403,6 @@ Each function should accept two arguments, NEW-NICK and 
OLD-NICK."
   :group 'erc-hooks
   :type 'hook)
 
-(defcustom erc-nickname-in-use-functions nil
-  "Function to run before trying for a different nickname.
-Called with two arguments: the desired but just rejected nickname
-and the alternate nickname about to be requested.  Use cases
-include special handling during connection registration and
-wrestling with nickname services.  For example, value
-`erc-regain-nick-on-connect' is aimed at dealing with reaping
-lingering connections that may prevent you from being issued a
-requested nick immediately when reconnecting.  It's meant to be
-used with an `erc-server-reconnect-function' value of
-`erc-server-delayed-check-reconnect' alongside SASL
-authentication."
-  :package-version '(ERC . "5.6")
-  :group 'erc-hooks
-  :type '(choice (function-item erc-regain-nick-on-connect)
-                 function
-                 (const nil)))
-
 (defcustom erc-connect-pre-hook '(erc-initialize-log-marker)
   "Hook called just before `erc' calls `erc-connect'.
 Functions are passed a buffer as the first argument."
@@ -1830,8 +1812,9 @@ If PROC is not supplied, all processes are searched."
 
 (defun erc-buffer-filter (predicate &optional proc)
   "Return a list of `erc-mode' buffers matching certain criteria.
-PREDICATE is a function executed with each buffer, if it returns t, that buffer
-is considered a valid match.
+Call PREDICATE without arguments in all ERC buffers or only those
+belonging to a non-nil PROC.  Expect it to return non-nil in
+buffers that should be included in the returned list.
 
 PROC is either an `erc-server-process', identifying a certain
 server connection, or nil which means all open connections."
@@ -1843,15 +1826,21 @@ server connection, or nil which means all open 
connections."
                 (erc--buffer-p buf predicate proc)))
              (buffer-list)))))
 
+(defalias 'erc-buffer-do 'erc-buffer-filter
+  "Call FUNCTION in all ERC buffers or only those for PROC.
+Expect users to prefer this alias to `erc-buffer-filter' in cases
+where the latter would only be called for effect and its return
+value thrown away.
+
+\(fn FUNCTION &optional PROC)")
+
 (defun erc-buffer-list (&optional predicate proc)
   "Return a list of ERC buffers.
 PREDICATE is a function which executes with every buffer satisfying
 the predicate.  If PREDICATE is passed as nil, return a list of all ERC
 buffers.  If PROC is given, the buffers local variable `erc-server-process'
 needs to match PROC."
-  (unless predicate
-    (setq predicate (lambda () t)))
-  (erc-buffer-filter predicate proc))
+  (erc-buffer-filter (or predicate #'always) proc))
 
 (define-obsolete-function-alias 'erc-iswitchb #'erc-switch-to-buffer "25.1")
 (defun erc--switch-to-buffer (&optional arg)
@@ -2207,8 +2196,8 @@ nil."
                     (alist-get 'erc-insert-marker continued-session))
         (set-marker erc-input-marker
                     (alist-get 'erc-input-marker continued-session))
-        (goto-char erc-insert-marker)
-        (cl-assert (= (field-end) erc-input-marker))
+        (set-marker-insertion-type erc-insert-marker t)
+        (cl-assert (= (field-end erc-insert-marker) erc-input-marker))
         (goto-char old-point)
         (erc--unhide-prompt))
     (cl-assert (not (get-text-property (point) 'erc-prompt)))
@@ -2219,6 +2208,7 @@ nil."
     (insert "\n\n")
     (set-marker erc-insert-marker (point))
     (erc-display-prompt)
+    (set-marker-insertion-type erc-insert-marker t)
     (cl-assert (= (point) (point-max)))))
 
 (defun erc-open (&optional server port nick full-name
@@ -2775,9 +2765,12 @@ If ARG is non-nil, show the *erc-protocol* buffer."
 (defun erc-send-action (tgt str &optional force)
   "Send CTCP ACTION information described by STR to TGT."
   (erc-send-ctcp-message tgt (format "ACTION %s" str) force)
-  (erc-display-message
-   nil 'input (current-buffer)
-   'ACTION ?n (erc-current-nick) ?a str ?u "" ?h ""))
+  (let ((erc-insert-pre-hook
+         (cons (lambda (s) ; Leave newline be.
+                 (put-text-property 0 (1- (length s)) 'erc-command 'PRIVMSG s))
+               erc-insert-pre-hook)))
+    (erc-display-message nil 'input (current-buffer)
+                         'ACTION ?n (erc-current-nick) ?a str ?u "" ?h "")))
 
 ;; Display interface
 
@@ -2811,10 +2804,12 @@ this option to nil."
   (when (functionp erc-prompt)
     (save-excursion
       (goto-char erc-insert-marker)
+      (set-marker-insertion-type erc-insert-marker nil)
       ;; Avoid `erc-prompt' (the named function), which appends a
       ;; space, and `erc-display-prompt', which propertizes all but
       ;; that space.
       (insert-and-inherit (funcall erc-prompt))
+      (set-marker-insertion-type erc-insert-marker t)
       (delete-region (point) (1- erc-input-marker)))))
 
 (defun erc-display-line-1 (string buffer)
@@ -2850,7 +2845,7 @@ If STRING is nil, the function does nothing."
               (save-restriction
                 (widen)
                 (goto-char insert-position)
-                (insert-before-markers string)
+                (insert string)
                 (erc--assert-input-bounds)
                 ;; run insertion hook, with point at restored location
                 (save-restriction
@@ -3185,13 +3180,16 @@ present."
   "Non-nil when a user types a \"/slash\" command.
 Remains bound until `erc-cmd-SLASH' returns.")
 
-(defvar-local erc-send-input-line-function 'erc-send-input-line
-  "Function for sending lines lacking a leading user command.
-When a line typed into a buffer contains an explicit command, like /msg,
-a corresponding handler (here, erc-cmd-MSG) is called.  But lines typed
-into a channel or query buffer already have an implicit target and
-command (PRIVMSG).  This function is called on such occasions and also
-for special purposes (see erc-dcc.el).")
+(defvar-local erc-send-input-line-function #'erc-send-input-line
+  "Function for sending lines lacking a leading \"slash\" command.
+When prompt input starts with a \"slash\" command, like \"/MSG\",
+ERC calls a corresponding handler, like `erc-cmd-MSG'.  But
+normal \"chat\" input also needs processing, for example, to
+convert it into a proper IRC command.  ERC calls this variable's
+value to perform that task, which, by default, simply involves
+constructing a \"PRIVMSG\" with the current channel or query
+partner as the target.  Some libraries, like `erc-dcc', use this
+for other purposes.")
 
 (defun erc-send-input-line (target line &optional force)
   "Send LINE to TARGET."
@@ -4976,34 +4974,6 @@ E.g. \"Read error to Nick [user@some.host]: 110\" would 
be shortened to
         (match-string 1 reason))
       reason))
 
-(defun erc-regain-nick-on-connect (want temp)
-  "Try at most once to grab nickname WANT after settling for TEMP.
-Only do so during connection registration, likely prior to
-authenticating with SASL.  Assume the prior connection was lost
-due to connectivity failure and that the server hasn't yet
-noticed.  Also assume that the server won't process any
-authentication-related messages until it has accepted a mulligan
-nick or at least sent a 433 and thus triggered
-`erc-nickname-in-use-functions'.  Expect authentication to have
-succeeded by the time a logical IRC connection has been
-established and that the contending connection may otherwise
-still be alive and require manual intervention involving
-NickServ."
-  (unless erc-server-connected
-    (letrec ((after-connect
-              (lambda (_ nick)
-                (remove-hook 'erc-after-connect after-connect t)
-                (when (equal temp nick)
-                  (erc-cmd-NICK want))))
-             (on-900
-              (lambda (_ parsed)
-                (remove-hook 'erc-server-900-functions on-900 t)
-                (unless erc-server-connected
-                  (when (equal (car (erc-response.command-args parsed)) temp)
-                    (add-hook 'erc-after-connect after-connect nil t)))
-                nil)))
-      (add-hook 'erc-server-900-functions on-900 nil t))))
-
 (defun erc-nickname-in-use (nick reason)
   "If NICK is unavailable, tell the user the REASON.
 
@@ -5037,7 +5007,6 @@ See also `erc-display-error-notice'."
                                    ;; established a connection yet
                                    (- 9 (length erc-nick-uniquifier))))
                                erc-nick-uniquifier)))
-      (run-hook-with-args 'erc-nickname-in-use-functions nick newnick)
       (erc-cmd-NICK newnick)
       (erc-display-error-notice
        nil
@@ -6477,14 +6446,14 @@ Return non-nil only if we actually send anything."
   (when erc-insert-this
     (save-excursion
       (erc--assert-input-bounds)
-      (let ((insert-position (marker-position erc-insert-marker))
+      (let ((insert-position (marker-position (goto-char erc-insert-marker)))
             beg)
-        (goto-char insert-position)
-        (insert-before-markers (erc-format-my-nick))
+        (insert (erc-format-my-nick))
         (setq beg (point))
-        (insert-before-markers line)
+        (insert line)
         (erc-put-text-property beg (point) 'font-lock-face 'erc-input-face)
-        (insert-before-markers "\n")
+        (erc-put-text-property insert-position (point) 'erc-command 'PRIVMSG)
+        (insert "\n")
         (save-restriction
           (narrow-to-region insert-position (point))
           (run-hooks 'erc-send-modify-hook)
@@ -7458,8 +7427,9 @@ With ARG, download and display the latest revision, which 
may
 contain more up-to-date information, even for older versions."
   (interactive "P")
   (find-file
-   (or (and arg erc--news-temp-file
+   (or (and erc--news-temp-file
             (time-less-p (current-time) (car erc--news-temp-file))
+            (not (and arg (y-or-n-p (format "Re-fetch? "))))
             (cdr erc--news-temp-file))
        (and arg
             (with-current-buffer (url-retrieve-synchronously erc--news-url)
@@ -7467,7 +7437,10 @@ contain more up-to-date information, even for older 
versions."
               (search-forward "200 OK" (pos-eol))
               (search-forward "\n\n")
               (delete-region (point-min) (point))
-              (let ((tempfile (make-temp-file "erc-news.")))
+              ;; May warn about file having changed on disk (unless
+              ;; `query-about-changed-file' is nil on 28+).
+              (let ((tempfile (or (cdr erc--news-temp-file)
+                                  (make-temp-file "erc-news."))))
                 (write-region (point-min) (point-max) tempfile)
                 (kill-buffer)
                 (cdr (setq erc--news-temp-file
@@ -7482,13 +7455,12 @@ contain more up-to-date information, even for older 
versions."
        (expand-file-name "ERC-NEWS" data-directory)))
   (when (fboundp 'emacs-news-view-mode)
     (emacs-news-view-mode))
+  (goto-char (point-min))
   (let ((v (mapcar #'number-to-string
                    (seq-take-while #'natnump (version-to-list erc-version)))))
-    (while (and v
-                (goto-char (point-min))
-                (not (search-forward (concat "\014\n* Changes in ERC "
-                                             (string-join v "."))
-                                     nil t)))
+    (while (and v (not (search-forward (concat "\014\n* Changes in ERC "
+                                               (string-join v "."))
+                                       nil t)))
       (setq v (butlast v))))
   (beginning-of-line))
 
diff --git a/lisp/transient.el b/lisp/transient.el
index 048554eee13..78496843284 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -2190,39 +2190,35 @@ value.  Otherwise return CHILDREN as is."
 
 (defun transient--wrap-command ()
   (let* ((prefix transient--prefix)
-         (suffix this-command)
-         (advice nil)
-         (advice-interactive
-          (lambda (spec)
-            (let ((abort t))
-              (unwind-protect
-                 (prog1 (advice-eval-interactive-spec spec)
-                   (setq abort nil))
-               (when abort
+         (suffix this-command))
+    (letrec ((advice
+              (lambda (fn &rest args)
+                (interactive
+                 (lambda (spec)
+                   (let ((abort t))
+                     (unwind-protect
+                        (prog1 (advice-eval-interactive-spec spec)
+                          (setq abort nil))
+                      (when abort
+                        (when-let ((unwind (oref prefix unwind-suffix)))
+                          (transient--debug 'unwind-interactive)
+                          (funcall unwind suffix))
+                        (if (symbolp suffix)
+                            (advice-remove suffix advice)
+                          (remove-function suffix advice))
+                        (oset prefix unwind-suffix nil))))))
+                (unwind-protect
+                    (apply fn args)
                   (when-let ((unwind (oref prefix unwind-suffix)))
-                    (transient--debug 'unwind-interactive)
+                    (transient--debug 'unwind-command)
                     (funcall unwind suffix))
                   (if (symbolp suffix)
                       (advice-remove suffix advice)
                     (remove-function suffix advice))
-                  (oset prefix unwind-suffix nil))))))
-         (advice-body
-          (lambda (fn &rest args)
-            (unwind-protect
-                (apply fn args)
-              (when-let ((unwind (oref prefix unwind-suffix)))
-                (transient--debug 'unwind-command)
-                (funcall unwind suffix))
-              (if (symbolp suffix)
-                  (advice-remove suffix advice)
-                (remove-function suffix advice))
-              (oset prefix unwind-suffix nil)))))
-    (setq advice `(lambda (fn &rest args)
-                    (interactive ,advice-interactive)
-                    (apply ',advice-body fn args)))
-    (if (symbolp suffix)
-        (advice-add suffix :around advice '((depth . -99)))
-      (add-function :around (var suffix) advice '((depth . -99))))))
+                  (oset prefix unwind-suffix nil)))))
+      (if (symbolp suffix)
+          (advice-add suffix :around advice '((depth . -99)))
+        (add-function :around (var suffix) advice '((depth . -99)))))))
 
 (defun transient--premature-post-command ()
   (and (equal (this-command-keys-vector) [])
diff --git a/test/lisp/erc/erc-dcc-tests.el b/test/lisp/erc/erc-dcc-tests.el
index 7fb5f82e784..f02ddf228a2 100644
--- a/test/lisp/erc/erc-dcc-tests.el
+++ b/test/lisp/erc/erc-dcc-tests.el
@@ -57,11 +57,8 @@
       (erc-mode)
       (setq erc-server-process
             (start-process "fake" (current-buffer) "sleep" "10")
-            erc-input-marker (make-marker)
-            erc-insert-marker (make-marker)
             erc-server-current-nick "dummy")
-      (erc-display-prompt)
-      (set-marker erc-insert-marker (pos-bol))
+      (erc--initialize-markers (point) nil)
       (set-process-query-on-exit-flag erc-server-process nil)
       (should-not erc-dcc-list)
       (erc-ctcp-query-DCC erc-server-process
@@ -121,17 +118,14 @@
            calls)
       (erc-mode)
       (setq erc-server-process proc
-            erc-input-marker (make-marker)
-            erc-insert-marker (make-marker)
             erc-server-current-nick "dummy")
+      (erc--initialize-markers (point) nil)
       (set-process-query-on-exit-flag proc nil)
       (cl-letf (((symbol-function 'read-file-name)
                  (lambda (&rest _) file))
                 ((symbol-function 'erc-dcc-get-file)
                  (lambda (&rest r) (push r calls))))
         (goto-char (point-max))
-        (set-marker erc-insert-marker (point-max))
-        (erc-display-prompt)
 
         (ert-info ("No turbo")
           (should-not (plist-member elt :turbo))
diff --git a/test/lisp/erc/erc-fill-tests.el b/test/lisp/erc/erc-fill-tests.el
index fc33d0b9103..15a8087f848 100644
--- a/test/lisp/erc/erc-fill-tests.el
+++ b/test/lisp/erc/erc-fill-tests.el
@@ -109,10 +109,12 @@
     (dolist (prefix prefixes)
       (should (search-forward prefix nil t))
       (should (get-text-property (pos-bol) 'line-prefix))
-      (should (get-text-property (pos-eol) 'line-prefix))
+      (should (get-text-property (1- (pos-eol)) 'line-prefix))
+      (should-not (get-text-property (pos-eol) 'line-prefix))
       (should (equal (get-text-property (pos-bol) 'wrap-prefix)
                      '(space :width erc-fill--wrap-value)))
-      (should (equal (get-text-property (pos-eol) 'wrap-prefix)
+      (should-not (get-text-property (pos-eol) 'wrap-prefix))
+      (should (equal (get-text-property (1- (pos-eol)) 'wrap-prefix)
                      '(space :width erc-fill--wrap-value))))))
 
 ;; Set this variable to t to generate new snapshots after carefully
diff --git a/test/lisp/erc/erc-networks-tests.el 
b/test/lisp/erc/erc-networks-tests.el
index b9d216f217b..f0fcbbc81c6 100644
--- a/test/lisp/erc/erc-networks-tests.el
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -1233,10 +1233,7 @@
                    :contents "MOTD File is missing")))
 
       (erc-mode) ; boilerplate displayable start (needs `erc-server-process')
-      (insert "\n\n")
-      (setq erc-input-marker (make-marker) erc-insert-marker (make-marker))
-      (set-marker erc-insert-marker (point-max))
-      (erc-display-prompt) ; boilerplate displayable end
+      (erc--initialize-markers (point) nil)
 
       (erc-networks--ensure-announced erc-server-process parsed)
       (goto-char (point-min))
@@ -1277,9 +1274,9 @@
     (with-current-buffer old-buf
       (erc-mode)
       (insert "*** Old buf")
+      (erc--initialize-markers (point) nil)
       (setq erc-network 'FooNet
             erc-server-current-nick "tester"
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc
             erc-networks--id (erc-networks--id-create nil)))
 
@@ -1328,10 +1325,10 @@
            erc-reuse-buffers)
       (with-current-buffer old-buf
         (erc-mode)
+        (erc--initialize-markers (point) nil)
         (insert "*** Old buf")
         (setq erc-network 'FooNet
               erc-server-current-nick "tester"
-              erc-insert-marker (set-marker (make-marker) (point-max))
               erc-server-process old-proc
               erc-networks--id (erc-networks--id-create nil)))
       (with-current-buffer (get-buffer-create "#chan")
@@ -1377,10 +1374,10 @@
 
     (with-current-buffer old-buf
       (erc-mode)
+      (erc--initialize-markers (point) nil)
       (insert "*** Old buf")
       (setq erc-network 'FooNet
             erc-server-current-nick "tester"
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc
             erc-networks--id (erc-networks--id-create nil)))
 
@@ -1415,10 +1412,10 @@
 
     (with-current-buffer old-buf
       (erc-mode)
+      (erc--initialize-markers (point) nil)
       (insert "*** Old buf")
       (setq erc-network 'FooNet
             erc-networks--id (erc-networks--id-create 'MySession)
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc))
 
     (with-current-buffer (get-buffer-create "#chan")
@@ -1454,10 +1451,10 @@
 
     (with-current-buffer old-buf
       (erc-mode)
+      (erc--initialize-markers (point) nil)
       (insert "*** Old buf")
       (setq erc-network 'FooNet
             erc-server-current-nick "tester"
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc
             erc-networks--id (erc-networks--id-create nil))
       (should (erc-server-process-alive)))
@@ -1473,15 +1470,12 @@
     (ert-info ("New buffer rejected, abandoned, not killed")
       (with-current-buffer (get-buffer-create "irc.foonet.org")
         (erc-mode)
+        (erc--initialize-markers (point) nil)
         (setq erc-network 'FooNet
               erc-server-current-nick "tester"
-              erc-insert-marker (make-marker)
-              erc-input-marker (make-marker)
               erc-server-process (erc-networks-tests--create-live-proc)
               erc-networks--id (erc-networks--id-create nil))
         (set-process-sentinel erc-server-process #'ignore)
-        (erc-display-prompt nil (point-max))
-        (set-marker erc-insert-marker (pos-bol))
         (erc-display-message nil 'notice (current-buffer) "notice")
         (with-silent-modifications
           (should-not (erc-networks--rename-server-buffer erc-server-process)))
@@ -1514,10 +1508,10 @@
     (with-current-buffer old-buf
       (erc-mode)
       (insert "*** Old buf")
+      (erc--initialize-markers (point) nil)
       (setq erc-network 'FooNet
             erc-server-current-nick "tester"
             erc-server-announced-name "us-east.foonet.org"
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc
             erc--isupport-params (make-hash-table)
             erc-networks--id (erc-networks--id-create nil))
@@ -1566,10 +1560,10 @@
     (with-current-buffer old-buf
       (erc-mode)
       (insert "*** Old buf")
+      (erc--initialize-markers (point) nil)
       (setq erc-network 'FooNet
             erc-server-current-nick "tester"
             erc-server-announced-name "us-west.foonet.org"
-            erc-insert-marker (set-marker (make-marker) (point-max))
             erc-server-process old-proc
             erc--isupport-params (make-hash-table)
             erc-networks--id (erc-networks--id-create nil))
diff --git a/test/lisp/erc/erc-scenarios-base-renick.el 
b/test/lisp/erc/erc-scenarios-base-renick.el
index f8350676fb7..f1723200533 100644
--- a/test/lisp/erc/erc-scenarios-base-renick.el
+++ b/test/lisp/erc/erc-scenarios-base-renick.el
@@ -303,47 +303,4 @@
       (should-not (search-forward "now known as frenemy" nil t))
       (erc-d-t-search-for 25 "I have lost"))))
 
-;; The server rejects your nick during registration, so ERC acquires a
-;; placeholder and successfully renicks once the connection is up.
-;; See also `erc-scenarios-base-renick-self-auto'.
-
-(ert-deftest erc-scenarios-base-renick-auto-regain ()
-  :tags '(:expensive-test)
-  (erc-scenarios-common-with-cleanup
-      ((erc-server-flood-penalty 0.1)
-       (erc-scenarios-common-dialog "base/renick/regain")
-       (dumb-server (erc-d-run "localhost" t 'normal 'normal-again))
-       (port (process-contact dumb-server :service))
-       (erc-server-auto-reconnect t)
-       (erc-modules (cons 'sasl erc-modules))
-       (erc-nickname-in-use-functions '(erc-regain-nick-on-connect))
-       (expect (erc-d-t-make-expecter)))
-
-    (ert-info ("Session succeeds but cut short")
-      (with-current-buffer (erc :server "127.0.0.1"
-                                :port port
-                                :nick "tester"
-                                :user "tester"
-                                :password "changeme"
-                                :full-name "tester")
-        (funcall expect 10 "Last login from")
-        (erc-cmd-JOIN "#test")))
-
-    (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#test"))
-      (funcall expect 10 "was created on"))
-
-    (ert-info ("Service restored")
-      (with-current-buffer "Libera.Chat"
-        (erc-d-t-wait-for 10 erc--server-reconnect-timer)
-        (funcall expect 10 "Connection failed!")
-        (funcall expect 10 "already in use")
-        (funcall expect 10 "changed mode for tester`")
-        (funcall expect 10 "Last login from")
-        (funcall expect 10 "Your new nickname is tester")))
-
-    (with-current-buffer (get-buffer "#test")
-      (funcall expect 10 "tester ")
-      (funcall expect 10 "was created on"))))
-
-
 ;;; erc-scenarios-base-renick.el ends here
diff --git a/test/lisp/erc/erc-stamp-tests.el b/test/lisp/erc/erc-stamp-tests.el
index 01e71e348e0..6da7ed4503d 100644
--- a/test/lisp/erc/erc-stamp-tests.el
+++ b/test/lisp/erc/erc-stamp-tests.el
@@ -43,13 +43,10 @@
     (with-current-buffer (get-buffer-create "*erc-stamp-tests--insert-right*")
       (erc-mode)
       (erc-munge-invisibility-spec)
+      (erc--initialize-markers (point) nil)
       (setq erc-server-process (start-process "p" (current-buffer)
-                                              "sleep" "1")
-            erc-input-marker (make-marker)
-            erc-insert-marker (make-marker))
+                                              "sleep" "1"))
       (set-process-query-on-exit-flag erc-server-process nil)
-      (set-marker erc-insert-marker (point-max))
-      (erc-display-prompt)
 
       (funcall test)
 
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 1c75f35e1b5..f3489a16386 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -294,16 +294,19 @@
         (set-process-query-on-exit-flag erc-server-process nil)
         ;; Incoming message redraws prompt
         (erc-display-message nil 'notice nil "Welcome")
+        (should (looking-at-p (rx "*** Welcome")))
+        (forward-line)
         (should (looking-at-p "ServNet 4>"))
         ;; Say something
-        (save-excursion (goto-char erc-input-marker)
-                        (insert "Howdy")
-                        (erc-send-current-line)
-                        (forward-line -1)
+        (goto-char erc-input-marker)
+        (insert "Howdy")
+        (erc-send-current-line)
+        (save-excursion (forward-line -1)
                         (should (looking-at "No target"))
                         (forward-line -1)
                         (should (looking-at "<tester> Howdy")))
-        (should (looking-at-p "ServNet 6>"))
+        (should (looking-back "ServNet 6> "))
+        (should (= erc-input-marker (point)))
         ;; Space after prompt is unpropertized
         (should (get-text-property (1- erc-input-marker) 'erc-prompt))
         (should-not (get-text-property erc-input-marker 'erc-prompt))
@@ -317,6 +320,7 @@
         (erc-tests--send-prep)
         (goto-char erc-insert-marker)
         (should (looking-at-p "#chan 9>"))
+        (goto-char erc-input-marker)
         (setq erc-server-process (buffer-local-value 'erc-server-process
                                                      (get-buffer "ServNet"))
               erc-networks--id (erc-with-server-buffer erc-networks--id)
@@ -328,18 +332,18 @@
         (erc-update-current-channel-member "tester" "tester")
         (erc-display-message nil nil (current-buffer)
                              (erc-format-privmessage "alice" "Hi" nil t))
-        (should (looking-at-p "#chan@ServNet 10>"))
-        (save-excursion (goto-char erc-input-marker)
-                        (insert "Howdy")
-                        (erc-send-current-line)
-                        (forward-line -1)
+        (should (looking-back "#chan@ServNet 10> "))
+        (goto-char erc-input-marker)
+        (insert "Howdy")
+        (erc-send-current-line)
+        (save-excursion (forward-line -1)
                         (should (looking-at "<tester> Howdy")))
-        (should (looking-at-p "#chan@ServNet 11>"))
-        (save-excursion (goto-char erc-input-marker)
-                        (insert "/query bob")
-                        (erc-send-current-line))
+        (should (looking-back "#chan@ServNet 11> "))
+        (should (= (point) erc-input-marker))
+        (insert "/query bob")
+        (erc-send-current-line)
         ;; Query does not redraw (nor /help, only message input)
-        (should (looking-at-p "#chan@ServNet 11>"))
+        (should (looking-back "#chan@ServNet 11> "))
         ;; No sign of old prompts
         (save-excursion
           (goto-char (point-min))
@@ -349,15 +353,16 @@
       (with-current-buffer (get-buffer "bob")
         (goto-char erc-insert-marker)
         (should (looking-at-p "bob@ServNet 14>"))
+        (goto-char erc-input-marker)
         (erc-display-message nil nil (current-buffer)
                              (erc-format-privmessage "bob" "Hi" nil t))
-        (should (looking-at-p "bob@ServNet 15>"))
-        (save-excursion (goto-char erc-input-marker)
-                        (insert "Howdy")
-                        (erc-send-current-line)
-                        (forward-line -1)
+        (should (looking-back "bob@ServNet 15> "))
+        (goto-char erc-input-marker)
+        (insert "Howdy")
+        (erc-send-current-line)
+        (save-excursion (forward-line -1)
                         (should (looking-at "<tester> Howdy")))
-        (should (looking-at-p "bob@ServNet 16>"))
+        (should (looking-back "bob@ServNet 16> "))
         ;; No sign of old prompts
         (save-excursion
           (goto-char (point-min))
@@ -2085,48 +2090,77 @@
   (should (eq (erc--normalize-module-symbol 'timestamp) 'stamp))
   (should (eq (erc--normalize-module-symbol 'nickserv) 'services)))
 
-;; Worrying about which library a module comes from is mostly not
-;; worth the hassle so long as ERC can find its minor mode.  However,
-;; bugs involving multiple modules living in the same library may slip
-;; by because a module's loading problems may remain hidden on account
-;; of its place in the default ordering.
-
-(ert-deftest erc--find-mode ()
+(defun erc-tests--assert-printed-in-subprocess (code expected)
   (let* ((package (if-let* ((found (getenv "ERC_PACKAGE_NAME"))
                             ((string-prefix-p "erc-" found)))
                       (intern found)
                     'erc))
+         ;; This is for integrations testing with managed configs
+         ;; ("starter kits") that use a different package manager.
+         (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
+                          (files (split-string found ","))
+                          ((seq-every-p #'file-exists-p files)))
+                 (mapcan (lambda (f) (list "-l" f)) files)))
          (prog
-          `(,@(and (featurep 'compat)
-                   `((progn
-                       (require 'package)
-                       (let ((package-load-list '((compat t) (,package t))))
-                         (package-initialize)))))
-            (require 'erc)
-            (let ((mods (mapcar #'cadddr
-                                (cdddr (get 'erc-modules 'custom-type))))
-                  moded)
-              (setq mods
-                    (sort mods (lambda (a b) (if (zerop (random 2)) a b))))
-              (dolist (mod mods)
-                (unless (keywordp mod)
-                  (push (if-let ((mode (erc--find-mode mod)))
-                            mod
-                          (list :missing mod))
-                        moded)))
-              (message "%S"
-                       (sort moded
-                             (lambda (a b)
-                               (string< (symbol-name a) (symbol-name b))))))))
-         (proc (start-process "erc--module-mode-autoloads"
-                              (current-buffer)
-                              (concat invocation-directory invocation-name)
-                              "-batch" "-Q"
-                              "-eval" (format "%S" (cons 'progn prog)))))
+          `(progn
+             ,@(and (not init) (featurep 'compat)
+                    `((require 'package)
+                      (let ((package-load-list '((compat t) (,package t))))
+                        (package-initialize))))
+             (require 'erc)
+             (cl-assert (equal erc-version ,erc-version) t)
+             ,code))
+         (proc (apply #'start-process
+                      (symbol-name (ert-test-name (ert-running-test)))
+                      (current-buffer)
+                      (concat invocation-directory invocation-name)
+                      `("-batch" ,@(or init '("-Q"))
+                        "-eval" ,(format "%S" prog)))))
     (set-process-query-on-exit-flag proc t)
     (while (accept-process-output proc 10))
     (goto-char (point-min))
-    (should (equal (read (current-buffer)) erc-tests--modules))))
+    (unless (equal (read (current-buffer)) expected)
+      (message "Exepcted: %S\nGot: %s" expected (buffer-string))
+      (ert-fail "Mismatch"))))
+
+;; Worrying about which library a module comes from is mostly not
+;; worth the hassle so long as ERC can find its minor mode.  However,
+;; bugs involving multiple modules living in the same library may slip
+;; by because a module's loading problems may remain hidden on account
+;; of its place in the default ordering.
+
+(ert-deftest erc--find-mode ()
+  (erc-tests--assert-printed-in-subprocess
+   `(let ((mods (mapcar #'cadddr (cdddr (get 'erc-modules 'custom-type))))
+          moded)
+      (setq mods (sort mods (lambda (a b) (if (zerop (random 2)) a b))))
+      (dolist (mod mods)
+        (unless (keywordp mod)
+          (push (if-let ((mode (erc--find-mode mod))) mod (list :missing mod))
+                moded)))
+      (message "%S"
+               (sort moded (lambda (a b)
+                             (string< (symbol-name a) (symbol-name b))))))
+   erc-tests--modules))
+
+(ert-deftest erc--essential-hook-ordering ()
+  (erc-tests--assert-printed-in-subprocess
+   '(progn
+      (erc-update-modules)
+      (message "%S"
+               (list :erc-insert-modify-hook erc-insert-modify-hook
+                     :erc-send-modify-hook erc-send-modify-hook)))
+
+   '( :erc-insert-modify-hook (erc-controls-highlight ; 0
+                               erc-button-add-buttons ; 30
+                               erc-fill ; 40
+                               erc-add-timestamp ; 50
+                               erc-match-message) ; 60
+
+      :erc-send-modify-hook ( erc-controls-highlight ; 0
+                              erc-button-add-buttons ; 30
+                              erc-fill ; 40
+                              erc-add-timestamp)))) ; 50
 
 (ert-deftest erc-migrate-modules ()
   (should (equal (erc-migrate-modules '(autojoin timestamp button))
diff --git a/test/lisp/erc/resources/base/renick/regain/normal-again.eld 
b/test/lisp/erc/resources/base/renick/regain/normal-again.eld
deleted file mode 100644
index c0529052c70..00000000000
--- a/test/lisp/erc/resources/base/renick/regain/normal-again.eld
+++ /dev/null
@@ -1,56 +0,0 @@
-;; -*- mode: lisp-data; -*-
-((cap 10 "CAP REQ :sasl"))
-((nick 10 "NICK tester"))
-((user 10 "USER tester 0 * :tester"))
-
-((authenticate 10 "AUTHENTICATE PLAIN")
- (0.04 ":tantalum.libera.chat NOTICE * :*** Checking Ident")
- (0.01 ":tantalum.libera.chat NOTICE * :*** Looking up your hostname...")
- (0.01 ":tantalum.libera.chat NOTICE * :*** Couldn't look up your hostname")
- (0.06 ":tantalum.libera.chat NOTICE * :*** No Ident response")
- (0.02 ":tantalum.libera.chat CAP * ACK :sasl")
- (0.03 ":tantalum.libera.chat 433 * tester :Nickname is already in use."))
-
-((nick 10 "NICK tester`")
- (0.03 "AUTHENTICATE +"))
-
-((authenticate 10 "AUTHENTICATE AHRlc3RlcgBjaGFuZ2VtZQ==")
- (0.06 ":tantalum.libera.chat 900 tester` tester`!tester@127.0.0.1 tester :You 
are now logged in as tester")
- (0.02 ":tantalum.libera.chat 903 tester` :SASL authentication successful"))
-
-((cap 10 "CAP END")
- (0.02 ":tantalum.libera.chat 001 tester` :Welcome to the Libera.Chat Internet 
Relay Chat Network tester`")
- (0.02 ":tantalum.libera.chat 002 tester` :Your host is 
tantalum.libera.chat[93.158.237.2/6697], running version solanum-1.0-dev")
- (0.02 ":tantalum.libera.chat 003 tester` :This server was created Mon Feb 13 
2023 at 12:05:04 UTC")
- (0.01 ":tantalum.libera.chat 004 tester` tantalum.libera.chat solanum-1.0-dev 
DGMQRSZaghilopsuwz CFILMPQRSTbcefgijklmnopqrstuvz bkloveqjfI")
- (0.01 ":tantalum.libera.chat 005 tester` WHOX MONITOR=100 SAFELIST 
ELIST=CMNTU ETRACE FNC CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX 
CHANMODES=eIbq,k,flj,CFLMPQRSTcgimnprstuz :are supported by this server")
- (0.01 ":tantalum.libera.chat 005 tester` CHANLIMIT=#:250 PREFIX=(ov)@+ 
MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 
NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by 
this server")
- (0.03 ":tantalum.libera.chat 005 tester` 
TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: 
EXTBAN=$,ajrxz :are supported by this server")
- (0.01 ":tantalum.libera.chat 251 tester` :There are 70 users and 42977 
invisible on 28 servers")
- (0.00 ":tantalum.libera.chat 252 tester` 38 :IRC Operators online")
- (0.00 ":tantalum.libera.chat 253 tester` 87 :unknown connection(s)")
- (0.00 ":tantalum.libera.chat 254 tester` 22908 :channels formed")
- (0.00 ":tantalum.libera.chat 255 tester` :I have 2507 clients and 1 servers")
- (0.00 ":tantalum.libera.chat 265 tester` 2507 3232 :Current local users 2507, 
max 3232")
- (0.00 ":tantalum.libera.chat 266 tester` 43047 51777 :Current global users 
43047, max 51777")
- (0.00 ":tantalum.libera.chat 250 tester` :Highest connection count: 3233 
(3232 clients) (284887 connections received)")
- (0.03 ":tantalum.libera.chat 375 tester` :- tantalum.libera.chat Message of 
the Day - ")
- (0.00 ":tantalum.libera.chat 372 tester` :- This server provided by 
Hyperfilter (https://hyperfilter.com)")
- (0.00 ":tantalum.libera.chat 372 tester` :- Email:                      
support@libera.chat")
- (0.02 ":tantalum.libera.chat 376 tester` :End of /MOTD command."))
-
-((mode 10 "MODE tester` +i")
- (0.01 ":tester` MODE tester` :+Ziw")
- (0.02 ":SaslServ!SaslServ@services.libera.chat NOTICE tester` :Last login 
from: \2~tester@127.0.0.1\2 on Apr 07 01:36:25 2023 +0000."))
-
-((nick 10 "NICK tester")
- (0.02 ":tester`!~tester@127.0.0.1 NICK :tester"))
-
-((join 10 "JOIN #test")
- (0.02 ":tester!~tester@127.0.0.1 JOIN #test")
- (0.02 ":tantalum.libera.chat 353 tester = #test :tester zbyqbepbqre7 
pusevgfpu Thrfg2187 zngbeb qnexNssvavgl wrebzr- rqpentt Ilehf grfg2 AvtugZbaxrl 
pevfgvvbna xrivap_ fnvybePng shohxv gxan arrqyr avpx16 NeanhqW_kzcc jvyyr 
wrnaogeq Wnarg cnefavc0 Xbentt RcvpArb flfqrs wfgbxre hafcrag__ Lbevpx_")
- (0.02 ":tantalum.libera.chat 366 tester #test :End of /NAMES list."))
-
-((mode 10 "MODE #test")
- (0.02 ":tantalum.libera.chat 324 tester #test +nt")
- (0.02 ":tantalum.libera.chat 329 tester #test 1621432263"))
diff --git a/test/lisp/erc/resources/base/renick/regain/normal.eld 
b/test/lisp/erc/resources/base/renick/regain/normal.eld
deleted file mode 100644
index 9f4df70e580..00000000000
--- a/test/lisp/erc/resources/base/renick/regain/normal.eld
+++ /dev/null
@@ -1,53 +0,0 @@
-;; -*- mode: lisp-data; -*-
-((cap 10 "CAP REQ :sasl"))
-((nick 10 "NICK tester"))
-((user 10 "USER tester 0 * :tester"))
-
-((authenticate 10 "AUTHENTICATE PLAIN")
- (0.02 ":cadmium.libera.chat NOTICE * :*** Checking Ident")
- (0.01 ":cadmium.libera.chat NOTICE * :*** Looking up your hostname...")
- (0.01 ":cadmium.libera.chat NOTICE * :*** Couldn't look up your hostname")
- (0.06 ":cadmium.libera.chat NOTICE * :*** No Ident response")
- (0.09 ":cadmium.libera.chat CAP * ACK :sasl")
- (0.01 "AUTHENTICATE +"))
-
-((authenticate 10 "AUTHENTICATE AHRlc3RlcgBjaGFuZ2VtZQ==")
- (0.03 ":cadmium.libera.chat 900 tester tester!tester@127.0.0.1 tester :You 
are now logged in as tester")
- (0.01 ":cadmium.libera.chat 903 tester :SASL authentication successful"))
-
-((cap 10 "CAP END")
- (0.03 ":cadmium.libera.chat 001 tester :Welcome to the Libera.Chat Internet 
Relay Chat Network tester")
- (0.02 ":cadmium.libera.chat 002 tester :Your host is 
cadmium.libera.chat[103.196.37.95/6697], running version solanum-1.0-dev")
- (0.01 ":cadmium.libera.chat 003 tester :This server was created Wed Jan 25 
2023 at 10:22:45 UTC")
- (0.01 ":cadmium.libera.chat 004 tester cadmium.libera.chat solanum-1.0-dev 
DGMQRSZaghilopsuwz CFILMPQRSTbcefgijklmnopqrstuvz bkloveqjfI")
- (0.00 ":cadmium.libera.chat 005 tester CALLERID=g WHOX ETRACE FNC SAFELIST 
ELIST=CMNTU KNOCK MONITOR=100 CHANTYPES=# EXCEPTS INVEX 
CHANMODES=eIbq,k,flj,CFLMPQRSTcgimnprstuz :are supported by this server")
- (0.01 ":cadmium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ 
MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 
NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by 
this server")
- (0.01 ":cadmium.libera.chat 005 tester 
TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: 
EXTBAN=$,ajrxz :are supported by this server")
- (0.01 ":cadmium.libera.chat 251 tester :There are 70 users and 42996 
invisible on 28 servers")
- (0.02 ":cadmium.libera.chat 252 tester 38 :IRC Operators online")
- (0.01 ":cadmium.libera.chat 253 tester 57 :unknown connection(s)")
- (0.01 ":cadmium.libera.chat 254 tester 22912 :channels formed")
- (0.01 ":cadmium.libera.chat 255 tester :I have 2499 clients and 1 servers")
- (0.01 ":cadmium.libera.chat 265 tester 2499 4187 :Current local users 2499, 
max 4187")
- (0.01 ":cadmium.libera.chat 266 tester 43066 51827 :Current global users 
43066, max 51827")
- (0.01 ":cadmium.libera.chat 250 tester :Highest connection count: 4188 (4187 
clients) (319420 connections received)")
- (0.01 ":cadmium.libera.chat 375 tester :- cadmium.libera.chat Message of the 
Day - ")
- (0.01 ":cadmium.libera.chat 372 tester :- This server kindly provided by Mach 
Dilemma (www.m-d.net)")
- (0.01 ":cadmium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC 
network for")
- (0.00 ":cadmium.libera.chat 372 tester :- Email:                      
support@libera.chat")
- (0.00 ":cadmium.libera.chat 376 tester :End of /MOTD command.")
- (0.00 ":tester MODE tester :+Ziw")
- (0.02 ":SaslServ!SaslServ@services.libera.chat NOTICE tester :Last login 
from: \2~tester@127.0.0.1\2 on Apr 07 01:02:11 2023 +0000."))
-
-((mode 10 "MODE tester +i"))
-
-((join 10 "JOIN #test")
- (0.09 ":tester!~tester@127.0.0.1 JOIN #test"))
-
-((mode 10 "MODE #test")
- (0.03 ":cadmium.libera.chat 353 tester = #test :tester zbyqbepbqre7 pusevgfpu 
Thrfg2187 zngbeb qnexNssvavgl wrebzr- rqpentt Ilehf grfg2 AvtugZbaxrl 
pevfgvvbna xrivap_ fnvybePng shohxv gxan arrqyr avpx16 NeanhqW_kzcc Lbevpx_ 
hafcrag__ wfgbxre flfqrs RcvpArb Xbentt jvyyr cnefavc0 Wnarg wrnaogeq")
- (0.02 ":cadmium.libera.chat 366 tester #test :End of /NAMES list.")
- (0.00 ":cadmium.libera.chat 324 tester #test +nt")
- (0.01 ":cadmium.libera.chat 329 tester #test 1621432263"))
-
-((drop 0 DROP))
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
index 88defb6c09e..689bacc7012 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
index c5a9cbfc05d..9fa23a7d332 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
index 67ebad542fb..80c9e1d80f5 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 21 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
index 0bf8001475d..e675695f660 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 21 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
index 7d231d19cef..a6070c2e3ff 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 21 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
index 67ebad542fb..80c9e1d80f5 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 21 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 
(erc-timestamp 0 line-prefix (space :wi [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld 
b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
index 45c3883b023..2b8766c27f4 100644
--- a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
+++ b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This 
buffer is for text.\n*** one two th [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This 
buffer is for text.\n*** one two th [...]
\ No newline at end of file



reply via email to

[Prev in Thread] Current Thread [Next in Thread]