GNU logs - #63595, boring messages


Message sent to emacs-erc@HIDDEN, bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: emacs-erc@HIDDEN, bug-gnu-emacs@HIDDEN
Resent-Date: Fri, 19 May 2023 19:26:01 +0000
Resent-Message-ID: <handler.63595.B.168452435416678 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: report 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
X-Debbugs-Original-To: bug-gnu-emacs@HIDDEN
X-Debbugs-Original-Xcc: emacs-erc@HIDDEN
Received: via spool by submit <at> debbugs.gnu.org id=B.168452435416678
          (code B ref -1); Fri, 19 May 2023 19:26:01 +0000
Received: (at submit) by debbugs.gnu.org; 19 May 2023 19:25:54 +0000
Received: from localhost ([127.0.0.1]:57435 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1q05ja-0004Kr-HF
	for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:53 -0400
Received: from lists.gnu.org ([209.51.188.17]:54098)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1q05jV-0004Ke-Se
 for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:49 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jV-0003yx-Ey
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-108-mta11.mxroute.com ([136.175.108.11])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jO-0005YW-Nz
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta11.mxroute.com (ZoneMTA) with ESMTPSA id 1883579758200074ee.001
 for <bug-gnu-emacs@HIDDEN>
 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);
 Fri, 19 May 2023 19:25:32 +0000
X-Zone-Loop: eec7dda6ba983e849cec5c7021dd9f3b963fa6e4e9fe
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=reOVYRocD84tqZU6Afp4MUToMaIkxYinxEkfAKJ6TEQ=; b=JWB0abbAfp98Slzy+ZQWJUY2pv
 tEBXPa65Rq/NP6nB1fU6/+hHUBsUtheeb5MoQVHR40jzE+eJhe4Dmv0UOfn+m62bNxe1VW1uuUlmT
 XAB1AwzSXVoCNW+V9WXYxY8kGncTwAzfmF5YHkTf+Q4YjJjlLPWtT5xmDbfKULqII4R19v6/uNGB1
 JA8JrJqdIuN/fGcYwR7e8K1XSdoFHWTtNhDWfEE+J47GN2USEtY43xp1QpI3Qkkt8gGB1dDlh6vYo
 FrMkk24HC5++Og2JpEzxk0pyTzZoghmB+FBth71ZF8qjTluwptnYhxjEHyknC0vteueMkPqXTVRaj
 NVDIEzCw==;
From: "J.P." <jp@HIDDEN>
Date: Fri, 19 May 2023 12:25:29 -0700
Message-ID: <87lehkt97a.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
Received-SPF: pass client-ip=136.175.108.11; envelope-from=jp@HIDDEN;
 helo=mail-108-mta11.mxroute.com
X-Spam_score_int: -20
X-Spam_score: -2.1
X-Spam_bar: --
X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001,
 SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: -1.4 (-)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -2.4 (--)

--=-=-=
Content-Type: text/plain

Tags: patch
Severity: wishlist

(This bug could just as well be titled "Make ERC look more like
standalone clients," although that's perhaps a bit clickbaity.)


Hi,

Newcomers to ERC are occasionally dumbfounded by the absence of a
certain pair of IRC essentials, namely, a "window list" and a "nicknames
list." But what even existing users may not know is that ERC already has
both; they just don't quite work the way folks coming from other clients
might expect. This patch aims to address that as if it were a problem.

What's being proposed here is the addition of two new modules built
entirely on functionality already offered by their host libraries,
erc-status-sidebar.el and erc-speedbar.el. What's different is these
additions flirt with something somewhat verboten in ERC, and that's
changing existing defaults for non-security reasons (in this case,
chiefly for unifying UX [1]). Beyond that, these changes also hard-wire
potentially offensive choices into some of these defaults while trying
in earnest to ensure old behavior remains accessible. For example, one
module assumes no one with a non-nil `erc-header-line-format' has any
use for modes and topics in a side window. Other baked in preferences
include the nixing of all throwback icons [2] and the showing of
disconnected buffers in a muted face. The list goes on but is open for
discussion, as always.

Another consideration here is of course naming [3]. I've gone ahead and
dubbed the speedbar module 'nickbar' as a bit of an homage to its roots.
`nicklist' wasn't available because a popular module of that name was
once part of ERC, and people still use it today. For status-sidebar, I
went with `bufbar', in part for consistency but also because the
would-be canonical "status-sidebar" is already taken by the side
window's buffer for its major mode. We might also consider going with
the slightly pedestrian `buflist', which is already used by at least one
other IRC client for referring to this feature.

Lastly, I'd like to stress that these modules (thankfully) won't be
loaded by default, which means you'll need to add `bufbar' and `nickbar'
to `erc-modules' when trying them out. Note that this patch set
currently depends on bug#63569 [3], whose changes need applying
beforehand.

Thanks!


[1] My justifications for taking such liberties are at best anecdotal,
    based mostly on personal impressions of prevailing usage patterns
    and the perceived motivations behind them. A few examples:

    a. The relative newness of erc-status-sidebar.el, its lack of an
       associated module, and its absence from ERC's Custom menu all
       point to its defaults being somewhat more free for the changing.
       The speedbar integration likewise lacks a module, and its
       graphical-only nature means its set of users currently excludes
       anyone using ERC from a terminal. (Less expected fallout from the
       proposed churn, IOW.)

    b. Both libraries provide an always-open side window (or, in
       speedbar's case, frame), which imposes a specific layout on the
       user, something that's relatively rare in Emacs outside of
       IDE-style modes. Compare this to something like ibuffer for
       listing buffers or a hypothetical /NAMES buffer, which, if based
       on `tabulated-list-mode', would make for a more familiar means of
       reviewing channel members. The point here is that devoted users
       likely aren't messing with erc-status-sidebar or erc-speedbar in
       droves, preferring more Emacsy alternatives instead.

    c. Newcomers can't be bothered with an overly involved setup if it
       requires carefully exploring options before trying. But they're
       perfectly willing to copy/paste gobs of configuration or even
       mindlessly follow a minutes long Customize itinerary, so long as
       the promise of emerging with something resembling their present
       idea of what makes an IRC client remains within reach. By
       introducing these modules "preconfigured," I'm positing that
       these preconceived notions typically include a reactive window
       list and/or nick list. That said, my hope is that these users
       will eventually gravitate toward the more Emacs-native way of
       doing things, at which point these modules will have served their
       primary purpose (of acting as bait).

[2] My reason for 86'ing the icons outright in the speedbar's new
    "window mode" is consistency. I figure anyone who wants the vanilla
    experience wants it in full and thus also wants a separate frame.
    That said, I suppose we could add a knob for tweaking this (or any
    of the other hard-coded choices mentioned), but IMO doing that
    unprovoked just contributes to "options sprawl."

[3] FWIW, all module names in contention flout our supposed policy of
    preferring those that align with host libraries and the features
    they `provide'.


In GNU Emacs 30.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version
 3.24.37, cairo version 1.17.6) of 2023-05-13 built on localhost
Repository revision: 867b104010760c4b7cd700078884cc774a01860a
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12014000
System Description: Fedora Linux 37 (Workstation Edition)

Configured using:
 'configure --enable-check-lisp-object-type --enable-checking=yes,glyphs
 'CFLAGS=-O0 -g3'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util text-property-search time-date mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils erc auth-source cl-seq
eieio eieio-core cl-macs password-cache json subr-x map format-spec
cl-loaddefs cl-lib erc-backend erc-networks byte-opt gv bytecomp
byte-compile erc-common erc-compat erc-loaddefs rmc iso-transl tooltip
cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd
fontset image regexp-opt fringe tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 64236 9476)
 (symbols 48 8573 0)
 (strings 32 23246 1709)
 (string-bytes 1 674076)
 (vectors 16 15015)
 (vector-slots 8 207266 8159)
 (floats 8 24 33)
 (intervals 56 229 0)
 (buffers 976 10))

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Fix-buffer-mismatch-bug-in-erc-scroll-to-bottom.patch

From 4a1bd9e173d91164d5abe6f2e349a447eaf019d7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 17 May 2023 19:48:02 -0700
Subject: [PATCH 1/5] [5.6] Fix buffer-mismatch bug in erc-scroll-to-bottom

* lisp/erc/erc-goodies.el (erc-scroll-to-bottom): Only `recenter' when
the selected window's buffer is current.  Previously, the module
`scrolltobottom' signaled an "Error in `post-command-hook'" when a
user clicked a channel indicator in the mode line from a window
showing another ERC buffer.
---
 lisp/erc/erc-goodies.el | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 01eae4b63c5..87c95778523 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -92,6 +92,7 @@ erc-scroll-to-bottom
     (save-restriction
       (widen)
       (when (and erc-insert-marker
+                 (eq (current-buffer) (window-buffer))
 		 ;; we're editing a line. Scroll.
 		 (> (point) erc-insert-marker))
 	(save-excursion
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0002-5.6-Allow-ERC-s-module-toggles-access-to-the-prefix-.patch

From 5ae05b1ad34ce1baea149c7af1e9e9282f101725 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Mon, 15 May 2023 00:16:00 -0700
Subject: [PATCH 2/5] [5.6] Allow ERC's module toggles access to the prefix arg

* lisp/erc/erc-common.el (erc--module-toggle-prefix-arg): Add internal
variable for preserving the `arg' passed to a module's minor-mode
toggle, which was previously discarded.  Doing this lets modules that
are more interactive in nature overload their mode toggles with
alternate behaviors.
(define-erc-module): Bind `erc--module-toggle-prefix-arg' to the `arg'
parameter, which is normally defined inside a `define-minor-mode' body
form.
* test/lisp/erc/erc-tests.el (define-erc-module--global,
define-erc-module--local): Expect activation body to be wrapped by a
let form binding `erc--module-toggle-prefix-arg'.
---
 lisp/erc/erc-common.el     | 14 +++++++++++---
 test/lisp/erc/erc-tests.el | 14 ++++++++------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index f152a1a32d9..dd39b30c4db 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -289,6 +289,15 @@ erc--find-feature
              (intern (file-name-base file))))
      (v v)))
 
+(defvar erc--module-toggle-prefix-arg nil
+  "The interpreted prefix arg of the minor-mode toggle.
+Non-nil inside an ERC module's activation (or deactivation)
+command, such as `erc-spelling-enable', when it's been called
+indirectly via the module's minor-mode toggle, i.e.,
+`erc-spelling-mode'.  Nil otherwise.  Its value is either the
+symbol `toggle' or an integer produced by `prefix-numeric-value'.
+See Info node `(elisp) Defining Minor Modes' for more.")
+
 (defmacro define-erc-module (name alias doc enable-body disable-body
                                   &optional local-p)
   "Define a new minor mode using ERC conventions.
@@ -337,9 +346,8 @@ define-erc-module
          :group (erc--find-group ',name ,(and alias (list 'quote alias)))
          ,@(unless local-p `(:require ',(erc--find-feature name alias)))
          ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name)))
-         (if ,mode
-             (,enable)
-           (,disable)))
+         (let ((erc--module-toggle-prefix-arg arg))
+           (if ,mode (,enable) (,disable))))
        ,(erc--assemble-toggle local-p name enable mode t enable-body)
        ,(erc--assemble-toggle local-p name disable mode nil disable-body)
        ,@(and-let* ((alias)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 991bfa3b082..de472527bde 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -2175,9 +2175,10 @@ define-erc-module--global
                         :group (erc--find-group 'mname 'malias)
                         :require 'nil
                         :type "mname"
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable ()
                         "Enable ERC mname mode."
@@ -2230,9 +2231,10 @@ define-erc-module--local
 Some docstring."
                         :global nil
                         :group (erc--find-group 'mname nil)
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable (&optional ,arg-en)
                         "Enable ERC mname mode.
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0003-5.6-Add-preset-styles-to-erc-status-sidebar.patch

From c4746e4bb3fde7670bd655ed7f17ec90435018ac Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 3/5] [5.6] Add preset styles to erc-status-sidebar

* lisp/erc/erc-networks.el (erc-networks--rename-server-buffer): Store
`erc-networks--id' in process object's plist.
* lisp/erc/erc-status-sidebar.el (erc-status-sidebar): Change parent
from `convenience' to `erc'.
(erc-status-sidebar-channel-format):
Mention in doc string that it depends on new option
`erc-status-sidebar-style'.
(erc-status-sidebar-highlight-active-buffer): New option to control
whether the current window's target is highlighted in the status bar.
(erc-status-sidebar-style): New option to determine whether servers
and queries also appear in the sidebar.
(erc-status-sidebar-click-display-action,
erc-status-sidebar-singular): New options.
(erc-status-sidebar-get-window): Consider
`erc-status-sidebar-singular'.
(erc-status-sidebar-open): Fix toggle functionality that somehow fell
through the cracks after the adoption of the package into ERC proper.
(erc-buflist-mode, erc-buflist-enable, erc-buflist-disable): New
module named `buflist' instead of `sidebar', which is more easily
confusable with `speedbar'.  The preferred name, `status-sidebar' was
unavailable because its minor-mode would have been
`erc-status-sidebar-mode', which is already taken by the major mode
used for status-bar buffers themselves.
(erc-status-sidebar-toggle): Ignore `erc-status-sidebar-singular'.
(erc-status-sidebar--trimpat, erc-status-sidebar--prechan): Add helper
vars for new sorting function, allowing it to honor the existing
interface, which only expects one argument.
(erc-status-sidebar-prefer-target-as-name): New function for
determining buffer name, preferring targets for target buffers.
(erc-status-sidebar-get-channame): Use internal API to help determine
name of buffer in sidebar.
(erc-status-sidebar-prefer-target-as-name,
erc-status-sidebar--show-disconnected,
erc-status-sidebar-all-target-buffers,
erc-status-sidebar-default-allsort): Add new naming and sorting
functions and associated helper functions and variables.
(erc-status-sidebar--active-marker,
erc-status-sidebar--set-active-line): New variable and function for
highlighting the active target in the status bar.
(erc-status-sidebar-default-insert,
erc-status-sidebar-pad-hierarchy): New functions for visiting various
stages of buffer modification when rendering sidebar.
(erc-status-sidebar-click): Appeal to option
`erc-status-sidebar-display-action' for `pop-to-buffer' action.
(erc-status-sidebar-scroll-up, erc-status-sidebar-scroll-down,
erc-status-sidebar-recenter): Add commands to scroll and
recenter sidebar from a target buffer's window.
(erc-status-sidebar-refresh): Consider presets and new options when
rendering sidebar.  Disable `erc-buflist-mode' when active.
(erc-status-sidebar-set-window-preserve-size): Ignore
`erc-status-sidebar-singular'.
(erc-status-sidebar-mode): Make non-interactive to avoid confusion
when folks run "M-x erc-status-sidebar-mode" expecting a module
toggle.
* test/lisp/erc/erc-scenarios-status-sidebar.el: New file.
* test/lisp/erc/resources/base/gapless-connect/foonet.eld: Fix wrong
manifest for channel and extend PASS timeout.
---
 lisp/erc/erc-networks.el                      |   1 +
 lisp/erc/erc-status-sidebar.el                | 328 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  93 +++++
 .../resources/base/gapless-connect/foonet.eld |   8 +-
 4 files changed, 400 insertions(+), 30 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-status-sidebar.el

diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index dd481032e7e..60d76d059da 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1459,6 +1459,7 @@ erc-networks--rename-server-buffer
          ;; When this ends up being the current buffer, either we have
          ;; a "given" ID or the buffer was reused on reconnecting.
          (existing (get-buffer name)))
+    (process-put new-proc 'erc-networks--id erc-networks--id)
     (cond ((or (not existing)
                (erc-networks--id-given erc-networks--id)
                (eq existing (current-buffer)))
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index f11faa3db10..c06ba53f3ae 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -45,6 +45,13 @@
 ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and
 ;; close the sidebar on all frames.
 
+;; In addition to the commands above, you can also try the all-in-one,
+;; "DWIM" command, `erc-bufbar-mode'.  See its doc string for usage.
+
+;; If you want the status sidebar enabled whenever you use ERC, add
+;; `bufbar' to `erc-modules'.  Note that this library also has a major
+;; mode, `erc-status-sidebar-mode', which is for internal use.
+
 ;;; Code:
 
 (require 'erc)
@@ -53,8 +60,15 @@
 (require 'seq)
 
 (defgroup erc-status-sidebar nil
-  "A sidebar for ERC channel status."
-  :group 'convenience)
+  "A responsive side window listing all connected ERC buffers.
+More commonly known as a window list or \"buflist\", this side
+panel displays clickable buffer names for switching to with the
+mouse.  By default, ERC highlights the name corresponding to the
+selected window's buffer, if any.  Here, \"connected buffer\"
+means one belonging to a session context for a server that ERC is
+currently communicating with.  For information on how the window
+itself works, see Info node `(elisp) Side Windows'."
+  :group 'erc)
 
 (defcustom erc-status-sidebar-buffer-name "*ERC Status*"
   "Name of the sidebar buffer."
@@ -80,9 +94,78 @@ erc-status-sidebar-channel-sort
 
 (defcustom erc-status-sidebar-channel-format
   'erc-status-sidebar-default-chan-format
-  "Function used to format channel names for display in the sidebar."
+  "Function used to format channel names for display in the sidebar.
+Only consulted for certain values of `erc-status-sidebar-style'."
   :type 'function)
 
+(defcustom erc-status-sidebar-highlight-active-buffer t
+  "Whether to highlight the selected window's buffer in the sidebar.
+ERC uses the same instance across all frames.  May not be
+compatible with all values of `erc-status-sidebar-style'."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defcustom erc-status-sidebar-style 'all-queries-first
+  "Preset style for rendering the sidebar.
+
+When set to `channels-only', ERC limits the items in the
+status bar to uniquified channels.  It uses the options
+and functions
+
+  `erc-channel-list',
+  `erc-status-sidebar-channel-sort',
+  `erc-status-sidebar-get-channame',
+  `erc-status-sidebar-channel-format'
+  `erc-status-sidebar-default-insert'
+
+for selecting, formatting, naming, and inserting entries.  When
+set to one of the various \\=`all-*' values, such as `all-mixed',
+ERC shows channels and queries under their respective server
+buffers, using the functions
+
+  `erc-status-sidebar-all-target-buffers',
+  `erc-status-sidebar-default-allsort',
+  `erc-status-sidebar-prefer-target-as-name',
+  `erc-status-sidebar-default-chan-format',
+  `erc-status-sidebar-pad-hierarchy'
+
+for the above-mentioned purposes.  ERC also accepts a list of
+functions to preform these roles a la carte.  See doc strings for
+a description of their expected arguments and return values."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const channels-only)
+                 (const all-mixed)
+                 (const all-queries-first)
+                 (const all-channels-first)
+                 (list (function :tag "Buffer lister")
+                       (function :tag "Buffer sorter")
+                       (function :tag "Name extractor")
+                       (function :tag "Name formatter")
+                       (function :tag "Name inserter"))))
+
+(defcustom erc-status-sidebar-click-display-action t
+  "How to display a buffer when clicked.
+Values can be anything recognized by `display-buffer' for its
+ACTION parameter."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const :tag "Always use/create other window" t)
+                 (const :tag "Let `display-buffer' decide" nil)
+                 (const :tag "Same window" (display-buffer-same-window
+                                            (inhibit-same-window . nil)))
+                 (cons :tag "Action"
+                       (choice function (repeat function))
+                       (alist :tag "Action arguments"
+                              :key-type symbol
+                              :value-type (sexp :tag "Value")))))
+
+(defcustom erc-status-sidebar-singular t
+  "Whether to show the sidebar on all frames or just one (default)."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defvar hl-line-mode)
+(declare-function hl-line-highlight "hl-line" nil)
+
 (defun erc-status-sidebar-display-window ()
   "Display the status buffer in a side window.  Return the new window."
   (display-buffer
@@ -94,7 +177,8 @@ erc-status-sidebar-get-window
   "Return the created/existing window displaying the status buffer.
 
 If NO-CREATION is non-nil, the window is not created."
-  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name)))
+  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name
+                                           erc-status-sidebar-singular)))
     (unless (or sidebar-window no-creation)
       (with-current-buffer (erc-status-sidebar-get-buffer)
         (setq-local vertical-scroll-bar nil))
@@ -144,22 +228,50 @@ erc-status-sidebar-open
   "Open or create a sidebar."
   (interactive)
   (save-excursion
-    (let ((sidebar-exists (erc-status-sidebar-buffer-exists-p))
-          (sidebar-buffer (erc-status-sidebar-get-buffer))
-          ;; (sidebar-window (erc-status-sidebar-get-window))
-          )
-      (unless sidebar-exists
-        (with-current-buffer sidebar-buffer
-          (erc-status-sidebar-mode)
-          (erc-status-sidebar-refresh))))))
+    (if (erc-status-sidebar-buffer-exists-p)
+        (erc-status-sidebar-get-window)
+      (with-current-buffer (erc-status-sidebar-get-buffer)
+        (erc-status-sidebar-mode)
+        (erc-status-sidebar-refresh)))))
+
+;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t)
+(define-erc-module bufbar nil
+  "Show `erc-track'-like activity in a side window.
+When enabling, show the sidebar immediately if called from a
+connected ERC buffer.  Otherwise, arrange for doing so on connect
+or whenever next displaying a new ERC buffer.  When disabling,
+hide the status window if it's showing.  With a negative prefix
+arg, also shutdown the session."
+  ((unless erc-track-mode
+     (unless (memq 'track erc-modules)
+       (erc--warn-once-before-connect 'erc-bufbar-mode
+         "Module `bufbar' needs global module `track'. Enabling now."
+         " This will affect \C-]all\C-] ERC sessions."
+         " Add `track' to `erc-modules' to silence this message."))
+     (erc-track-mode +1))
+   (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (unless erc--updating-modules-p
+     (if (erc-with-server-buffer erc-server-connected)
+         (erc-status-sidebar-open)
+       (setq erc-bufbar-mode nil)
+       (user-error "`%s' not called from a connected ERC buffer."
+                   'erc-bufbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (erc-status-sidebar-close erc-status-sidebar-singular)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-status-sidebar-kill))))
 
 ;;;###autoload
 (defun erc-status-sidebar-toggle ()
-  "Toggle the sidebar open/closed on the current frame."
+  "Toggle the sidebar open/closed on the current frame.
+Do this regardless of `erc-status-sidebar-singular'."
   (interactive)
   (if (get-buffer-window erc-status-sidebar-buffer-name nil)
       (erc-status-sidebar-close)
-    (erc-status-sidebar-open)))
+    (let (erc-status-sidebar-singular)
+      (erc-status-sidebar-open))))
 
 (defun erc-status-sidebar-get-channame (buffer)
   "Return name of BUFFER with all leading \"#\" characters removed."
@@ -174,6 +286,98 @@ erc-status-sidebar-default-chansort
                    (string< (erc-status-sidebar-get-channame x)
                             (erc-status-sidebar-get-channame y)))))
 
+(defvar erc-status-sidebar--trimpat nil)
+(defvar erc-status-sidebar--prechan nil)
+
+(defun erc-status-sidebar-prefer-target-as-name (buffer)
+  "Return some name to represent buffer in the sidebar."
+  (if-let ((target (buffer-local-value 'erc--target buffer)))
+      (cond ((and erc-status-sidebar--trimpat (erc--target-channel-p target))
+             (string-trim-left (erc--target-string target)
+                               erc-status-sidebar--trimpat))
+            ((and erc-status-sidebar--prechan (erc--target-channel-p target))
+             (concat erc-status-sidebar--prechan
+                     (erc--target-string target)))
+            (t (erc--target-string target)))
+    (buffer-name buffer)))
+
+;; This could be converted into an option if people want.
+(defvar erc-status-sidebar--show-disconnected t)
+
+(defun erc-status-sidebar-all-target-buffers (process)
+  (erc-buffer-filter (lambda ()
+                       (and erc--target
+                            (or erc-status-sidebar--show-disconnected
+                                (erc-server-process-alive))))
+                     process))
+
+;; FIXME profile this.  Rebuilding the graph every time track updates
+;; seems wasteful for occasions where server messages are processed
+;; unthrottled, such as during history playback.  If it's a problem,
+;; we should look into rewriting this using `ewoc' or some other
+;; solution that maintains a persistent model.
+(defun erc-status-sidebar-default-allsort (target-buffers)
+  "Return a list of servers interspersed with their targets."
+  (mapcan (pcase-lambda (`(,proc . ,chans))
+            (cons (process-buffer proc)
+                  (let ((erc-status-sidebar--trimpat
+                         (and (eq erc-status-sidebar-style 'all-mixed)
+                              (with-current-buffer (process-buffer proc)
+                                (when-let ((ch-pfxs (erc--get-isupport-entry
+                                                     'CHANTYPES 'single)))
+                                  (regexp-quote ch-pfxs)))))
+                        (erc-status-sidebar--prechan
+                         (and (eq erc-status-sidebar-style
+                                  'all-queries-first)
+                              "\C-?")))
+                    (sort chans
+                          (lambda (x y)
+                            (string<
+                             (erc-status-sidebar-prefer-target-as-name x)
+                             (erc-status-sidebar-prefer-target-as-name y)))))))
+          (sort (seq-group-by (lambda (b)
+                                (buffer-local-value 'erc-server-process b))
+                              target-buffers)
+                (lambda (a b)
+                  (string< (buffer-name (process-buffer (car a)))
+                           (buffer-name (process-buffer (car b))))))))
+
+(defvar-local erc-status-sidebar--active-marker nil
+  "Marker indicating currently active buffer.")
+
+(defun erc-status-sidebar--set-active-line (erc-buffer)
+  (when (and erc-status-sidebar-highlight-active-buffer
+             (eq (window-buffer (and (minibuffer-window-active-p
+                                      (selected-window))
+                                     (minibuffer-selected-window)))
+                 erc-buffer))
+    (set-marker erc-status-sidebar--active-marker (point))))
+
+(defun erc-status-sidebar-default-insert (channame chanbuf _chanlist)
+  "Insert CHANNAME followed by a newline.
+Maybe arrange to highlight line if CHANBUF is showing in the
+focused window."
+  (erc-status-sidebar--set-active-line chanbuf)
+  (insert channame "\n"))
+
+(defun erc-status-sidebar-pad-hierarchy (bufname buffer buflist)
+  "Prefix BUFNAME to emphasize BUFFER's role in BUFLIST."
+  (if (and (buffer-live-p buffer) (buffer-local-value 'erc--target buffer))
+      (insert " ")
+    (unless (eq buffer (car buflist))
+      (insert "\n"))) ;  ^L
+  (when bufname
+    (erc-status-sidebar--set-active-line buffer))
+  (insert (or bufname
+              (and-let* (((not (buffer-live-p buffer)))
+                         (next (cadr (member buffer buflist)))
+                         ((buffer-live-p next))
+                         (proc (buffer-local-value 'erc-server-process next))
+                         (id (process-get proc 'erc-networks--id)))
+                (symbol-name (erc-networks--id-symbol id)))
+              "???")
+          "\n"))
+
 (defun erc-status-sidebar-default-chan-format (channame
                                                &optional num-messages erc-face)
   "Format CHANNAME for display in the sidebar.
@@ -193,43 +397,111 @@ erc-status-sidebar-default-chan-format
 (defun erc-status-sidebar-refresh ()
   "Update the content of the sidebar."
   (interactive)
-  (let ((chanlist (apply erc-status-sidebar-channel-sort
-                         (erc-channel-list nil) nil)))
+  (pcase-let* ((`(,list-fn ,sort-fn ,name-fn ,fmt-fn ,insert-fn)
+                (pcase erc-status-sidebar-style
+                  ('channels-only (list #'erc-channel-list
+                                        erc-status-sidebar-channel-sort
+                                        #'erc-status-sidebar-get-channame
+                                        erc-status-sidebar-channel-format
+                                        #'erc-status-sidebar-default-insert))
+                  ((or 'all-mixed 'all-queries-first 'all-channels-first)
+                   '(erc-status-sidebar-all-target-buffers
+                     erc-status-sidebar-default-allsort
+                     erc-status-sidebar-prefer-target-as-name
+                     erc-status-sidebar-default-chan-format
+                     erc-status-sidebar-pad-hierarchy))
+                  (v v)))
+               (chanlist (apply sort-fn (funcall list-fn nil) nil))
+               (window nil)
+               (winstart nil))
     (with-current-buffer (erc-status-sidebar-get-buffer)
+      (setq window (get-buffer-window nil erc-status-sidebar-singular)
+            winstart (and window (window-start window)))
       (erc-status-sidebar-writable
        (delete-region (point-min) (point-max))
        (goto-char (point-min))
+       (if erc-status-sidebar--active-marker
+           (set-marker erc-status-sidebar--active-marker nil)
+         (setq erc-status-sidebar--active-marker (make-marker)))
        (dolist (chanbuf chanlist)
          (let* ((tup (seq-find (lambda (tup) (eq (car tup) chanbuf))
                                erc-modified-channels-alist))
                 (count (if tup (cadr tup)))
                 (face (if tup (cddr tup)))
-                (channame (apply erc-status-sidebar-channel-format
-                                 (buffer-name chanbuf) count face nil))
+                (face (if (or (not (buffer-live-p chanbuf))
+                              (not (erc-server-process-alive chanbuf)))
+                          `(shadow ,face)
+                        face))
+                (channame (apply fmt-fn
+                                 (copy-sequence (funcall name-fn chanbuf))
+                                 count face nil))
                 (cnlen (length channame)))
            (put-text-property 0 cnlen 'erc-buf chanbuf channame)
            (put-text-property 0 cnlen 'mouse-face 'highlight channame)
            (put-text-property
             0 cnlen 'help-echo
             "mouse-1: switch to buffer in other window" channame)
-           (insert channame "\n")))))))
+           (funcall insert-fn channame chanbuf chanlist)))
+       (when winstart
+         (set-window-point window winstart)
+         (with-selected-window window (recenter 0)))
+       (when (and erc-status-sidebar-highlight-active-buffer
+                  (marker-buffer erc-status-sidebar--active-marker))
+         (goto-char erc-status-sidebar--active-marker)
+         (require 'hl-line)
+         (unless hl-line-mode (hl-line-mode +1))
+         (hl-line-highlight))))))
 
 (defun erc-status-sidebar-kill ()
   "Close the ERC status sidebar and its buffer."
   (interactive)
+  (when (and erc-bufbar-mode (not erc--module-toggle-prefix-arg))
+    (erc-bufbar-mode -1))
   (ignore-errors (kill-buffer erc-status-sidebar-buffer-name)))
 
 (defun erc-status-sidebar-click (event)
   "Handle click EVENT in `erc-status-sidebar-mode-map'."
   (interactive "e")
   (save-excursion
-    (let ((window (posn-window (event-end event)))
+    (let ((window (posn-window (event-start event)))
           (pos (posn-point (event-end event))))
-      (set-buffer (window-buffer window))
-      (let ((buf (get-text-property pos 'erc-buf)))
-        (when buf
-          (select-window window)
-          (switch-to-buffer-other-window buf))))))
+      ;; Current buffer is "ERC Status" and its window is selected
+      (cl-assert (eq major-mode 'erc-status-sidebar-mode))
+      (cl-assert (eq (selected-window) window))
+      (cl-assert (eq (window-buffer window) (current-buffer)))
+      (when-let ((buf (get-text-property pos 'erc-buf)))
+        ;; Option operates relative to last selected window
+        (select-window (get-mru-window nil nil 'not-selected))
+        (pop-to-buffer buf erc-status-sidebar-click-display-action)))))
+
+(defun erc-status-sidebar-scroll-up (lines)
+  "Scroll sidebar buffer's content LINES linse upward.
+If LINES is nil, scroll up a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window lines)))
+
+(defun erc-status-sidebar-scroll-down (lines)
+  "Scroll sidebar buffer's content LINES lines downward.
+If LINES is nil, scroll down a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window-down lines)))
+
+(defun erc-status-sidebar-recenter (arg)
+  "Recenter the status sidebar.
+Expect `erc-status-sidebar-highlight-active-buffer' to be non-nil
+and to be invoked in a buffer matching the line currently
+highlighted."
+  (interactive "P")
+  (let* ((buf (erc-status-sidebar-get-buffer))
+         (win (get-buffer-window buf)))
+    (with-current-buffer buf
+      (when (and erc-status-sidebar--active-marker
+                 (marker-position erc-status-sidebar--active-marker))
+        (with-selected-window win
+          (goto-char erc-status-sidebar--active-marker)
+          (recenter arg t))))))
 
 (defvar erc-status-sidebar-mode-map
   (let ((map (make-sparse-keymap)))
@@ -268,13 +540,17 @@ erc-status-sidebar-set-window-preserve-size
 Note that preserve status needs to be reset when the window is
 manually resized, so `erc-status-sidebar-mode' adds this function
 to the `window-configuration-change-hook'."
-  (when (and (eq (selected-window) (erc-status-sidebar-get-window))
+  (when (and (eq (selected-window) (let (erc-status-sidebar-singular)
+                                     (erc-status-sidebar-get-window)))
              (fboundp 'window-preserve-size))
     (unless (eq (window-total-width) (window-min-size nil t))
       (apply #'window-preserve-size (selected-window) t t nil))))
 
 (define-derived-mode erc-status-sidebar-mode special-mode "ERC Sidebar"
   "Major mode for ERC status sidebar."
+  ;; Users invoking M-x erc-status-sidebar-mode most likely expect to
+  ;; summon the module's minor-mode, `erc-bufbar-mode'.
+  :interactive nil
   ;; Don't scroll the buffer horizontally, if a channel name is
   ;; obscured then the window can be resized.
   (setq-local auto-hscroll-mode nil)
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
new file mode 100644
index 00000000000..aec61333e0b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -0,0 +1,93 @@
+;;; erc-scenarios-status-sidebar.el --- sidebar/speedbar -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+(require 'erc-status-sidebar)
+
+
+(ert-deftest erc-scenarios-status-sidebar--bufbar ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(bufbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit"))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (ert-info ("Activity marker is in the right spot")
+        (let ((obuf (window-buffer))) ; *scratch*
+          (set-window-buffer (selected-window) "#foo")
+          (erc-d-t-wait-for 5
+              (when noninteractive
+                (erc-status-sidebar-refresh))
+            (with-current-buffer "*ERC Status*"
+              (and (marker-position erc-status-sidebar--active-marker)
+                   (goto-char erc-status-sidebar--active-marker)
+                   ;; The " [N]" suffix disappears because it's selected
+                   (search-forward "#foo" (pos-eol) t))))
+          (set-window-buffer (selected-window) obuf))))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "*ERC Status*"))
+      (ert-info ("Hierarchy printed correctly")
+        (funcall expect 10 "barnet [")
+        (funcall expect 10 "#bar [")
+        (funcall expect 10 "foonet [")
+        (funcall expect 10 "#foo")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (should (get-buffer-window "*ERC Status*"))
+        (erc-bufbar-mode -1)
+        (should-not (get-buffer-window "*ERC Status*"))
+        (erc-status-sidebar-kill)
+        (should-not (get-buffer "*ERC Status*"))))))
+
+;;; erc-scenarios-status-sidebar.el ends here
diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
index 4ac4a3e5968..10b742fdb34 100644
--- a/test/lisp/erc/resources/base/gapless-connect/foonet.eld
+++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
@@ -1,7 +1,7 @@
 ;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :foonet:changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
  (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
  (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
  (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
@@ -21,7 +21,7 @@
  ;; No mode answer
  (0 ":irc.znc.in 306 tester :You have been marked as being away")
  (0 ":tester!~u@HIDDEN JOIN #foo")
- (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob tester")
  (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
  (0 ":***!znc@HIDDEN PRIVMSG #foo :Buffer Playback...")
  (0 ":alice!~u@HIDDEN PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.")
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0004-5.6-Add-erc-status-sidebar-integration-to-erc-speedb.patch

From fd2ec89c40dd52322c8196c3653e06c937176bc7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 4/5] [5.6] Add erc-status-sidebar integration to erc-speedbar

* lisp/erc/erc-speedbar.el: Require `erc-button' atop file and don't
bother loading `dframe', which `speedbar' handles for us.
(erc-speedbar-hide-mode-topic): New option determining whether to hide
the mode and topic.
(erc-speedbar-my-nick-face): New option for determining face to use
when displaying user's current nick.
(erc-speedbar-browser): Call `erc-install-speedbar-variables'
explicitly and remove top-level `with-eval-after-load'.
(erc-speedbar-insert-target): Add parenthesized channel count after
channel name in server and channel views.
(erc-speedbar-expand-channel): Hide mode and topic depending on option
`erc-speedbar-hide-mode-topic' and pass buffer to
`erc-speedbar-insert-user'.
(erc-speedbar--nick-face-function): New internal function-interface
variable.
(erc-speedbar--highlight-self-and-ops): New function to serve as
default value for `erc-speedbar--nick-face-function'.
(erc-speedbar--on-click): Dispatch `erc-nick-popup' after trimming
status chars.
(erc-speedbar-insert-user): Revise doc string.  Call
`erc-speedbar--nick-face-function' to determine face.  Change
token for both expansion and on-click text props.  Assign
`erc-speedbar--on-click' as the mouse handler for nick items.
(erc-speedbar-emulated-sidebar-width): New option to control width
of nicknames list window.
(erc-speedbar): Mention `erc-nickbar-mode' in group doc string.
(erc-speedbar--buffer-options): Variable to override options locally
in speedbar buffer.
(erc-speedbar--hidden-speedbar-frame): Add variable to hold original
`speedbar-frame' before spoofing by setting to selected frame
containing window showing ERC buffer.
(erc-speedbar--dframe-controlled) Add function to overwrite
`speedbar-frame-mode' as `dframe-controlled' in speedbar buffer.
(erc-speedbar--emulate-sidebar-set-window-preserve-size,
erc-speedbar--status-sidebar-mode--unhook): Add function
to ensure status sidebar is showing correctly and helper to
unregister from hook on teardown.
(erc-speedbar--emulate-sidebar): Add function to
control sidebar nicknames setup.
(erc-speedbar--toggle-nicknames-sidebar): Add toggle function
for sidebar or speedbar.
(erc-speedbar--ensure): Add helper function to show speedbar if its
hidden or create one if none exists.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable):
Add new module.
(erc-speedbar-toggle-nicknames-window-lock,
erc-speedbar-close-nicknames-window): Add commands to close speedbar
window and toggle its cyclability.
(erc-speedbar--compose-nicks-face): Add helper for nicks integration.
* test/lisp/erc/erc-scenarios-status-sidebar.el
(erc-scenarios-status-sidebar--nickbar): New test, unfortunately only
runs in terminals.
---
 lisp/erc/erc-speedbar.el                      | 284 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  76 +++++
 2 files changed, 342 insertions(+), 18 deletions(-)

diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index a9443e0ea17..21ad4c6f97a 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -32,20 +32,31 @@
 ;;   update-channel, update-nick, remove-nick-from-channel, ...
 ;; * Use indicator-strings for op/voice
 ;; * Extract/convert face notes field from bbdb if available
+;; * Write tests that run in a term-mode subprocess
 ;;
 ;;; Code:
 
 (require 'erc)
 (require 'erc-goodies)
+(require 'erc-button)
 (require 'speedbar)
-(condition-case nil (require 'dframe) (error nil))
 
 ;;; Customization:
 
 (defgroup erc-speedbar nil
-  "Integration of ERC in the Speedbar."
+  "Speedbar integration for ERC.
+To open an ERC-flavored speedbar in a separate frame, run the
+command `erc-speedbar-browser'.  To use a window-based proxy
+instead, run \\[erc-nickbar-mode] in a connected ERC buffer or
+put `nickbar' in `erc-modules' before connecting.  See Info
+node `(speedbar) Top' for more about the underlying integration."
   :group 'erc)
 
+(defcustom erc-speedbar-nicknames-window-width 18
+  "Default width of the nicknames sidebar (in columns)."
+  :package-version '(ERC . "5.7")
+  :type 'integer)
+
 (defcustom erc-speedbar-sort-users-type 'activity
   "How channel nicknames are sorted.
 
@@ -56,6 +67,23 @@ erc-speedbar-sort-users-type
 		 (const :tag "Sort users alphabetically" alphabetical)
 		 (const :tag "Do not sort users" nil)))
 
+(defcustom erc-speedbar-hide-mode-topic 'headerline
+  "Hide mode and topic lines."
+  :package-version '(ERC . "5.7") ; FIXME sync on release
+  :type '(choice (const :tag "Always show" nil)
+                 (const :tag "Always hide" t)
+                 (const :tag "Omit when headerline visible" headerline)))
+
+(defcustom erc-speedbar-my-nick-face t
+  "A face to use for your nickname.
+When the value is t, ERC uses `erc-current-nick-face' if
+`erc-match' has been loaded and `erc-my-nick-face' otherwise.
+When using the `nicks' module, you can see your nick as it
+appears to others by coordinating with the option
+`erc-nicks-skip-faces'."
+  :package-version '(ERC . "5.7")
+  :type '(choice face (const :tag "Match or own input face" t)))
+
 (defvar erc-speedbar-key-map nil
   "Keymap used when in erc display mode.")
 
@@ -88,10 +116,6 @@ erc-speedbar-menu-items
 		     (looking-at "[0-9]+: *.-. "))])
   "Additional menu-items to add to speedbar frame.")
 
-;; Make sure our special speedbar major mode is loaded
-(with-eval-after-load 'speedbar
-  (erc-install-speedbar-variables))
-
 ;;; ERC hierarchy display method
 ;;;###autoload
 (defun erc-speedbar-browser ()
@@ -99,6 +123,7 @@ erc-speedbar-browser
 This will add a speedbar major display mode."
   (interactive)
   (require 'speedbar)
+  (erc-install-speedbar-variables)
   ;; Make sure that speedbar is active
   (speedbar-frame-mode 1)
   ;; Now, throw us into Info mode on speedbar.
@@ -169,12 +194,18 @@ erc-speedbar-channel-buttons
 	  t)))))
 
 (defun erc-speedbar-insert-target (buffer depth)
-  (if (with-current-buffer buffer
-	(erc-channel-p (erc-default-target)))
-      (speedbar-make-tag-line
-       'bracket ?+ 'erc-speedbar-expand-channel buffer
-       (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
-       depth)
+  (if (erc--target-channel-p (buffer-local-value 'erc--target buffer))
+      (progn
+        (speedbar-make-tag-line
+         'bracket ?+ 'erc-speedbar-expand-channel buffer
+         (erc--target-string (buffer-local-value 'erc--target buffer))
+         'erc-speedbar-goto-buffer buffer nil
+         depth)
+        (save-excursion
+          (forward-line -1)
+          (let ((table (buffer-local-value 'erc-channel-users buffer)))
+            (speedbar-add-indicator (format "(%d)" (hash-table-count table)))
+            (rx "(" (+ (any "0-9")) ")"))))
     ;; Query target
     (speedbar-make-tag-line
      nil nil nil nil
@@ -220,6 +251,13 @@ erc-speedbar-expand-channel
 	    'angle ?i nil nil
 	    (concat "Topic: " topic) nil nil nil
 	    (1+ indent)))
+         (unless (pcase erc-speedbar-hide-mode-topic
+                   ('nil 'show)
+                   ('headerline (null erc-header-line-format)))
+           (save-excursion
+             (goto-char (point-max))
+             (forward-line (if (string= topic "") -1 -2))
+             (put-text-property (pos-bol) (point-max) 'invisible t)))
 	 (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical)
 			     (erc-sort-channel-users-alphabetically
 			      (with-current-buffer channel
@@ -233,17 +271,52 @@ erc-speedbar-expand-channel
 	   (when names
 	     (speedbar-with-writable
 	      (dolist (entry names)
-		(erc-speedbar-insert-user entry ?+ (1+ indent))))))))))
+                (erc-speedbar-insert-user entry ?+ (1+ indent) channel)))))))))
    ((string-search "-" text)
     (speedbar-change-expand-button-char ?+)
     (speedbar-delete-subblock indent))
    (t (error "Ooops... not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun erc-speedbar-insert-user (entry exp-char indent)
+(defvar erc-speedbar--nick-face-function #'erc-speedbar--highlight-self-and-ops
+  "Function called when finding a face for fontifying nicks.
+Called with the proposed nick, the `erc-server-user', and the
+`erc-channel-user'.  Should return any valid face, possibly
+composed or anonymous, or nil.")
+
+(defun erc-speedbar--highlight-self-and-ops (buffer user cuser)
+  "Highlight own nick and op'd users in the speedbar."
+  (with-current-buffer buffer
+    (if (erc-current-nick-p (erc-server-user-nickname user))
+        (pcase erc-speedbar-my-nick-face
+          ('t (if (featurep 'erc-match)
+                  'erc-current-nick-face
+                'erc-my-nick-face))
+          (v v))
+      ;; FIXME overload `erc-channel-user-owner-p' and friends to
+      ;; accept an `erc-channel-user' object and replace this unrolled
+      ;; stuff with a single call to `erc-get-user-mode-prefix'.
+      (and cuser (or (erc-channel-user-owner cuser)
+                     (erc-channel-user-admin cuser)
+                     (erc-channel-user-op cuser)
+                     (erc-channel-user-halfop cuser)
+                     (erc-channel-user-voice cuser))
+           erc-button-nickname-face))))
+
+(defun erc-speedbar--on-click (nick sbtoken _indent)
+  ;; 0: finger, 1: name, 2: info, 3: buffer-name
+  (with-current-buffer (nth 3 sbtoken)
+    (erc-nick-popup (string-trim-left nick "[~&@%+]+"))))
+
+(defun erc-speedbar-insert-user (entry exp-char indent &optional buffer)
   "Insert one user based on the channel member list ENTRY.
-EXP-CHAR is the expansion character to use.
-INDENT is the current indentation level."
+Expect EXP-CHAR to be the expansion character to use, INDENT the
+current indentation level, and BUFFER the associated channel or
+query buffer.  Set the `speedbar-function' text property to
+`erc-speedbar--on-click', which is called with the formatted
+nick, a so-called \"token\", and the indent level.  The token is
+a list of four items: the userhost, the GECOS, the current
+`erc-server-user' info slot, and the associated buffer."
   (let* ((user (car entry))
 	 (cuser (cdr entry))
 	 (nick (erc-server-user-nickname user))
@@ -255,11 +328,12 @@ erc-speedbar-insert-user
 	 (op (and cuser (erc-channel-user-op cuser)))
 	 (nick-str (concat (if op "@" "") (if voice "+" "") nick))
 	 (finger (concat login (when (or login host) "@") host))
-	 (sbtoken (list finger name info)))
+         (sbtoken (list finger name info (buffer-name buffer))))
     (if (or login host name info) ; we want to be expandable
 	(speedbar-make-tag-line
 	 'bracket ?+ 'erc-speedbar-expand-user sbtoken
-	 nick-str nil sbtoken nil
+         nick-str #'erc-speedbar--on-click sbtoken
+         (funcall erc-speedbar--nick-face-function buffer user cuser)
 	 indent)
       (when (equal exp-char ?-)
 	(forward-line -1)
@@ -357,6 +431,180 @@ erc-speedbar-item-info
 	  (t
 	   (message "%s" txt)))))
 
+
+;;;; Status-sidebar integration
+
+(defvar erc-status-sidebar-buffer-name)
+(declare-function erc-status-sidebar-set-window-preserve-size
+                  "erc-status-sidebar" nil)
+(declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil)
+
+(defvar erc-speedbar--buffer-options
+  '((speedbar-update-flag . t)
+    (speedbar-use-images . nil)
+    (speedbar-hide-button-brackets-flag . t)))
+
+(defvar erc-speedbar--hidden-speedbar-frame nil)
+
+(defun erc-speedbar--emulate-sidebar-set-window-preserve-size ()
+  (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer))
+        (display-buffer-overriding-action
+         `(display-buffer-in-side-window
+           . ((side . right)
+              (window-width . ,erc-speedbar-nicknames-window-width)))))
+    (erc-status-sidebar-set-window-preserve-size)
+    (when-let ((window (get-buffer-window speedbar-buffer)))
+      (set-window-parameter window 'no-other-window nil)
+      (internal-show-cursor window t))))
+
+(defun erc-speedbar--status-sidebar-mode--unhook ()
+  "Remove hooks installed by `erc-status-sidebar-mode'."
+  (remove-hook 'window-configuration-change-hook
+               #'erc-speedbar--emulate-sidebar-set-window-preserve-size))
+
+(defun erc-speedbar--emulate-sidebar ()
+  (require 'erc-status-sidebar)
+  (cl-assert speedbar-frame)
+  (cl-assert (eq speedbar-buffer (current-buffer)))
+  (cl-assert (eq speedbar-frame (selected-frame)))
+  (setq erc-speedbar--hidden-speedbar-frame speedbar-frame
+        dframe-controlled #'erc-speedbar--dframe-controlled)
+  (add-hook 'window-configuration-change-hook
+            #'erc-speedbar--emulate-sidebar-set-window-preserve-size nil t)
+  (add-hook 'kill-buffer-hook
+            #'erc-speedbar--status-sidebar-mode--unhook nil t)
+  (with-current-buffer speedbar-buffer
+    (pcase-dolist (`(,var . ,val) erc-speedbar--buffer-options)
+      (set (make-local-variable var) val)))
+  (when (memq 'nicks erc-modules)
+    (with-current-buffer speedbar-buffer
+      (add-function :around (local 'erc-speedbar--nick-face-function)
+                    #'erc-speedbar--compose-nicks-face))))
+
+(defun erc-speedbar--toggle-nicknames-sidebar (arg)
+  (let ((force (numberp arg)))
+    (if speedbar-buffer
+        (progn
+          (cl-assert (buffer-live-p speedbar-buffer))
+          (if (or (and force (< arg 0))
+                  (and (not force) (get-buffer-window speedbar-buffer nil)))
+              (erc-speedbar-close-nicknames-window nil)
+            (when (or (not force) (>= arg 0))
+              (with-selected-frame speedbar-frame
+                (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
+      (when (or (not force) (>= arg 0))
+        (let ((speedbar-frame-parameters (backquote-list*
+                                          '(visibility . nil)
+                                          '(no-other-frame . t)
+                                          speedbar-frame-parameters))
+              (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
+          (erc-speedbar-browser)
+          ;; If we put the remaining parts in the "create hook" along
+          ;; with everything else, the frame with `window-main-window'
+          ;; gets raised and steals focus if you've switched away from
+          ;; Emacs in the meantime.
+          (make-frame-invisible speedbar-frame)
+          (select-frame (setq speedbar-frame (previous-frame)))
+          (erc-speedbar--emulate-sidebar-set-window-preserve-size))))))
+
+(defun erc-speedbar--ensure (&optional force)
+  (when (or (erc-server-buffer) force)
+    (erc-speedbar--toggle-nicknames-sidebar +1)
+    (speedbar-enable-update)))
+
+;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
+(define-erc-module nickbar nil
+  "Show nicknames in a side window.
+When enabling, create a speedbar session if one doesn't exist and
+show its buffer in an `erc-status-sidebar' window instead of a
+separate frame.  When disabling, close the window or, with a
+negative prefix arg, destroy the session.
+
+WARNING: it's suspected that this module may perform unwanted
+side effects like raising frames and/or stealing input focus.  If
+you witness such an occurrence, and can reproduce it, please file
+a bug report with \\[erc-bug]."
+  ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (erc-speedbar--ensure)
+   (unless (or erc--updating-modules-p
+               (and-let* ((speedbar-buffer)
+                          (win (get-buffer-window speedbar-buffer 'all-frames))
+                          ((eq speedbar-frame (window-frame win))))))
+     (if speedbar-buffer
+         (erc-speedbar--ensure 'force)
+       (cl-assert (not (derived-mode-p 'erc-mode)))
+       (setq erc-nickbar-mode nil)
+       (user-error "Cannot initialize `%s' in a non-ERC buffer"
+                   'erc-nickbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (speedbar-disable-update)
+   (erc-speedbar--toggle-nicknames-sidebar -1)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-speedbar-close-nicknames-window 'kill))))
+
+(defun erc-speedbar--dframe-controlled (arg)
+  (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
+    (when erc-nickbar-mode
+      (erc-nickbar-mode -1))
+    (setq speedbar-frame erc-speedbar--hidden-speedbar-frame
+          erc-speedbar--hidden-speedbar-frame nil)
+    ;; It's unknown whether leaving the frame invisible interferes
+    ;; with the upstream teardown procedure.
+    (when (display-graphic-p)
+      (make-frame-visible speedbar-frame))
+    (speedbar-frame-mode arg)
+    (when speedbar-buffer
+      (kill-buffer speedbar-buffer)
+      (setq speedbar-buffer nil))))
+
+(defun erc-speedbar-toggle-nicknames-window-lock ()
+  "Toggle whether nicknames window is selectable with \\[other-window]."
+  (interactive)
+  (unless erc-nickbar-mode
+    (user-error "`erc-nickbar-mode' inactive"))
+  (when-let* ((window (get-buffer-window speedbar-buffer)))
+    (let ((val (window-parameter window 'no-other-window)))
+      (set-window-parameter window 'no-other-window (not val))
+      (message "nick-window: %s" (if val "selectable" "protected")))))
+
+(defun erc-speedbar-close-nicknames-window (kill)
+  (interactive "P")
+  (if kill
+      (with-current-buffer speedbar-buffer
+        (dframe-close-frame)
+        (cl-assert (not erc-nickbar-mode))
+        (setq erc-speedbar--hidden-speedbar-frame nil))
+    (dolist (window (get-buffer-window-list speedbar-buffer nil t))
+      (unless (frame-root-window-p window)
+        (when erc-speedbar--hidden-speedbar-frame
+          (cl-assert (not (eq (window-frame window)
+                              erc-speedbar--hidden-speedbar-frame))))
+        (delete-window window)))))
+
+
+;;;; Nicks integration
+
+(defvar erc-nicks--phony-face)
+(declare-function erc-nicks--highlight "erc-nicks" (nick-object))
+
+(defun erc-speedbar--compose-nicks-face (orig buffer user cuser)
+  (require 'erc-nicks)
+  (let ((rv (funcall orig buffer user cuser)))
+    (if-let* ((nobj (make-erc-button--nick
+                     :downcased (erc-downcase (erc-server-user-nickname user))
+                     :user user
+                     :cuser cuser))
+              (erc-nicks--phony-face (or rv t))
+              (nobj (with-current-buffer buffer
+                      (erc-nicks--highlight nobj)))
+              (face (erc-button--nick-erc-button-nickname-face nobj))
+              ((not (eq face erc-button-nickname-face))))
+        (cons face (ensure-list rv))
+      rv)))
+
+
 (provide 'erc-speedbar)
 ;;; erc-speedbar.el ends here
 ;;
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index aec61333e0b..6ac1821ebb7 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -90,4 +90,80 @@ erc-scenarios-status-sidebar--bufbar
         (erc-status-sidebar-kill)
         (should-not (get-buffer "*ERC Status*"))))))
 
+;; No need to pollute the global obarray since we can't currently run
+;; this on EMBA (it requires a terminal).  Please try running this
+;; test interactively with both graphical Emacs and non.
+(declare-function erc-nickbar-mode "erc-speedbar" (arg))
+(declare-function erc-speedbar-close-nicknames-window "erc-speedbar" (kill))
+(declare-function speedbar-timer-fn "speedbar" nil)
+(defvar erc-nickbar-mode)
+(defvar speedbar-buffer)
+
+(ert-deftest erc-scenarios-status-sidebar--nickbar ()
+  :tags '(:unstable :expensive-test)
+  (when noninteractive (ert-skip "Interactive only"))
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(nickbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#bar"))
+    (with-current-buffer (pop-to-buffer "#bar")
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit")
+      (erc-d-t-wait-for 10 (and speedbar-buffer (get-buffer speedbar-buffer)))
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#bar (3)")
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 "tester")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#foo"))
+    (with-current-buffer (pop-to-buffer "#foo")
+      (delete-other-windows)
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#foo (3)")
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 "tester")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (erc-nickbar-mode -1)
+        (should-not (and speedbar-buffer
+                         (get-buffer-window speedbar-buffer)))
+        (erc-nickbar-mode +1)
+        (should (and speedbar-buffer
+                     (get-buffer-window speedbar-buffer)))
+        (should (get-buffer " SPEEDBAR"))
+        (erc-speedbar-close-nicknames-window 'kill)
+        (should-not (get-buffer " SPEEDBAR"))
+        (should-not erc-nickbar-mode)
+        (should-not (cdr (frame-list)))))))
+
 ;;; erc-scenarios-status-sidebar.el ends here
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0005-5.6-Add-new-ERC-modules-bufbar-and-nickbar.patch

From 93f31ce4e062acd8ea6e87ea8023707b9e4b383b Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 5/5] [5.6] Add new ERC modules bufbar and nickbar

* doc/misc/erc.texi: Add `bufbar' and `nickbar' to known modules.
* erc/ERC-NEWS: Mention erc-status-sidebar and erc-speedbar
improvements.
* lisp/erc/erc.el (erc-modules): Add `bufbar' and `nickbar' to
selection of offered modules.
* test/lisp/erc/erc-tests.el (erc-tests--modules): Add `bufbar' and
`nickbar'.
---
 doc/misc/erc.texi          |  9 +++++++++
 etc/ERC-NEWS               | 16 ++++++++++++++++
 lisp/erc/erc.el            |  2 ++
 test/lisp/erc/erc-tests.el |  4 ++--
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index f7036e57638..7c625c2fd02 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -418,6 +418,10 @@ Modules
 @item bbdb
 Integrate with the Big Brother Database
 
+@cindex modules, bufbar
+@item bufbar
+List ERC buffers belonging to a live connection in a side window
+
 @cindex modules, button
 @item button
 Buttonize URLs, nicknames, and other text
@@ -463,6 +467,11 @@ Modules
 @item nicks
 Automatically colorize nicks
 
+@cindex modules, nickbar
+@item nickbar
+List participating nicks for the current target buffer in a side
+window
+
 @cindex modules, noncommands
 @item noncommands
 Don't display non-IRC commands after evaluation
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 41af8b88277..6922ae22482 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -72,6 +72,22 @@ widget has been an age-old annoyance for new users.  Previously
 ineffective, this method now actually works, but it also admonishes
 users to edit the 'erc-modules' widget instead.
 
+** ERC's status-sidebar now has an accompanying module.
+Users can now add 'bufbar' to 'erc-modules' to achieve the same effect
+as toggling 'erc-status-sidebar-open' manually at the start of an IRC
+session.  The module has also been outfitted to show channels and
+queries under their respective servers by default.  To avoid
+confusion, the major mode used for the sidebar buffer itself,
+'erc-status-sidebar-mode', is no longer available interactively.
+
+** A new spin on a classic integration in erc-speedbar.
+Add 'nickbar' to 'erc-modules' to spawn a dynamically updating side
+window listing all the users in any target buffer.  It's powered by
+the same speedbar.el integration you've always known, except this
+one's optionally accessible from the keyboard, just like any other
+side window.  Hit '<RET>' over a nick to spawn a "/QUERY" or a
+"Lastlog" (Occur) session.  See 'erc-nickbar-mode' for more.
+
 ** The option 'erc-timestamp-use-align-to' is more versatile.
 While this option has always offered to right-align stamps via the
 'display' text property, it's now more effective at doing so when set
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 5a3b312b53b..2f26985f74d 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2006,6 +2006,7 @@ erc-modules
     :greedy t
     (const :tag "autoaway: Set away status automatically" autoaway)
     (const :tag "autojoin: Join channels automatically" autojoin)
+    (const :tag "bufbar: Show ERC buffers in a side window" bufbar)
     (const :tag "button: Buttonize URLs, nicknames, and other text" button)
     (const :tag "capab: Mark unidentified users on servers supporting CAPAB"
            capab-identify)
@@ -2026,6 +2027,7 @@ erc-modules
            move-to-prompt)
     (const :tag "netsplit: Detect netsplits" netsplit)
     (const :tag "networks: Provide data about IRC networks" networks)
+    (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar)
     (const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks)
     (const :tag "noncommands: Don't display non-IRC commands after evaluation"
            noncommands)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index de472527bde..4432dc58082 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1951,9 +1951,9 @@ erc-handle-irc-url
     (kill-buffer "#chan")))
 
 (defconst erc-tests--modules
-  '( autoaway autojoin button capab-identify completion dcc fill identd
+  '( autoaway autojoin bufbar button capab-identify completion dcc fill identd
      imenu irccontrols keep-place list log match menu move-to-prompt netsplit
-     networks nicks noncommands notifications notify page readonly
+     networks nickbar nicks noncommands notifications notify page readonly
      replace ring sasl scrolltobottom services smiley sound
      spelling stamp track truncate unmorse xdcc))
 
-- 
2.40.0


--=-=-=--




Message sent:


Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-Mailer: MIME-tools 5.505 (Entity 5.505)
Content-Type: text/plain; charset=utf-8
X-Loop: help-debbugs@HIDDEN
From: help-debbugs@HIDDEN (GNU bug Tracking System)
To: "J.P." <jp@HIDDEN>
Subject: bug#63595: Acknowledgement (30.0.50; ERC 5.6: Add buffer-list and
 nick-list modules)
Message-ID: <handler.63595.B.168452435416678.ack <at> debbugs.gnu.org>
References: <87lehkt97a.fsf@HIDDEN>
X-Gnu-PR-Message: ack 63595
X-Gnu-PR-Package: emacs
X-Gnu-PR-Keywords: patch
Reply-To: 63595 <at> debbugs.gnu.org
Date: Fri, 19 May 2023 19:26:02 +0000

Thank you for filing a new bug report with debbugs.gnu.org.

This is an automatically generated reply to let you know your message
has been received.

Your message is being forwarded to the package maintainers and other
interested parties for their attention; they will reply in due course.

As you requested using X-Debbugs-CC, your message was also forwarded to
  emacs-erc@HIDDEN
(after having been given a bug report number, if it did not have one).

Your message has been sent to the package maintainer(s):
 bug-gnu-emacs@HIDDEN

If you wish to submit further information on this problem, please
send it to 63595 <at> debbugs.gnu.org.

Please do not send mail to help-debbugs@HIDDEN unless you wish
to report a problem with the Bug-tracking system.

--=20
63595: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D63595
GNU Bug Tracking System
Contact help-debbugs@HIDDEN with problems


Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Fri, 19 May 2023 20:49:01 +0000
Resent-Message-ID: <handler.63595.B63595.168452929426074 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.168452929426074
          (code B ref 63595); Fri, 19 May 2023 20:49:01 +0000
Received: (at 63595) by debbugs.gnu.org; 19 May 2023 20:48:14 +0000
Received: from localhost ([127.0.0.1]:57502 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1q071J-0006mR-SC
	for submit <at> debbugs.gnu.org; Fri, 19 May 2023 16:48:14 -0400
Received: from mail-108-mta134.mxroute.com ([136.175.108.134]:39343)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1q071H-0006lZ-2q
 for 63595 <at> debbugs.gnu.org; Fri, 19 May 2023 16:48:11 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta134.mxroute.com (ZoneMTA) with ESMTPSA id
 18835c503d300074ee.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);
 Fri, 19 May 2023 20:48:04 +0000
X-Zone-Loop: 43d1da637cfe96d7c85839160dd2ebaeb2f60b0687d3
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=zb7WkyPvdnUCFH1zeZ3qsSF1uRQXSHrUxZDR5t/wL1U=; b=VP7Dy1R4RfiZwWHwrWouAeKqND
 gjXgMZ5pE+uD+g9L+MBO1dAhtuWnsRJRO+VfOGRLzSTR5ICQIFF0q+chsSEEyDJMoWhttDHYMk71f
 vc3m7byxQnpizubTcE6wCJN7UGg+huPxZsizprsht7/9TJf+Z4k5+e5sf2mzoBpk8QvDzKhk66GTD
 Z+KXxhd8T9VrMrIkEcrKWEPFnM5IgUU3YrTN/Pq29KB6U/9eQmvRz6RwMCWqmzLAV4laIm4IO+VU0
 wM8wk+Kzq4GBcDaGPtu9Tn2KGSKCtNCQbl0REgnVinwvkHUmUzTl2EaZmMtVHIFNR/8hBW4o5uxri
 XWrYUhYg==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Fri, 19 May 2023 13:47:59 -0700
Message-ID: <874jo8t5ds.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Screenshots (modus themed but otherwise vanilla):

graphical:

  https://debbugs.gnu.org/cgi/bugreport.cgi?filename=erc-sidebar-graphical.png;bug=63595;att=1;msg=6

terminal:

  https://debbugs.gnu.org/cgi/bugreport.cgi?msg=6;att=2;filename=erc-sidebar-terminal.png;bug=63595




Message sent:


MIME-Version: 1.0
X-Mailer: MIME-tools 5.505 (Entity 5.505)
X-Loop: help-debbugs@HIDDEN
From: help-debbugs@HIDDEN (GNU bug Tracking System)
To: "J.P." <jp@HIDDEN>
Subject: bug#63595: closed (30.0.50; ERC 5.6: Add buffer-list and
 nick-list modules)
CC: tracker <at> debbugs.gnu.org
Message-ID: <handler.63595.D63595.16893004792640.ackdone <at> debbugs.gnu.org>
References: <87r0pbs0st.fsf@HIDDEN> <87lehkt97a.fsf@HIDDEN>
X-Gnu-PR-Message: closed 63595
X-Gnu-PR-Package: emacs
X-Gnu-PR-Keywords: patch
Date: Fri, 14 Jul 2023 02:08:02 +0000
Content-Type: multipart/mixed; boundary="----------=_1689300482-2649-0"

This is a multi-part message in MIME format...

------------=_1689300482-2649-0
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=utf-8

Your message dated Thu, 13 Jul 2023 19:07:46 -0700
with message-id <87r0pbs0st.fsf@HIDDEN>
and subject line Re: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-=
list modules
has caused the debbugs.gnu.org bug report #63595,
regarding 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
to be marked as done.

(If you believe you have received this mail in error, please contact
help-debbugs@HIDDEN)


--=20
63595: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D63595
GNU Bug Tracking System
Contact help-debbugs@HIDDEN with problems

------------=_1689300482-2649-0
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Received: (at submit) by debbugs.gnu.org; 19 May 2023 19:25:54 +0000
Received: from localhost ([127.0.0.1]:57435 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1q05ja-0004Kr-HF
	for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:53 -0400
Received: from lists.gnu.org ([209.51.188.17]:54098)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1q05jV-0004Ke-Se
 for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:49 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jV-0003yx-Ey
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-108-mta11.mxroute.com ([136.175.108.11])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jO-0005YW-Nz
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta11.mxroute.com (ZoneMTA) with ESMTPSA id 1883579758200074ee.001
 for <bug-gnu-emacs@HIDDEN>
 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);
 Fri, 19 May 2023 19:25:32 +0000
X-Zone-Loop: eec7dda6ba983e849cec5c7021dd9f3b963fa6e4e9fe
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=reOVYRocD84tqZU6Afp4MUToMaIkxYinxEkfAKJ6TEQ=; b=JWB0abbAfp98Slzy+ZQWJUY2pv
 tEBXPa65Rq/NP6nB1fU6/+hHUBsUtheeb5MoQVHR40jzE+eJhe4Dmv0UOfn+m62bNxe1VW1uuUlmT
 XAB1AwzSXVoCNW+V9WXYxY8kGncTwAzfmF5YHkTf+Q4YjJjlLPWtT5xmDbfKULqII4R19v6/uNGB1
 JA8JrJqdIuN/fGcYwR7e8K1XSdoFHWTtNhDWfEE+J47GN2USEtY43xp1QpI3Qkkt8gGB1dDlh6vYo
 FrMkk24HC5++Og2JpEzxk0pyTzZoghmB+FBth71ZF8qjTluwptnYhxjEHyknC0vteueMkPqXTVRaj
 NVDIEzCw==;
From: "J.P." <jp@HIDDEN>
To: bug-gnu-emacs@HIDDEN
Subject: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
X-Debbugs-CC: emacs-erc@HIDDEN
Date: Fri, 19 May 2023 12:25:29 -0700
Message-ID: <87lehkt97a.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
Received-SPF: pass client-ip=136.175.108.11; envelope-from=jp@HIDDEN;
 helo=mail-108-mta11.mxroute.com
X-Spam_score_int: -20
X-Spam_score: -2.1
X-Spam_bar: --
X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001,
 SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: -1.4 (-)
X-Debbugs-Envelope-To: submit
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -2.4 (--)

--=-=-=
Content-Type: text/plain

Tags: patch
Severity: wishlist

(This bug could just as well be titled "Make ERC look more like
standalone clients," although that's perhaps a bit clickbaity.)


Hi,

Newcomers to ERC are occasionally dumbfounded by the absence of a
certain pair of IRC essentials, namely, a "window list" and a "nicknames
list." But what even existing users may not know is that ERC already has
both; they just don't quite work the way folks coming from other clients
might expect. This patch aims to address that as if it were a problem.

What's being proposed here is the addition of two new modules built
entirely on functionality already offered by their host libraries,
erc-status-sidebar.el and erc-speedbar.el. What's different is these
additions flirt with something somewhat verboten in ERC, and that's
changing existing defaults for non-security reasons (in this case,
chiefly for unifying UX [1]). Beyond that, these changes also hard-wire
potentially offensive choices into some of these defaults while trying
in earnest to ensure old behavior remains accessible. For example, one
module assumes no one with a non-nil `erc-header-line-format' has any
use for modes and topics in a side window. Other baked in preferences
include the nixing of all throwback icons [2] and the showing of
disconnected buffers in a muted face. The list goes on but is open for
discussion, as always.

Another consideration here is of course naming [3]. I've gone ahead and
dubbed the speedbar module 'nickbar' as a bit of an homage to its roots.
`nicklist' wasn't available because a popular module of that name was
once part of ERC, and people still use it today. For status-sidebar, I
went with `bufbar', in part for consistency but also because the
would-be canonical "status-sidebar" is already taken by the side
window's buffer for its major mode. We might also consider going with
the slightly pedestrian `buflist', which is already used by at least one
other IRC client for referring to this feature.

Lastly, I'd like to stress that these modules (thankfully) won't be
loaded by default, which means you'll need to add `bufbar' and `nickbar'
to `erc-modules' when trying them out. Note that this patch set
currently depends on bug#63569 [3], whose changes need applying
beforehand.

Thanks!


[1] My justifications for taking such liberties are at best anecdotal,
    based mostly on personal impressions of prevailing usage patterns
    and the perceived motivations behind them. A few examples:

    a. The relative newness of erc-status-sidebar.el, its lack of an
       associated module, and its absence from ERC's Custom menu all
       point to its defaults being somewhat more free for the changing.
       The speedbar integration likewise lacks a module, and its
       graphical-only nature means its set of users currently excludes
       anyone using ERC from a terminal. (Less expected fallout from the
       proposed churn, IOW.)

    b. Both libraries provide an always-open side window (or, in
       speedbar's case, frame), which imposes a specific layout on the
       user, something that's relatively rare in Emacs outside of
       IDE-style modes. Compare this to something like ibuffer for
       listing buffers or a hypothetical /NAMES buffer, which, if based
       on `tabulated-list-mode', would make for a more familiar means of
       reviewing channel members. The point here is that devoted users
       likely aren't messing with erc-status-sidebar or erc-speedbar in
       droves, preferring more Emacsy alternatives instead.

    c. Newcomers can't be bothered with an overly involved setup if it
       requires carefully exploring options before trying. But they're
       perfectly willing to copy/paste gobs of configuration or even
       mindlessly follow a minutes long Customize itinerary, so long as
       the promise of emerging with something resembling their present
       idea of what makes an IRC client remains within reach. By
       introducing these modules "preconfigured," I'm positing that
       these preconceived notions typically include a reactive window
       list and/or nick list. That said, my hope is that these users
       will eventually gravitate toward the more Emacs-native way of
       doing things, at which point these modules will have served their
       primary purpose (of acting as bait).

[2] My reason for 86'ing the icons outright in the speedbar's new
    "window mode" is consistency. I figure anyone who wants the vanilla
    experience wants it in full and thus also wants a separate frame.
    That said, I suppose we could add a knob for tweaking this (or any
    of the other hard-coded choices mentioned), but IMO doing that
    unprovoked just contributes to "options sprawl."

[3] FWIW, all module names in contention flout our supposed policy of
    preferring those that align with host libraries and the features
    they `provide'.


In GNU Emacs 30.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version
 3.24.37, cairo version 1.17.6) of 2023-05-13 built on localhost
Repository revision: 867b104010760c4b7cd700078884cc774a01860a
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12014000
System Description: Fedora Linux 37 (Workstation Edition)

Configured using:
 'configure --enable-check-lisp-object-type --enable-checking=yes,glyphs
 'CFLAGS=-O0 -g3'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util text-property-search time-date mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils erc auth-source cl-seq
eieio eieio-core cl-macs password-cache json subr-x map format-spec
cl-loaddefs cl-lib erc-backend erc-networks byte-opt gv bytecomp
byte-compile erc-common erc-compat erc-loaddefs rmc iso-transl tooltip
cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd
fontset image regexp-opt fringe tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 64236 9476)
 (symbols 48 8573 0)
 (strings 32 23246 1709)
 (string-bytes 1 674076)
 (vectors 16 15015)
 (vector-slots 8 207266 8159)
 (floats 8 24 33)
 (intervals 56 229 0)
 (buffers 976 10))

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Fix-buffer-mismatch-bug-in-erc-scroll-to-bottom.patch

From 4a1bd9e173d91164d5abe6f2e349a447eaf019d7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 17 May 2023 19:48:02 -0700
Subject: [PATCH 1/5] [5.6] Fix buffer-mismatch bug in erc-scroll-to-bottom

* lisp/erc/erc-goodies.el (erc-scroll-to-bottom): Only `recenter' when
the selected window's buffer is current.  Previously, the module
`scrolltobottom' signaled an "Error in `post-command-hook'" when a
user clicked a channel indicator in the mode line from a window
showing another ERC buffer.
---
 lisp/erc/erc-goodies.el | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 01eae4b63c5..87c95778523 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -92,6 +92,7 @@ erc-scroll-to-bottom
     (save-restriction
       (widen)
       (when (and erc-insert-marker
+                 (eq (current-buffer) (window-buffer))
 		 ;; we're editing a line. Scroll.
 		 (> (point) erc-insert-marker))
 	(save-excursion
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0002-5.6-Allow-ERC-s-module-toggles-access-to-the-prefix-.patch

From 5ae05b1ad34ce1baea149c7af1e9e9282f101725 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Mon, 15 May 2023 00:16:00 -0700
Subject: [PATCH 2/5] [5.6] Allow ERC's module toggles access to the prefix arg

* lisp/erc/erc-common.el (erc--module-toggle-prefix-arg): Add internal
variable for preserving the `arg' passed to a module's minor-mode
toggle, which was previously discarded.  Doing this lets modules that
are more interactive in nature overload their mode toggles with
alternate behaviors.
(define-erc-module): Bind `erc--module-toggle-prefix-arg' to the `arg'
parameter, which is normally defined inside a `define-minor-mode' body
form.
* test/lisp/erc/erc-tests.el (define-erc-module--global,
define-erc-module--local): Expect activation body to be wrapped by a
let form binding `erc--module-toggle-prefix-arg'.
---
 lisp/erc/erc-common.el     | 14 +++++++++++---
 test/lisp/erc/erc-tests.el | 14 ++++++++------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index f152a1a32d9..dd39b30c4db 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -289,6 +289,15 @@ erc--find-feature
              (intern (file-name-base file))))
      (v v)))
 
+(defvar erc--module-toggle-prefix-arg nil
+  "The interpreted prefix arg of the minor-mode toggle.
+Non-nil inside an ERC module's activation (or deactivation)
+command, such as `erc-spelling-enable', when it's been called
+indirectly via the module's minor-mode toggle, i.e.,
+`erc-spelling-mode'.  Nil otherwise.  Its value is either the
+symbol `toggle' or an integer produced by `prefix-numeric-value'.
+See Info node `(elisp) Defining Minor Modes' for more.")
+
 (defmacro define-erc-module (name alias doc enable-body disable-body
                                   &optional local-p)
   "Define a new minor mode using ERC conventions.
@@ -337,9 +346,8 @@ define-erc-module
          :group (erc--find-group ',name ,(and alias (list 'quote alias)))
          ,@(unless local-p `(:require ',(erc--find-feature name alias)))
          ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name)))
-         (if ,mode
-             (,enable)
-           (,disable)))
+         (let ((erc--module-toggle-prefix-arg arg))
+           (if ,mode (,enable) (,disable))))
        ,(erc--assemble-toggle local-p name enable mode t enable-body)
        ,(erc--assemble-toggle local-p name disable mode nil disable-body)
        ,@(and-let* ((alias)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 991bfa3b082..de472527bde 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -2175,9 +2175,10 @@ define-erc-module--global
                         :group (erc--find-group 'mname 'malias)
                         :require 'nil
                         :type "mname"
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable ()
                         "Enable ERC mname mode."
@@ -2230,9 +2231,10 @@ define-erc-module--local
 Some docstring."
                         :global nil
                         :group (erc--find-group 'mname nil)
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable (&optional ,arg-en)
                         "Enable ERC mname mode.
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0003-5.6-Add-preset-styles-to-erc-status-sidebar.patch

From c4746e4bb3fde7670bd655ed7f17ec90435018ac Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 3/5] [5.6] Add preset styles to erc-status-sidebar

* lisp/erc/erc-networks.el (erc-networks--rename-server-buffer): Store
`erc-networks--id' in process object's plist.
* lisp/erc/erc-status-sidebar.el (erc-status-sidebar): Change parent
from `convenience' to `erc'.
(erc-status-sidebar-channel-format):
Mention in doc string that it depends on new option
`erc-status-sidebar-style'.
(erc-status-sidebar-highlight-active-buffer): New option to control
whether the current window's target is highlighted in the status bar.
(erc-status-sidebar-style): New option to determine whether servers
and queries also appear in the sidebar.
(erc-status-sidebar-click-display-action,
erc-status-sidebar-singular): New options.
(erc-status-sidebar-get-window): Consider
`erc-status-sidebar-singular'.
(erc-status-sidebar-open): Fix toggle functionality that somehow fell
through the cracks after the adoption of the package into ERC proper.
(erc-buflist-mode, erc-buflist-enable, erc-buflist-disable): New
module named `buflist' instead of `sidebar', which is more easily
confusable with `speedbar'.  The preferred name, `status-sidebar' was
unavailable because its minor-mode would have been
`erc-status-sidebar-mode', which is already taken by the major mode
used for status-bar buffers themselves.
(erc-status-sidebar-toggle): Ignore `erc-status-sidebar-singular'.
(erc-status-sidebar--trimpat, erc-status-sidebar--prechan): Add helper
vars for new sorting function, allowing it to honor the existing
interface, which only expects one argument.
(erc-status-sidebar-prefer-target-as-name): New function for
determining buffer name, preferring targets for target buffers.
(erc-status-sidebar-get-channame): Use internal API to help determine
name of buffer in sidebar.
(erc-status-sidebar-prefer-target-as-name,
erc-status-sidebar--show-disconnected,
erc-status-sidebar-all-target-buffers,
erc-status-sidebar-default-allsort): Add new naming and sorting
functions and associated helper functions and variables.
(erc-status-sidebar--active-marker,
erc-status-sidebar--set-active-line): New variable and function for
highlighting the active target in the status bar.
(erc-status-sidebar-default-insert,
erc-status-sidebar-pad-hierarchy): New functions for visiting various
stages of buffer modification when rendering sidebar.
(erc-status-sidebar-click): Appeal to option
`erc-status-sidebar-display-action' for `pop-to-buffer' action.
(erc-status-sidebar-scroll-up, erc-status-sidebar-scroll-down,
erc-status-sidebar-recenter): Add commands to scroll and
recenter sidebar from a target buffer's window.
(erc-status-sidebar-refresh): Consider presets and new options when
rendering sidebar.  Disable `erc-buflist-mode' when active.
(erc-status-sidebar-set-window-preserve-size): Ignore
`erc-status-sidebar-singular'.
(erc-status-sidebar-mode): Make non-interactive to avoid confusion
when folks run "M-x erc-status-sidebar-mode" expecting a module
toggle.
* test/lisp/erc/erc-scenarios-status-sidebar.el: New file.
* test/lisp/erc/resources/base/gapless-connect/foonet.eld: Fix wrong
manifest for channel and extend PASS timeout.
---
 lisp/erc/erc-networks.el                      |   1 +
 lisp/erc/erc-status-sidebar.el                | 328 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  93 +++++
 .../resources/base/gapless-connect/foonet.eld |   8 +-
 4 files changed, 400 insertions(+), 30 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-status-sidebar.el

diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index dd481032e7e..60d76d059da 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1459,6 +1459,7 @@ erc-networks--rename-server-buffer
          ;; When this ends up being the current buffer, either we have
          ;; a "given" ID or the buffer was reused on reconnecting.
          (existing (get-buffer name)))
+    (process-put new-proc 'erc-networks--id erc-networks--id)
     (cond ((or (not existing)
                (erc-networks--id-given erc-networks--id)
                (eq existing (current-buffer)))
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index f11faa3db10..c06ba53f3ae 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -45,6 +45,13 @@
 ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and
 ;; close the sidebar on all frames.
 
+;; In addition to the commands above, you can also try the all-in-one,
+;; "DWIM" command, `erc-bufbar-mode'.  See its doc string for usage.
+
+;; If you want the status sidebar enabled whenever you use ERC, add
+;; `bufbar' to `erc-modules'.  Note that this library also has a major
+;; mode, `erc-status-sidebar-mode', which is for internal use.
+
 ;;; Code:
 
 (require 'erc)
@@ -53,8 +60,15 @@
 (require 'seq)
 
 (defgroup erc-status-sidebar nil
-  "A sidebar for ERC channel status."
-  :group 'convenience)
+  "A responsive side window listing all connected ERC buffers.
+More commonly known as a window list or \"buflist\", this side
+panel displays clickable buffer names for switching to with the
+mouse.  By default, ERC highlights the name corresponding to the
+selected window's buffer, if any.  Here, \"connected buffer\"
+means one belonging to a session context for a server that ERC is
+currently communicating with.  For information on how the window
+itself works, see Info node `(elisp) Side Windows'."
+  :group 'erc)
 
 (defcustom erc-status-sidebar-buffer-name "*ERC Status*"
   "Name of the sidebar buffer."
@@ -80,9 +94,78 @@ erc-status-sidebar-channel-sort
 
 (defcustom erc-status-sidebar-channel-format
   'erc-status-sidebar-default-chan-format
-  "Function used to format channel names for display in the sidebar."
+  "Function used to format channel names for display in the sidebar.
+Only consulted for certain values of `erc-status-sidebar-style'."
   :type 'function)
 
+(defcustom erc-status-sidebar-highlight-active-buffer t
+  "Whether to highlight the selected window's buffer in the sidebar.
+ERC uses the same instance across all frames.  May not be
+compatible with all values of `erc-status-sidebar-style'."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defcustom erc-status-sidebar-style 'all-queries-first
+  "Preset style for rendering the sidebar.
+
+When set to `channels-only', ERC limits the items in the
+status bar to uniquified channels.  It uses the options
+and functions
+
+  `erc-channel-list',
+  `erc-status-sidebar-channel-sort',
+  `erc-status-sidebar-get-channame',
+  `erc-status-sidebar-channel-format'
+  `erc-status-sidebar-default-insert'
+
+for selecting, formatting, naming, and inserting entries.  When
+set to one of the various \\=`all-*' values, such as `all-mixed',
+ERC shows channels and queries under their respective server
+buffers, using the functions
+
+  `erc-status-sidebar-all-target-buffers',
+  `erc-status-sidebar-default-allsort',
+  `erc-status-sidebar-prefer-target-as-name',
+  `erc-status-sidebar-default-chan-format',
+  `erc-status-sidebar-pad-hierarchy'
+
+for the above-mentioned purposes.  ERC also accepts a list of
+functions to preform these roles a la carte.  See doc strings for
+a description of their expected arguments and return values."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const channels-only)
+                 (const all-mixed)
+                 (const all-queries-first)
+                 (const all-channels-first)
+                 (list (function :tag "Buffer lister")
+                       (function :tag "Buffer sorter")
+                       (function :tag "Name extractor")
+                       (function :tag "Name formatter")
+                       (function :tag "Name inserter"))))
+
+(defcustom erc-status-sidebar-click-display-action t
+  "How to display a buffer when clicked.
+Values can be anything recognized by `display-buffer' for its
+ACTION parameter."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const :tag "Always use/create other window" t)
+                 (const :tag "Let `display-buffer' decide" nil)
+                 (const :tag "Same window" (display-buffer-same-window
+                                            (inhibit-same-window . nil)))
+                 (cons :tag "Action"
+                       (choice function (repeat function))
+                       (alist :tag "Action arguments"
+                              :key-type symbol
+                              :value-type (sexp :tag "Value")))))
+
+(defcustom erc-status-sidebar-singular t
+  "Whether to show the sidebar on all frames or just one (default)."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defvar hl-line-mode)
+(declare-function hl-line-highlight "hl-line" nil)
+
 (defun erc-status-sidebar-display-window ()
   "Display the status buffer in a side window.  Return the new window."
   (display-buffer
@@ -94,7 +177,8 @@ erc-status-sidebar-get-window
   "Return the created/existing window displaying the status buffer.
 
 If NO-CREATION is non-nil, the window is not created."
-  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name)))
+  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name
+                                           erc-status-sidebar-singular)))
     (unless (or sidebar-window no-creation)
       (with-current-buffer (erc-status-sidebar-get-buffer)
         (setq-local vertical-scroll-bar nil))
@@ -144,22 +228,50 @@ erc-status-sidebar-open
   "Open or create a sidebar."
   (interactive)
   (save-excursion
-    (let ((sidebar-exists (erc-status-sidebar-buffer-exists-p))
-          (sidebar-buffer (erc-status-sidebar-get-buffer))
-          ;; (sidebar-window (erc-status-sidebar-get-window))
-          )
-      (unless sidebar-exists
-        (with-current-buffer sidebar-buffer
-          (erc-status-sidebar-mode)
-          (erc-status-sidebar-refresh))))))
+    (if (erc-status-sidebar-buffer-exists-p)
+        (erc-status-sidebar-get-window)
+      (with-current-buffer (erc-status-sidebar-get-buffer)
+        (erc-status-sidebar-mode)
+        (erc-status-sidebar-refresh)))))
+
+;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t)
+(define-erc-module bufbar nil
+  "Show `erc-track'-like activity in a side window.
+When enabling, show the sidebar immediately if called from a
+connected ERC buffer.  Otherwise, arrange for doing so on connect
+or whenever next displaying a new ERC buffer.  When disabling,
+hide the status window if it's showing.  With a negative prefix
+arg, also shutdown the session."
+  ((unless erc-track-mode
+     (unless (memq 'track erc-modules)
+       (erc--warn-once-before-connect 'erc-bufbar-mode
+         "Module `bufbar' needs global module `track'. Enabling now."
+         " This will affect \C-]all\C-] ERC sessions."
+         " Add `track' to `erc-modules' to silence this message."))
+     (erc-track-mode +1))
+   (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (unless erc--updating-modules-p
+     (if (erc-with-server-buffer erc-server-connected)
+         (erc-status-sidebar-open)
+       (setq erc-bufbar-mode nil)
+       (user-error "`%s' not called from a connected ERC buffer."
+                   'erc-bufbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (erc-status-sidebar-close erc-status-sidebar-singular)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-status-sidebar-kill))))
 
 ;;;###autoload
 (defun erc-status-sidebar-toggle ()
-  "Toggle the sidebar open/closed on the current frame."
+  "Toggle the sidebar open/closed on the current frame.
+Do this regardless of `erc-status-sidebar-singular'."
   (interactive)
   (if (get-buffer-window erc-status-sidebar-buffer-name nil)
       (erc-status-sidebar-close)
-    (erc-status-sidebar-open)))
+    (let (erc-status-sidebar-singular)
+      (erc-status-sidebar-open))))
 
 (defun erc-status-sidebar-get-channame (buffer)
   "Return name of BUFFER with all leading \"#\" characters removed."
@@ -174,6 +286,98 @@ erc-status-sidebar-default-chansort
                    (string< (erc-status-sidebar-get-channame x)
                             (erc-status-sidebar-get-channame y)))))
 
+(defvar erc-status-sidebar--trimpat nil)
+(defvar erc-status-sidebar--prechan nil)
+
+(defun erc-status-sidebar-prefer-target-as-name (buffer)
+  "Return some name to represent buffer in the sidebar."
+  (if-let ((target (buffer-local-value 'erc--target buffer)))
+      (cond ((and erc-status-sidebar--trimpat (erc--target-channel-p target))
+             (string-trim-left (erc--target-string target)
+                               erc-status-sidebar--trimpat))
+            ((and erc-status-sidebar--prechan (erc--target-channel-p target))
+             (concat erc-status-sidebar--prechan
+                     (erc--target-string target)))
+            (t (erc--target-string target)))
+    (buffer-name buffer)))
+
+;; This could be converted into an option if people want.
+(defvar erc-status-sidebar--show-disconnected t)
+
+(defun erc-status-sidebar-all-target-buffers (process)
+  (erc-buffer-filter (lambda ()
+                       (and erc--target
+                            (or erc-status-sidebar--show-disconnected
+                                (erc-server-process-alive))))
+                     process))
+
+;; FIXME profile this.  Rebuilding the graph every time track updates
+;; seems wasteful for occasions where server messages are processed
+;; unthrottled, such as during history playback.  If it's a problem,
+;; we should look into rewriting this using `ewoc' or some other
+;; solution that maintains a persistent model.
+(defun erc-status-sidebar-default-allsort (target-buffers)
+  "Return a list of servers interspersed with their targets."
+  (mapcan (pcase-lambda (`(,proc . ,chans))
+            (cons (process-buffer proc)
+                  (let ((erc-status-sidebar--trimpat
+                         (and (eq erc-status-sidebar-style 'all-mixed)
+                              (with-current-buffer (process-buffer proc)
+                                (when-let ((ch-pfxs (erc--get-isupport-entry
+                                                     'CHANTYPES 'single)))
+                                  (regexp-quote ch-pfxs)))))
+                        (erc-status-sidebar--prechan
+                         (and (eq erc-status-sidebar-style
+                                  'all-queries-first)
+                              "\C-?")))
+                    (sort chans
+                          (lambda (x y)
+                            (string<
+                             (erc-status-sidebar-prefer-target-as-name x)
+                             (erc-status-sidebar-prefer-target-as-name y)))))))
+          (sort (seq-group-by (lambda (b)
+                                (buffer-local-value 'erc-server-process b))
+                              target-buffers)
+                (lambda (a b)
+                  (string< (buffer-name (process-buffer (car a)))
+                           (buffer-name (process-buffer (car b))))))))
+
+(defvar-local erc-status-sidebar--active-marker nil
+  "Marker indicating currently active buffer.")
+
+(defun erc-status-sidebar--set-active-line (erc-buffer)
+  (when (and erc-status-sidebar-highlight-active-buffer
+             (eq (window-buffer (and (minibuffer-window-active-p
+                                      (selected-window))
+                                     (minibuffer-selected-window)))
+                 erc-buffer))
+    (set-marker erc-status-sidebar--active-marker (point))))
+
+(defun erc-status-sidebar-default-insert (channame chanbuf _chanlist)
+  "Insert CHANNAME followed by a newline.
+Maybe arrange to highlight line if CHANBUF is showing in the
+focused window."
+  (erc-status-sidebar--set-active-line chanbuf)
+  (insert channame "\n"))
+
+(defun erc-status-sidebar-pad-hierarchy (bufname buffer buflist)
+  "Prefix BUFNAME to emphasize BUFFER's role in BUFLIST."
+  (if (and (buffer-live-p buffer) (buffer-local-value 'erc--target buffer))
+      (insert " ")
+    (unless (eq buffer (car buflist))
+      (insert "\n"))) ;  ^L
+  (when bufname
+    (erc-status-sidebar--set-active-line buffer))
+  (insert (or bufname
+              (and-let* (((not (buffer-live-p buffer)))
+                         (next (cadr (member buffer buflist)))
+                         ((buffer-live-p next))
+                         (proc (buffer-local-value 'erc-server-process next))
+                         (id (process-get proc 'erc-networks--id)))
+                (symbol-name (erc-networks--id-symbol id)))
+              "???")
+          "\n"))
+
 (defun erc-status-sidebar-default-chan-format (channame
                                                &optional num-messages erc-face)
   "Format CHANNAME for display in the sidebar.
@@ -193,43 +397,111 @@ erc-status-sidebar-default-chan-format
 (defun erc-status-sidebar-refresh ()
   "Update the content of the sidebar."
   (interactive)
-  (let ((chanlist (apply erc-status-sidebar-channel-sort
-                         (erc-channel-list nil) nil)))
+  (pcase-let* ((`(,list-fn ,sort-fn ,name-fn ,fmt-fn ,insert-fn)
+                (pcase erc-status-sidebar-style
+                  ('channels-only (list #'erc-channel-list
+                                        erc-status-sidebar-channel-sort
+                                        #'erc-status-sidebar-get-channame
+                                        erc-status-sidebar-channel-format
+                                        #'erc-status-sidebar-default-insert))
+                  ((or 'all-mixed 'all-queries-first 'all-channels-first)
+                   '(erc-status-sidebar-all-target-buffers
+                     erc-status-sidebar-default-allsort
+                     erc-status-sidebar-prefer-target-as-name
+                     erc-status-sidebar-default-chan-format
+                     erc-status-sidebar-pad-hierarchy))
+                  (v v)))
+               (chanlist (apply sort-fn (funcall list-fn nil) nil))
+               (window nil)
+               (winstart nil))
     (with-current-buffer (erc-status-sidebar-get-buffer)
+      (setq window (get-buffer-window nil erc-status-sidebar-singular)
+            winstart (and window (window-start window)))
       (erc-status-sidebar-writable
        (delete-region (point-min) (point-max))
        (goto-char (point-min))
+       (if erc-status-sidebar--active-marker
+           (set-marker erc-status-sidebar--active-marker nil)
+         (setq erc-status-sidebar--active-marker (make-marker)))
        (dolist (chanbuf chanlist)
          (let* ((tup (seq-find (lambda (tup) (eq (car tup) chanbuf))
                                erc-modified-channels-alist))
                 (count (if tup (cadr tup)))
                 (face (if tup (cddr tup)))
-                (channame (apply erc-status-sidebar-channel-format
-                                 (buffer-name chanbuf) count face nil))
+                (face (if (or (not (buffer-live-p chanbuf))
+                              (not (erc-server-process-alive chanbuf)))
+                          `(shadow ,face)
+                        face))
+                (channame (apply fmt-fn
+                                 (copy-sequence (funcall name-fn chanbuf))
+                                 count face nil))
                 (cnlen (length channame)))
            (put-text-property 0 cnlen 'erc-buf chanbuf channame)
            (put-text-property 0 cnlen 'mouse-face 'highlight channame)
            (put-text-property
             0 cnlen 'help-echo
             "mouse-1: switch to buffer in other window" channame)
-           (insert channame "\n")))))))
+           (funcall insert-fn channame chanbuf chanlist)))
+       (when winstart
+         (set-window-point window winstart)
+         (with-selected-window window (recenter 0)))
+       (when (and erc-status-sidebar-highlight-active-buffer
+                  (marker-buffer erc-status-sidebar--active-marker))
+         (goto-char erc-status-sidebar--active-marker)
+         (require 'hl-line)
+         (unless hl-line-mode (hl-line-mode +1))
+         (hl-line-highlight))))))
 
 (defun erc-status-sidebar-kill ()
   "Close the ERC status sidebar and its buffer."
   (interactive)
+  (when (and erc-bufbar-mode (not erc--module-toggle-prefix-arg))
+    (erc-bufbar-mode -1))
   (ignore-errors (kill-buffer erc-status-sidebar-buffer-name)))
 
 (defun erc-status-sidebar-click (event)
   "Handle click EVENT in `erc-status-sidebar-mode-map'."
   (interactive "e")
   (save-excursion
-    (let ((window (posn-window (event-end event)))
+    (let ((window (posn-window (event-start event)))
           (pos (posn-point (event-end event))))
-      (set-buffer (window-buffer window))
-      (let ((buf (get-text-property pos 'erc-buf)))
-        (when buf
-          (select-window window)
-          (switch-to-buffer-other-window buf))))))
+      ;; Current buffer is "ERC Status" and its window is selected
+      (cl-assert (eq major-mode 'erc-status-sidebar-mode))
+      (cl-assert (eq (selected-window) window))
+      (cl-assert (eq (window-buffer window) (current-buffer)))
+      (when-let ((buf (get-text-property pos 'erc-buf)))
+        ;; Option operates relative to last selected window
+        (select-window (get-mru-window nil nil 'not-selected))
+        (pop-to-buffer buf erc-status-sidebar-click-display-action)))))
+
+(defun erc-status-sidebar-scroll-up (lines)
+  "Scroll sidebar buffer's content LINES linse upward.
+If LINES is nil, scroll up a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window lines)))
+
+(defun erc-status-sidebar-scroll-down (lines)
+  "Scroll sidebar buffer's content LINES lines downward.
+If LINES is nil, scroll down a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window-down lines)))
+
+(defun erc-status-sidebar-recenter (arg)
+  "Recenter the status sidebar.
+Expect `erc-status-sidebar-highlight-active-buffer' to be non-nil
+and to be invoked in a buffer matching the line currently
+highlighted."
+  (interactive "P")
+  (let* ((buf (erc-status-sidebar-get-buffer))
+         (win (get-buffer-window buf)))
+    (with-current-buffer buf
+      (when (and erc-status-sidebar--active-marker
+                 (marker-position erc-status-sidebar--active-marker))
+        (with-selected-window win
+          (goto-char erc-status-sidebar--active-marker)
+          (recenter arg t))))))
 
 (defvar erc-status-sidebar-mode-map
   (let ((map (make-sparse-keymap)))
@@ -268,13 +540,17 @@ erc-status-sidebar-set-window-preserve-size
 Note that preserve status needs to be reset when the window is
 manually resized, so `erc-status-sidebar-mode' adds this function
 to the `window-configuration-change-hook'."
-  (when (and (eq (selected-window) (erc-status-sidebar-get-window))
+  (when (and (eq (selected-window) (let (erc-status-sidebar-singular)
+                                     (erc-status-sidebar-get-window)))
              (fboundp 'window-preserve-size))
     (unless (eq (window-total-width) (window-min-size nil t))
       (apply #'window-preserve-size (selected-window) t t nil))))
 
 (define-derived-mode erc-status-sidebar-mode special-mode "ERC Sidebar"
   "Major mode for ERC status sidebar."
+  ;; Users invoking M-x erc-status-sidebar-mode most likely expect to
+  ;; summon the module's minor-mode, `erc-bufbar-mode'.
+  :interactive nil
   ;; Don't scroll the buffer horizontally, if a channel name is
   ;; obscured then the window can be resized.
   (setq-local auto-hscroll-mode nil)
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
new file mode 100644
index 00000000000..aec61333e0b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -0,0 +1,93 @@
+;;; erc-scenarios-status-sidebar.el --- sidebar/speedbar -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+(require 'erc-status-sidebar)
+
+
+(ert-deftest erc-scenarios-status-sidebar--bufbar ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(bufbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit"))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (ert-info ("Activity marker is in the right spot")
+        (let ((obuf (window-buffer))) ; *scratch*
+          (set-window-buffer (selected-window) "#foo")
+          (erc-d-t-wait-for 5
+              (when noninteractive
+                (erc-status-sidebar-refresh))
+            (with-current-buffer "*ERC Status*"
+              (and (marker-position erc-status-sidebar--active-marker)
+                   (goto-char erc-status-sidebar--active-marker)
+                   ;; The " [N]" suffix disappears because it's selected
+                   (search-forward "#foo" (pos-eol) t))))
+          (set-window-buffer (selected-window) obuf))))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "*ERC Status*"))
+      (ert-info ("Hierarchy printed correctly")
+        (funcall expect 10 "barnet [")
+        (funcall expect 10 "#bar [")
+        (funcall expect 10 "foonet [")
+        (funcall expect 10 "#foo")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (should (get-buffer-window "*ERC Status*"))
+        (erc-bufbar-mode -1)
+        (should-not (get-buffer-window "*ERC Status*"))
+        (erc-status-sidebar-kill)
+        (should-not (get-buffer "*ERC Status*"))))))
+
+;;; erc-scenarios-status-sidebar.el ends here
diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
index 4ac4a3e5968..10b742fdb34 100644
--- a/test/lisp/erc/resources/base/gapless-connect/foonet.eld
+++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
@@ -1,7 +1,7 @@
 ;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :foonet:changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
  (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
  (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
  (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
@@ -21,7 +21,7 @@
  ;; No mode answer
  (0 ":irc.znc.in 306 tester :You have been marked as being away")
  (0 ":tester!~u@HIDDEN JOIN #foo")
- (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob tester")
  (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
  (0 ":***!znc@HIDDEN PRIVMSG #foo :Buffer Playback...")
  (0 ":alice!~u@HIDDEN PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.")
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0004-5.6-Add-erc-status-sidebar-integration-to-erc-speedb.patch

From fd2ec89c40dd52322c8196c3653e06c937176bc7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 4/5] [5.6] Add erc-status-sidebar integration to erc-speedbar

* lisp/erc/erc-speedbar.el: Require `erc-button' atop file and don't
bother loading `dframe', which `speedbar' handles for us.
(erc-speedbar-hide-mode-topic): New option determining whether to hide
the mode and topic.
(erc-speedbar-my-nick-face): New option for determining face to use
when displaying user's current nick.
(erc-speedbar-browser): Call `erc-install-speedbar-variables'
explicitly and remove top-level `with-eval-after-load'.
(erc-speedbar-insert-target): Add parenthesized channel count after
channel name in server and channel views.
(erc-speedbar-expand-channel): Hide mode and topic depending on option
`erc-speedbar-hide-mode-topic' and pass buffer to
`erc-speedbar-insert-user'.
(erc-speedbar--nick-face-function): New internal function-interface
variable.
(erc-speedbar--highlight-self-and-ops): New function to serve as
default value for `erc-speedbar--nick-face-function'.
(erc-speedbar--on-click): Dispatch `erc-nick-popup' after trimming
status chars.
(erc-speedbar-insert-user): Revise doc string.  Call
`erc-speedbar--nick-face-function' to determine face.  Change
token for both expansion and on-click text props.  Assign
`erc-speedbar--on-click' as the mouse handler for nick items.
(erc-speedbar-emulated-sidebar-width): New option to control width
of nicknames list window.
(erc-speedbar): Mention `erc-nickbar-mode' in group doc string.
(erc-speedbar--buffer-options): Variable to override options locally
in speedbar buffer.
(erc-speedbar--hidden-speedbar-frame): Add variable to hold original
`speedbar-frame' before spoofing by setting to selected frame
containing window showing ERC buffer.
(erc-speedbar--dframe-controlled) Add function to overwrite
`speedbar-frame-mode' as `dframe-controlled' in speedbar buffer.
(erc-speedbar--emulate-sidebar-set-window-preserve-size,
erc-speedbar--status-sidebar-mode--unhook): Add function
to ensure status sidebar is showing correctly and helper to
unregister from hook on teardown.
(erc-speedbar--emulate-sidebar): Add function to
control sidebar nicknames setup.
(erc-speedbar--toggle-nicknames-sidebar): Add toggle function
for sidebar or speedbar.
(erc-speedbar--ensure): Add helper function to show speedbar if its
hidden or create one if none exists.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable):
Add new module.
(erc-speedbar-toggle-nicknames-window-lock,
erc-speedbar-close-nicknames-window): Add commands to close speedbar
window and toggle its cyclability.
(erc-speedbar--compose-nicks-face): Add helper for nicks integration.
* test/lisp/erc/erc-scenarios-status-sidebar.el
(erc-scenarios-status-sidebar--nickbar): New test, unfortunately only
runs in terminals.
---
 lisp/erc/erc-speedbar.el                      | 284 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  76 +++++
 2 files changed, 342 insertions(+), 18 deletions(-)

diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index a9443e0ea17..21ad4c6f97a 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -32,20 +32,31 @@
 ;;   update-channel, update-nick, remove-nick-from-channel, ...
 ;; * Use indicator-strings for op/voice
 ;; * Extract/convert face notes field from bbdb if available
+;; * Write tests that run in a term-mode subprocess
 ;;
 ;;; Code:
 
 (require 'erc)
 (require 'erc-goodies)
+(require 'erc-button)
 (require 'speedbar)
-(condition-case nil (require 'dframe) (error nil))
 
 ;;; Customization:
 
 (defgroup erc-speedbar nil
-  "Integration of ERC in the Speedbar."
+  "Speedbar integration for ERC.
+To open an ERC-flavored speedbar in a separate frame, run the
+command `erc-speedbar-browser'.  To use a window-based proxy
+instead, run \\[erc-nickbar-mode] in a connected ERC buffer or
+put `nickbar' in `erc-modules' before connecting.  See Info
+node `(speedbar) Top' for more about the underlying integration."
   :group 'erc)
 
+(defcustom erc-speedbar-nicknames-window-width 18
+  "Default width of the nicknames sidebar (in columns)."
+  :package-version '(ERC . "5.7")
+  :type 'integer)
+
 (defcustom erc-speedbar-sort-users-type 'activity
   "How channel nicknames are sorted.
 
@@ -56,6 +67,23 @@ erc-speedbar-sort-users-type
 		 (const :tag "Sort users alphabetically" alphabetical)
 		 (const :tag "Do not sort users" nil)))
 
+(defcustom erc-speedbar-hide-mode-topic 'headerline
+  "Hide mode and topic lines."
+  :package-version '(ERC . "5.7") ; FIXME sync on release
+  :type '(choice (const :tag "Always show" nil)
+                 (const :tag "Always hide" t)
+                 (const :tag "Omit when headerline visible" headerline)))
+
+(defcustom erc-speedbar-my-nick-face t
+  "A face to use for your nickname.
+When the value is t, ERC uses `erc-current-nick-face' if
+`erc-match' has been loaded and `erc-my-nick-face' otherwise.
+When using the `nicks' module, you can see your nick as it
+appears to others by coordinating with the option
+`erc-nicks-skip-faces'."
+  :package-version '(ERC . "5.7")
+  :type '(choice face (const :tag "Match or own input face" t)))
+
 (defvar erc-speedbar-key-map nil
   "Keymap used when in erc display mode.")
 
@@ -88,10 +116,6 @@ erc-speedbar-menu-items
 		     (looking-at "[0-9]+: *.-. "))])
   "Additional menu-items to add to speedbar frame.")
 
-;; Make sure our special speedbar major mode is loaded
-(with-eval-after-load 'speedbar
-  (erc-install-speedbar-variables))
-
 ;;; ERC hierarchy display method
 ;;;###autoload
 (defun erc-speedbar-browser ()
@@ -99,6 +123,7 @@ erc-speedbar-browser
 This will add a speedbar major display mode."
   (interactive)
   (require 'speedbar)
+  (erc-install-speedbar-variables)
   ;; Make sure that speedbar is active
   (speedbar-frame-mode 1)
   ;; Now, throw us into Info mode on speedbar.
@@ -169,12 +194,18 @@ erc-speedbar-channel-buttons
 	  t)))))
 
 (defun erc-speedbar-insert-target (buffer depth)
-  (if (with-current-buffer buffer
-	(erc-channel-p (erc-default-target)))
-      (speedbar-make-tag-line
-       'bracket ?+ 'erc-speedbar-expand-channel buffer
-       (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
-       depth)
+  (if (erc--target-channel-p (buffer-local-value 'erc--target buffer))
+      (progn
+        (speedbar-make-tag-line
+         'bracket ?+ 'erc-speedbar-expand-channel buffer
+         (erc--target-string (buffer-local-value 'erc--target buffer))
+         'erc-speedbar-goto-buffer buffer nil
+         depth)
+        (save-excursion
+          (forward-line -1)
+          (let ((table (buffer-local-value 'erc-channel-users buffer)))
+            (speedbar-add-indicator (format "(%d)" (hash-table-count table)))
+            (rx "(" (+ (any "0-9")) ")"))))
     ;; Query target
     (speedbar-make-tag-line
      nil nil nil nil
@@ -220,6 +251,13 @@ erc-speedbar-expand-channel
 	    'angle ?i nil nil
 	    (concat "Topic: " topic) nil nil nil
 	    (1+ indent)))
+         (unless (pcase erc-speedbar-hide-mode-topic
+                   ('nil 'show)
+                   ('headerline (null erc-header-line-format)))
+           (save-excursion
+             (goto-char (point-max))
+             (forward-line (if (string= topic "") -1 -2))
+             (put-text-property (pos-bol) (point-max) 'invisible t)))
 	 (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical)
 			     (erc-sort-channel-users-alphabetically
 			      (with-current-buffer channel
@@ -233,17 +271,52 @@ erc-speedbar-expand-channel
 	   (when names
 	     (speedbar-with-writable
 	      (dolist (entry names)
-		(erc-speedbar-insert-user entry ?+ (1+ indent))))))))))
+                (erc-speedbar-insert-user entry ?+ (1+ indent) channel)))))))))
    ((string-search "-" text)
     (speedbar-change-expand-button-char ?+)
     (speedbar-delete-subblock indent))
    (t (error "Ooops... not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun erc-speedbar-insert-user (entry exp-char indent)
+(defvar erc-speedbar--nick-face-function #'erc-speedbar--highlight-self-and-ops
+  "Function called when finding a face for fontifying nicks.
+Called with the proposed nick, the `erc-server-user', and the
+`erc-channel-user'.  Should return any valid face, possibly
+composed or anonymous, or nil.")
+
+(defun erc-speedbar--highlight-self-and-ops (buffer user cuser)
+  "Highlight own nick and op'd users in the speedbar."
+  (with-current-buffer buffer
+    (if (erc-current-nick-p (erc-server-user-nickname user))
+        (pcase erc-speedbar-my-nick-face
+          ('t (if (featurep 'erc-match)
+                  'erc-current-nick-face
+                'erc-my-nick-face))
+          (v v))
+      ;; FIXME overload `erc-channel-user-owner-p' and friends to
+      ;; accept an `erc-channel-user' object and replace this unrolled
+      ;; stuff with a single call to `erc-get-user-mode-prefix'.
+      (and cuser (or (erc-channel-user-owner cuser)
+                     (erc-channel-user-admin cuser)
+                     (erc-channel-user-op cuser)
+                     (erc-channel-user-halfop cuser)
+                     (erc-channel-user-voice cuser))
+           erc-button-nickname-face))))
+
+(defun erc-speedbar--on-click (nick sbtoken _indent)
+  ;; 0: finger, 1: name, 2: info, 3: buffer-name
+  (with-current-buffer (nth 3 sbtoken)
+    (erc-nick-popup (string-trim-left nick "[~&@%+]+"))))
+
+(defun erc-speedbar-insert-user (entry exp-char indent &optional buffer)
   "Insert one user based on the channel member list ENTRY.
-EXP-CHAR is the expansion character to use.
-INDENT is the current indentation level."
+Expect EXP-CHAR to be the expansion character to use, INDENT the
+current indentation level, and BUFFER the associated channel or
+query buffer.  Set the `speedbar-function' text property to
+`erc-speedbar--on-click', which is called with the formatted
+nick, a so-called \"token\", and the indent level.  The token is
+a list of four items: the userhost, the GECOS, the current
+`erc-server-user' info slot, and the associated buffer."
   (let* ((user (car entry))
 	 (cuser (cdr entry))
 	 (nick (erc-server-user-nickname user))
@@ -255,11 +328,12 @@ erc-speedbar-insert-user
 	 (op (and cuser (erc-channel-user-op cuser)))
 	 (nick-str (concat (if op "@" "") (if voice "+" "") nick))
 	 (finger (concat login (when (or login host) "@") host))
-	 (sbtoken (list finger name info)))
+         (sbtoken (list finger name info (buffer-name buffer))))
     (if (or login host name info) ; we want to be expandable
 	(speedbar-make-tag-line
 	 'bracket ?+ 'erc-speedbar-expand-user sbtoken
-	 nick-str nil sbtoken nil
+         nick-str #'erc-speedbar--on-click sbtoken
+         (funcall erc-speedbar--nick-face-function buffer user cuser)
 	 indent)
       (when (equal exp-char ?-)
 	(forward-line -1)
@@ -357,6 +431,180 @@ erc-speedbar-item-info
 	  (t
 	   (message "%s" txt)))))
 
+
+;;;; Status-sidebar integration
+
+(defvar erc-status-sidebar-buffer-name)
+(declare-function erc-status-sidebar-set-window-preserve-size
+                  "erc-status-sidebar" nil)
+(declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil)
+
+(defvar erc-speedbar--buffer-options
+  '((speedbar-update-flag . t)
+    (speedbar-use-images . nil)
+    (speedbar-hide-button-brackets-flag . t)))
+
+(defvar erc-speedbar--hidden-speedbar-frame nil)
+
+(defun erc-speedbar--emulate-sidebar-set-window-preserve-size ()
+  (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer))
+        (display-buffer-overriding-action
+         `(display-buffer-in-side-window
+           . ((side . right)
+              (window-width . ,erc-speedbar-nicknames-window-width)))))
+    (erc-status-sidebar-set-window-preserve-size)
+    (when-let ((window (get-buffer-window speedbar-buffer)))
+      (set-window-parameter window 'no-other-window nil)
+      (internal-show-cursor window t))))
+
+(defun erc-speedbar--status-sidebar-mode--unhook ()
+  "Remove hooks installed by `erc-status-sidebar-mode'."
+  (remove-hook 'window-configuration-change-hook
+               #'erc-speedbar--emulate-sidebar-set-window-preserve-size))
+
+(defun erc-speedbar--emulate-sidebar ()
+  (require 'erc-status-sidebar)
+  (cl-assert speedbar-frame)
+  (cl-assert (eq speedbar-buffer (current-buffer)))
+  (cl-assert (eq speedbar-frame (selected-frame)))
+  (setq erc-speedbar--hidden-speedbar-frame speedbar-frame
+        dframe-controlled #'erc-speedbar--dframe-controlled)
+  (add-hook 'window-configuration-change-hook
+            #'erc-speedbar--emulate-sidebar-set-window-preserve-size nil t)
+  (add-hook 'kill-buffer-hook
+            #'erc-speedbar--status-sidebar-mode--unhook nil t)
+  (with-current-buffer speedbar-buffer
+    (pcase-dolist (`(,var . ,val) erc-speedbar--buffer-options)
+      (set (make-local-variable var) val)))
+  (when (memq 'nicks erc-modules)
+    (with-current-buffer speedbar-buffer
+      (add-function :around (local 'erc-speedbar--nick-face-function)
+                    #'erc-speedbar--compose-nicks-face))))
+
+(defun erc-speedbar--toggle-nicknames-sidebar (arg)
+  (let ((force (numberp arg)))
+    (if speedbar-buffer
+        (progn
+          (cl-assert (buffer-live-p speedbar-buffer))
+          (if (or (and force (< arg 0))
+                  (and (not force) (get-buffer-window speedbar-buffer nil)))
+              (erc-speedbar-close-nicknames-window nil)
+            (when (or (not force) (>= arg 0))
+              (with-selected-frame speedbar-frame
+                (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
+      (when (or (not force) (>= arg 0))
+        (let ((speedbar-frame-parameters (backquote-list*
+                                          '(visibility . nil)
+                                          '(no-other-frame . t)
+                                          speedbar-frame-parameters))
+              (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
+          (erc-speedbar-browser)
+          ;; If we put the remaining parts in the "create hook" along
+          ;; with everything else, the frame with `window-main-window'
+          ;; gets raised and steals focus if you've switched away from
+          ;; Emacs in the meantime.
+          (make-frame-invisible speedbar-frame)
+          (select-frame (setq speedbar-frame (previous-frame)))
+          (erc-speedbar--emulate-sidebar-set-window-preserve-size))))))
+
+(defun erc-speedbar--ensure (&optional force)
+  (when (or (erc-server-buffer) force)
+    (erc-speedbar--toggle-nicknames-sidebar +1)
+    (speedbar-enable-update)))
+
+;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
+(define-erc-module nickbar nil
+  "Show nicknames in a side window.
+When enabling, create a speedbar session if one doesn't exist and
+show its buffer in an `erc-status-sidebar' window instead of a
+separate frame.  When disabling, close the window or, with a
+negative prefix arg, destroy the session.
+
+WARNING: it's suspected that this module may perform unwanted
+side effects like raising frames and/or stealing input focus.  If
+you witness such an occurrence, and can reproduce it, please file
+a bug report with \\[erc-bug]."
+  ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (erc-speedbar--ensure)
+   (unless (or erc--updating-modules-p
+               (and-let* ((speedbar-buffer)
+                          (win (get-buffer-window speedbar-buffer 'all-frames))
+                          ((eq speedbar-frame (window-frame win))))))
+     (if speedbar-buffer
+         (erc-speedbar--ensure 'force)
+       (cl-assert (not (derived-mode-p 'erc-mode)))
+       (setq erc-nickbar-mode nil)
+       (user-error "Cannot initialize `%s' in a non-ERC buffer"
+                   'erc-nickbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (speedbar-disable-update)
+   (erc-speedbar--toggle-nicknames-sidebar -1)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-speedbar-close-nicknames-window 'kill))))
+
+(defun erc-speedbar--dframe-controlled (arg)
+  (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
+    (when erc-nickbar-mode
+      (erc-nickbar-mode -1))
+    (setq speedbar-frame erc-speedbar--hidden-speedbar-frame
+          erc-speedbar--hidden-speedbar-frame nil)
+    ;; It's unknown whether leaving the frame invisible interferes
+    ;; with the upstream teardown procedure.
+    (when (display-graphic-p)
+      (make-frame-visible speedbar-frame))
+    (speedbar-frame-mode arg)
+    (when speedbar-buffer
+      (kill-buffer speedbar-buffer)
+      (setq speedbar-buffer nil))))
+
+(defun erc-speedbar-toggle-nicknames-window-lock ()
+  "Toggle whether nicknames window is selectable with \\[other-window]."
+  (interactive)
+  (unless erc-nickbar-mode
+    (user-error "`erc-nickbar-mode' inactive"))
+  (when-let* ((window (get-buffer-window speedbar-buffer)))
+    (let ((val (window-parameter window 'no-other-window)))
+      (set-window-parameter window 'no-other-window (not val))
+      (message "nick-window: %s" (if val "selectable" "protected")))))
+
+(defun erc-speedbar-close-nicknames-window (kill)
+  (interactive "P")
+  (if kill
+      (with-current-buffer speedbar-buffer
+        (dframe-close-frame)
+        (cl-assert (not erc-nickbar-mode))
+        (setq erc-speedbar--hidden-speedbar-frame nil))
+    (dolist (window (get-buffer-window-list speedbar-buffer nil t))
+      (unless (frame-root-window-p window)
+        (when erc-speedbar--hidden-speedbar-frame
+          (cl-assert (not (eq (window-frame window)
+                              erc-speedbar--hidden-speedbar-frame))))
+        (delete-window window)))))
+
+
+;;;; Nicks integration
+
+(defvar erc-nicks--phony-face)
+(declare-function erc-nicks--highlight "erc-nicks" (nick-object))
+
+(defun erc-speedbar--compose-nicks-face (orig buffer user cuser)
+  (require 'erc-nicks)
+  (let ((rv (funcall orig buffer user cuser)))
+    (if-let* ((nobj (make-erc-button--nick
+                     :downcased (erc-downcase (erc-server-user-nickname user))
+                     :user user
+                     :cuser cuser))
+              (erc-nicks--phony-face (or rv t))
+              (nobj (with-current-buffer buffer
+                      (erc-nicks--highlight nobj)))
+              (face (erc-button--nick-erc-button-nickname-face nobj))
+              ((not (eq face erc-button-nickname-face))))
+        (cons face (ensure-list rv))
+      rv)))
+
+
 (provide 'erc-speedbar)
 ;;; erc-speedbar.el ends here
 ;;
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index aec61333e0b..6ac1821ebb7 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -90,4 +90,80 @@ erc-scenarios-status-sidebar--bufbar
         (erc-status-sidebar-kill)
         (should-not (get-buffer "*ERC Status*"))))))
 
+;; No need to pollute the global obarray since we can't currently run
+;; this on EMBA (it requires a terminal).  Please try running this
+;; test interactively with both graphical Emacs and non.
+(declare-function erc-nickbar-mode "erc-speedbar" (arg))
+(declare-function erc-speedbar-close-nicknames-window "erc-speedbar" (kill))
+(declare-function speedbar-timer-fn "speedbar" nil)
+(defvar erc-nickbar-mode)
+(defvar speedbar-buffer)
+
+(ert-deftest erc-scenarios-status-sidebar--nickbar ()
+  :tags '(:unstable :expensive-test)
+  (when noninteractive (ert-skip "Interactive only"))
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(nickbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#bar"))
+    (with-current-buffer (pop-to-buffer "#bar")
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit")
+      (erc-d-t-wait-for 10 (and speedbar-buffer (get-buffer speedbar-buffer)))
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#bar (3)")
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 "tester")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#foo"))
+    (with-current-buffer (pop-to-buffer "#foo")
+      (delete-other-windows)
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#foo (3)")
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 "tester")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (erc-nickbar-mode -1)
+        (should-not (and speedbar-buffer
+                         (get-buffer-window speedbar-buffer)))
+        (erc-nickbar-mode +1)
+        (should (and speedbar-buffer
+                     (get-buffer-window speedbar-buffer)))
+        (should (get-buffer " SPEEDBAR"))
+        (erc-speedbar-close-nicknames-window 'kill)
+        (should-not (get-buffer " SPEEDBAR"))
+        (should-not erc-nickbar-mode)
+        (should-not (cdr (frame-list)))))))
+
 ;;; erc-scenarios-status-sidebar.el ends here
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0005-5.6-Add-new-ERC-modules-bufbar-and-nickbar.patch

From 93f31ce4e062acd8ea6e87ea8023707b9e4b383b Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 5/5] [5.6] Add new ERC modules bufbar and nickbar

* doc/misc/erc.texi: Add `bufbar' and `nickbar' to known modules.
* erc/ERC-NEWS: Mention erc-status-sidebar and erc-speedbar
improvements.
* lisp/erc/erc.el (erc-modules): Add `bufbar' and `nickbar' to
selection of offered modules.
* test/lisp/erc/erc-tests.el (erc-tests--modules): Add `bufbar' and
`nickbar'.
---
 doc/misc/erc.texi          |  9 +++++++++
 etc/ERC-NEWS               | 16 ++++++++++++++++
 lisp/erc/erc.el            |  2 ++
 test/lisp/erc/erc-tests.el |  4 ++--
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index f7036e57638..7c625c2fd02 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -418,6 +418,10 @@ Modules
 @item bbdb
 Integrate with the Big Brother Database
 
+@cindex modules, bufbar
+@item bufbar
+List ERC buffers belonging to a live connection in a side window
+
 @cindex modules, button
 @item button
 Buttonize URLs, nicknames, and other text
@@ -463,6 +467,11 @@ Modules
 @item nicks
 Automatically colorize nicks
 
+@cindex modules, nickbar
+@item nickbar
+List participating nicks for the current target buffer in a side
+window
+
 @cindex modules, noncommands
 @item noncommands
 Don't display non-IRC commands after evaluation
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 41af8b88277..6922ae22482 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -72,6 +72,22 @@ widget has been an age-old annoyance for new users.  Previously
 ineffective, this method now actually works, but it also admonishes
 users to edit the 'erc-modules' widget instead.
 
+** ERC's status-sidebar now has an accompanying module.
+Users can now add 'bufbar' to 'erc-modules' to achieve the same effect
+as toggling 'erc-status-sidebar-open' manually at the start of an IRC
+session.  The module has also been outfitted to show channels and
+queries under their respective servers by default.  To avoid
+confusion, the major mode used for the sidebar buffer itself,
+'erc-status-sidebar-mode', is no longer available interactively.
+
+** A new spin on a classic integration in erc-speedbar.
+Add 'nickbar' to 'erc-modules' to spawn a dynamically updating side
+window listing all the users in any target buffer.  It's powered by
+the same speedbar.el integration you've always known, except this
+one's optionally accessible from the keyboard, just like any other
+side window.  Hit '<RET>' over a nick to spawn a "/QUERY" or a
+"Lastlog" (Occur) session.  See 'erc-nickbar-mode' for more.
+
 ** The option 'erc-timestamp-use-align-to' is more versatile.
 While this option has always offered to right-align stamps via the
 'display' text property, it's now more effective at doing so when set
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 5a3b312b53b..2f26985f74d 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2006,6 +2006,7 @@ erc-modules
     :greedy t
     (const :tag "autoaway: Set away status automatically" autoaway)
     (const :tag "autojoin: Join channels automatically" autojoin)
+    (const :tag "bufbar: Show ERC buffers in a side window" bufbar)
     (const :tag "button: Buttonize URLs, nicknames, and other text" button)
     (const :tag "capab: Mark unidentified users on servers supporting CAPAB"
            capab-identify)
@@ -2026,6 +2027,7 @@ erc-modules
            move-to-prompt)
     (const :tag "netsplit: Detect netsplits" netsplit)
     (const :tag "networks: Provide data about IRC networks" networks)
+    (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar)
     (const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks)
     (const :tag "noncommands: Don't display non-IRC commands after evaluation"
            noncommands)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index de472527bde..4432dc58082 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1951,9 +1951,9 @@ erc-handle-irc-url
     (kill-buffer "#chan")))
 
 (defconst erc-tests--modules
-  '( autoaway autojoin button capab-identify completion dcc fill identd
+  '( autoaway autojoin bufbar button capab-identify completion dcc fill identd
      imenu irccontrols keep-place list log match menu move-to-prompt netsplit
-     networks nicks noncommands notifications notify page readonly
+     networks nickbar nicks noncommands notifications notify page readonly
      replace ring sasl scrolltobottom services smiley sound
      spelling stamp track truncate unmorse xdcc))
 
-- 
2.40.0


--=-=-=--



------------=_1689300482-2649-0
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Received: (at 63595-done) by debbugs.gnu.org; 14 Jul 2023 02:07:59 +0000
Received: from localhost ([127.0.0.1]:41087 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qK8Dv-0000gV-HE
	for submit <at> debbugs.gnu.org; Thu, 13 Jul 2023 22:07:59 -0400
Received: from mail-108-mta181.mxroute.com ([136.175.108.181]:42017)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qK8Dr-0000gJ-8N
 for 63595-done <at> debbugs.gnu.org; Thu, 13 Jul 2023 22:07:58 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta181.mxroute.com (ZoneMTA) with ESMTPSA id
 189522787e90004cef.001 for <63595-done <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 14 Jul 2023 02:07:49 +0000
X-Zone-Loop: 3f60c6cd01287d375eaaf9431f400fd1e6aedd64b514
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=O40614c5LW5s4eKAeVrBACzhVjTZsn9jgbu5wYNh4Gs=; b=W4305aLiuzX1V9KD9f9ZNPH99+
 rt2EEwHd6aKiZDsipNtHKq+yRNowtlnF7tdhPJXn7td6I2rqU6YsGx3+LAMYP/oZrnDilupppmVrq
 9AyjZvr5q3vEzt6AoGwJwnFbcUy4N+T9SJTfbq+AywDgvgCxPPNoSfFaWvoO5Anf0fwAtdveMLY0I
 sx/Mh43QaVo3wkgSGhLssCqM4a79z5j27Z2YZWI0ZAObbLFKktcZmBpw4awMrAImIqev3BopU7UR+
 SK98XfU3byZyN8gU/cemOXNAb4oSCxGHucvV+Jb8eRQVGqhA29hPdtTmQlOoUnaZOnUJ8q/K6wvbk
 +T+elf5g==;
From: "J.P." <jp@HIDDEN>
To: 63595-done <at> debbugs.gnu.org
Subject: Re: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Thu, 13 Jul 2023 19:07:46 -0700
Message-ID: <87r0pbs0st.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 63595-done
Cc: emacs-erc@HIDDEN
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

A more refined version of these changes has been installed [1]. However,
they're more likely than most to be imperfect due to their relative
complexity and the lack of effective tests, not to mention the kludgy
nature of the new speedbar module (whose frame we're hiding in favor of
showing its buffer in a side window). Hopefully, these new features will
lead to increased use, which should help exorcise the worst of their
demons.

Closing (for now).

[1] https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ded35c2d
    https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=3c70e85d


------------=_1689300482-2649-0--


Message sent:


MIME-Version: 1.0
X-Mailer: MIME-tools 5.505 (Entity 5.505)
X-Loop: help-debbugs@HIDDEN
From: help-debbugs@HIDDEN (GNU bug Tracking System)
To: "J.P." <jp@HIDDEN>
Subject: bug#63595: closed (Re: bug#63595: 30.0.50; ERC 5.6: Add
 buffer-list and nick-list modules)
Message-ID: <handler.63595.D63595.16893004792640.notifdone <at> debbugs.gnu.org>
References: <87r0pbs0st.fsf@HIDDEN> <87lehkt97a.fsf@HIDDEN>
X-Gnu-PR-Message: they-closed 63595
X-Gnu-PR-Package: emacs
X-Gnu-PR-Keywords: patch
Reply-To: 63595 <at> debbugs.gnu.org
Date: Fri, 14 Jul 2023 02:08:02 +0000
Content-Type: multipart/mixed; boundary="----------=_1689300482-2649-1"

This is a multi-part message in MIME format...

------------=_1689300482-2649-1
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

Your bug report

#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to 63595 <at> debbugs.gnu.org.

--=20
63595: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D63595
GNU Bug Tracking System
Contact help-debbugs@HIDDEN with problems

------------=_1689300482-2649-1
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Received: (at 63595-done) by debbugs.gnu.org; 14 Jul 2023 02:07:59 +0000
Received: from localhost ([127.0.0.1]:41087 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qK8Dv-0000gV-HE
	for submit <at> debbugs.gnu.org; Thu, 13 Jul 2023 22:07:59 -0400
Received: from mail-108-mta181.mxroute.com ([136.175.108.181]:42017)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qK8Dr-0000gJ-8N
 for 63595-done <at> debbugs.gnu.org; Thu, 13 Jul 2023 22:07:58 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta181.mxroute.com (ZoneMTA) with ESMTPSA id
 189522787e90004cef.001 for <63595-done <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 14 Jul 2023 02:07:49 +0000
X-Zone-Loop: 3f60c6cd01287d375eaaf9431f400fd1e6aedd64b514
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=O40614c5LW5s4eKAeVrBACzhVjTZsn9jgbu5wYNh4Gs=; b=W4305aLiuzX1V9KD9f9ZNPH99+
 rt2EEwHd6aKiZDsipNtHKq+yRNowtlnF7tdhPJXn7td6I2rqU6YsGx3+LAMYP/oZrnDilupppmVrq
 9AyjZvr5q3vEzt6AoGwJwnFbcUy4N+T9SJTfbq+AywDgvgCxPPNoSfFaWvoO5Anf0fwAtdveMLY0I
 sx/Mh43QaVo3wkgSGhLssCqM4a79z5j27Z2YZWI0ZAObbLFKktcZmBpw4awMrAImIqev3BopU7UR+
 SK98XfU3byZyN8gU/cemOXNAb4oSCxGHucvV+Jb8eRQVGqhA29hPdtTmQlOoUnaZOnUJ8q/K6wvbk
 +T+elf5g==;
From: "J.P." <jp@HIDDEN>
To: 63595-done <at> debbugs.gnu.org
Subject: Re: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Thu, 13 Jul 2023 19:07:46 -0700
Message-ID: <87r0pbs0st.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 63595-done
Cc: emacs-erc@HIDDEN
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

A more refined version of these changes has been installed [1]. However,
they're more likely than most to be imperfect due to their relative
complexity and the lack of effective tests, not to mention the kludgy
nature of the new speedbar module (whose frame we're hiding in favor of
showing its buffer in a side window). Hopefully, these new features will
lead to increased use, which should help exorcise the worst of their
demons.

Closing (for now).

[1] https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ded35c2d
    https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=3c70e85d


------------=_1689300482-2649-1
Content-Type: message/rfc822
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Received: (at submit) by debbugs.gnu.org; 19 May 2023 19:25:54 +0000
Received: from localhost ([127.0.0.1]:57435 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1q05ja-0004Kr-HF
	for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:53 -0400
Received: from lists.gnu.org ([209.51.188.17]:54098)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1q05jV-0004Ke-Se
 for submit <at> debbugs.gnu.org; Fri, 19 May 2023 15:25:49 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jV-0003yx-Ey
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-108-mta11.mxroute.com ([136.175.108.11])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
 (Exim 4.90_1) (envelope-from <jp@HIDDEN>) id 1q05jO-0005YW-Nz
 for bug-gnu-emacs@HIDDEN; Fri, 19 May 2023 15:25:45 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta11.mxroute.com (ZoneMTA) with ESMTPSA id 1883579758200074ee.001
 for <bug-gnu-emacs@HIDDEN>
 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);
 Fri, 19 May 2023 19:25:32 +0000
X-Zone-Loop: eec7dda6ba983e849cec5c7021dd9f3b963fa6e4e9fe
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=reOVYRocD84tqZU6Afp4MUToMaIkxYinxEkfAKJ6TEQ=; b=JWB0abbAfp98Slzy+ZQWJUY2pv
 tEBXPa65Rq/NP6nB1fU6/+hHUBsUtheeb5MoQVHR40jzE+eJhe4Dmv0UOfn+m62bNxe1VW1uuUlmT
 XAB1AwzSXVoCNW+V9WXYxY8kGncTwAzfmF5YHkTf+Q4YjJjlLPWtT5xmDbfKULqII4R19v6/uNGB1
 JA8JrJqdIuN/fGcYwR7e8K1XSdoFHWTtNhDWfEE+J47GN2USEtY43xp1QpI3Qkkt8gGB1dDlh6vYo
 FrMkk24HC5++Og2JpEzxk0pyTzZoghmB+FBth71ZF8qjTluwptnYhxjEHyknC0vteueMkPqXTVRaj
 NVDIEzCw==;
From: "J.P." <jp@HIDDEN>
To: bug-gnu-emacs@HIDDEN
Subject: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
X-Debbugs-CC: emacs-erc@HIDDEN
Date: Fri, 19 May 2023 12:25:29 -0700
Message-ID: <87lehkt97a.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
Received-SPF: pass client-ip=136.175.108.11; envelope-from=jp@HIDDEN;
 helo=mail-108-mta11.mxroute.com
X-Spam_score_int: -20
X-Spam_score: -2.1
X-Spam_bar: --
X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001,
 SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: -1.4 (-)
X-Debbugs-Envelope-To: submit
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -2.4 (--)

--=-=-=
Content-Type: text/plain

Tags: patch
Severity: wishlist

(This bug could just as well be titled "Make ERC look more like
standalone clients," although that's perhaps a bit clickbaity.)


Hi,

Newcomers to ERC are occasionally dumbfounded by the absence of a
certain pair of IRC essentials, namely, a "window list" and a "nicknames
list." But what even existing users may not know is that ERC already has
both; they just don't quite work the way folks coming from other clients
might expect. This patch aims to address that as if it were a problem.

What's being proposed here is the addition of two new modules built
entirely on functionality already offered by their host libraries,
erc-status-sidebar.el and erc-speedbar.el. What's different is these
additions flirt with something somewhat verboten in ERC, and that's
changing existing defaults for non-security reasons (in this case,
chiefly for unifying UX [1]). Beyond that, these changes also hard-wire
potentially offensive choices into some of these defaults while trying
in earnest to ensure old behavior remains accessible. For example, one
module assumes no one with a non-nil `erc-header-line-format' has any
use for modes and topics in a side window. Other baked in preferences
include the nixing of all throwback icons [2] and the showing of
disconnected buffers in a muted face. The list goes on but is open for
discussion, as always.

Another consideration here is of course naming [3]. I've gone ahead and
dubbed the speedbar module 'nickbar' as a bit of an homage to its roots.
`nicklist' wasn't available because a popular module of that name was
once part of ERC, and people still use it today. For status-sidebar, I
went with `bufbar', in part for consistency but also because the
would-be canonical "status-sidebar" is already taken by the side
window's buffer for its major mode. We might also consider going with
the slightly pedestrian `buflist', which is already used by at least one
other IRC client for referring to this feature.

Lastly, I'd like to stress that these modules (thankfully) won't be
loaded by default, which means you'll need to add `bufbar' and `nickbar'
to `erc-modules' when trying them out. Note that this patch set
currently depends on bug#63569 [3], whose changes need applying
beforehand.

Thanks!


[1] My justifications for taking such liberties are at best anecdotal,
    based mostly on personal impressions of prevailing usage patterns
    and the perceived motivations behind them. A few examples:

    a. The relative newness of erc-status-sidebar.el, its lack of an
       associated module, and its absence from ERC's Custom menu all
       point to its defaults being somewhat more free for the changing.
       The speedbar integration likewise lacks a module, and its
       graphical-only nature means its set of users currently excludes
       anyone using ERC from a terminal. (Less expected fallout from the
       proposed churn, IOW.)

    b. Both libraries provide an always-open side window (or, in
       speedbar's case, frame), which imposes a specific layout on the
       user, something that's relatively rare in Emacs outside of
       IDE-style modes. Compare this to something like ibuffer for
       listing buffers or a hypothetical /NAMES buffer, which, if based
       on `tabulated-list-mode', would make for a more familiar means of
       reviewing channel members. The point here is that devoted users
       likely aren't messing with erc-status-sidebar or erc-speedbar in
       droves, preferring more Emacsy alternatives instead.

    c. Newcomers can't be bothered with an overly involved setup if it
       requires carefully exploring options before trying. But they're
       perfectly willing to copy/paste gobs of configuration or even
       mindlessly follow a minutes long Customize itinerary, so long as
       the promise of emerging with something resembling their present
       idea of what makes an IRC client remains within reach. By
       introducing these modules "preconfigured," I'm positing that
       these preconceived notions typically include a reactive window
       list and/or nick list. That said, my hope is that these users
       will eventually gravitate toward the more Emacs-native way of
       doing things, at which point these modules will have served their
       primary purpose (of acting as bait).

[2] My reason for 86'ing the icons outright in the speedbar's new
    "window mode" is consistency. I figure anyone who wants the vanilla
    experience wants it in full and thus also wants a separate frame.
    That said, I suppose we could add a knob for tweaking this (or any
    of the other hard-coded choices mentioned), but IMO doing that
    unprovoked just contributes to "options sprawl."

[3] FWIW, all module names in contention flout our supposed policy of
    preferring those that align with host libraries and the features
    they `provide'.


In GNU Emacs 30.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version
 3.24.37, cairo version 1.17.6) of 2023-05-13 built on localhost
Repository revision: 867b104010760c4b7cd700078884cc774a01860a
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12014000
System Description: Fedora Linux 37 (Workstation Edition)

Configured using:
 'configure --enable-check-lisp-object-type --enable-checking=yes,glyphs
 'CFLAGS=-O0 -g3'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util text-property-search time-date mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils erc auth-source cl-seq
eieio eieio-core cl-macs password-cache json subr-x map format-spec
cl-loaddefs cl-lib erc-backend erc-networks byte-opt gv bytecomp
byte-compile erc-common erc-compat erc-loaddefs rmc iso-transl tooltip
cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd
fontset image regexp-opt fringe tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 64236 9476)
 (symbols 48 8573 0)
 (strings 32 23246 1709)
 (string-bytes 1 674076)
 (vectors 16 15015)
 (vector-slots 8 207266 8159)
 (floats 8 24 33)
 (intervals 56 229 0)
 (buffers 976 10))

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Fix-buffer-mismatch-bug-in-erc-scroll-to-bottom.patch

From 4a1bd9e173d91164d5abe6f2e349a447eaf019d7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 17 May 2023 19:48:02 -0700
Subject: [PATCH 1/5] [5.6] Fix buffer-mismatch bug in erc-scroll-to-bottom

* lisp/erc/erc-goodies.el (erc-scroll-to-bottom): Only `recenter' when
the selected window's buffer is current.  Previously, the module
`scrolltobottom' signaled an "Error in `post-command-hook'" when a
user clicked a channel indicator in the mode line from a window
showing another ERC buffer.
---
 lisp/erc/erc-goodies.el | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 01eae4b63c5..87c95778523 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -92,6 +92,7 @@ erc-scroll-to-bottom
     (save-restriction
       (widen)
       (when (and erc-insert-marker
+                 (eq (current-buffer) (window-buffer))
 		 ;; we're editing a line. Scroll.
 		 (> (point) erc-insert-marker))
 	(save-excursion
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0002-5.6-Allow-ERC-s-module-toggles-access-to-the-prefix-.patch

From 5ae05b1ad34ce1baea149c7af1e9e9282f101725 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Mon, 15 May 2023 00:16:00 -0700
Subject: [PATCH 2/5] [5.6] Allow ERC's module toggles access to the prefix arg

* lisp/erc/erc-common.el (erc--module-toggle-prefix-arg): Add internal
variable for preserving the `arg' passed to a module's minor-mode
toggle, which was previously discarded.  Doing this lets modules that
are more interactive in nature overload their mode toggles with
alternate behaviors.
(define-erc-module): Bind `erc--module-toggle-prefix-arg' to the `arg'
parameter, which is normally defined inside a `define-minor-mode' body
form.
* test/lisp/erc/erc-tests.el (define-erc-module--global,
define-erc-module--local): Expect activation body to be wrapped by a
let form binding `erc--module-toggle-prefix-arg'.
---
 lisp/erc/erc-common.el     | 14 +++++++++++---
 test/lisp/erc/erc-tests.el | 14 ++++++++------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index f152a1a32d9..dd39b30c4db 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -289,6 +289,15 @@ erc--find-feature
              (intern (file-name-base file))))
      (v v)))
 
+(defvar erc--module-toggle-prefix-arg nil
+  "The interpreted prefix arg of the minor-mode toggle.
+Non-nil inside an ERC module's activation (or deactivation)
+command, such as `erc-spelling-enable', when it's been called
+indirectly via the module's minor-mode toggle, i.e.,
+`erc-spelling-mode'.  Nil otherwise.  Its value is either the
+symbol `toggle' or an integer produced by `prefix-numeric-value'.
+See Info node `(elisp) Defining Minor Modes' for more.")
+
 (defmacro define-erc-module (name alias doc enable-body disable-body
                                   &optional local-p)
   "Define a new minor mode using ERC conventions.
@@ -337,9 +346,8 @@ define-erc-module
          :group (erc--find-group ',name ,(and alias (list 'quote alias)))
          ,@(unless local-p `(:require ',(erc--find-feature name alias)))
          ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name)))
-         (if ,mode
-             (,enable)
-           (,disable)))
+         (let ((erc--module-toggle-prefix-arg arg))
+           (if ,mode (,enable) (,disable))))
        ,(erc--assemble-toggle local-p name enable mode t enable-body)
        ,(erc--assemble-toggle local-p name disable mode nil disable-body)
        ,@(and-let* ((alias)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 991bfa3b082..de472527bde 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -2175,9 +2175,10 @@ define-erc-module--global
                         :group (erc--find-group 'mname 'malias)
                         :require 'nil
                         :type "mname"
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable ()
                         "Enable ERC mname mode."
@@ -2230,9 +2231,10 @@ define-erc-module--local
 Some docstring."
                         :global nil
                         :group (erc--find-group 'mname nil)
-                        (if erc-mname-mode
-                            (erc-mname-enable)
-                          (erc-mname-disable)))
+                        (let ((erc--module-toggle-prefix-arg arg))
+                          (if erc-mname-mode
+                              (erc-mname-enable)
+                            (erc-mname-disable))))
 
                       (defun erc-mname-enable (&optional ,arg-en)
                         "Enable ERC mname mode.
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0003-5.6-Add-preset-styles-to-erc-status-sidebar.patch

From c4746e4bb3fde7670bd655ed7f17ec90435018ac Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 3/5] [5.6] Add preset styles to erc-status-sidebar

* lisp/erc/erc-networks.el (erc-networks--rename-server-buffer): Store
`erc-networks--id' in process object's plist.
* lisp/erc/erc-status-sidebar.el (erc-status-sidebar): Change parent
from `convenience' to `erc'.
(erc-status-sidebar-channel-format):
Mention in doc string that it depends on new option
`erc-status-sidebar-style'.
(erc-status-sidebar-highlight-active-buffer): New option to control
whether the current window's target is highlighted in the status bar.
(erc-status-sidebar-style): New option to determine whether servers
and queries also appear in the sidebar.
(erc-status-sidebar-click-display-action,
erc-status-sidebar-singular): New options.
(erc-status-sidebar-get-window): Consider
`erc-status-sidebar-singular'.
(erc-status-sidebar-open): Fix toggle functionality that somehow fell
through the cracks after the adoption of the package into ERC proper.
(erc-buflist-mode, erc-buflist-enable, erc-buflist-disable): New
module named `buflist' instead of `sidebar', which is more easily
confusable with `speedbar'.  The preferred name, `status-sidebar' was
unavailable because its minor-mode would have been
`erc-status-sidebar-mode', which is already taken by the major mode
used for status-bar buffers themselves.
(erc-status-sidebar-toggle): Ignore `erc-status-sidebar-singular'.
(erc-status-sidebar--trimpat, erc-status-sidebar--prechan): Add helper
vars for new sorting function, allowing it to honor the existing
interface, which only expects one argument.
(erc-status-sidebar-prefer-target-as-name): New function for
determining buffer name, preferring targets for target buffers.
(erc-status-sidebar-get-channame): Use internal API to help determine
name of buffer in sidebar.
(erc-status-sidebar-prefer-target-as-name,
erc-status-sidebar--show-disconnected,
erc-status-sidebar-all-target-buffers,
erc-status-sidebar-default-allsort): Add new naming and sorting
functions and associated helper functions and variables.
(erc-status-sidebar--active-marker,
erc-status-sidebar--set-active-line): New variable and function for
highlighting the active target in the status bar.
(erc-status-sidebar-default-insert,
erc-status-sidebar-pad-hierarchy): New functions for visiting various
stages of buffer modification when rendering sidebar.
(erc-status-sidebar-click): Appeal to option
`erc-status-sidebar-display-action' for `pop-to-buffer' action.
(erc-status-sidebar-scroll-up, erc-status-sidebar-scroll-down,
erc-status-sidebar-recenter): Add commands to scroll and
recenter sidebar from a target buffer's window.
(erc-status-sidebar-refresh): Consider presets and new options when
rendering sidebar.  Disable `erc-buflist-mode' when active.
(erc-status-sidebar-set-window-preserve-size): Ignore
`erc-status-sidebar-singular'.
(erc-status-sidebar-mode): Make non-interactive to avoid confusion
when folks run "M-x erc-status-sidebar-mode" expecting a module
toggle.
* test/lisp/erc/erc-scenarios-status-sidebar.el: New file.
* test/lisp/erc/resources/base/gapless-connect/foonet.eld: Fix wrong
manifest for channel and extend PASS timeout.
---
 lisp/erc/erc-networks.el                      |   1 +
 lisp/erc/erc-status-sidebar.el                | 328 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  93 +++++
 .../resources/base/gapless-connect/foonet.eld |   8 +-
 4 files changed, 400 insertions(+), 30 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-status-sidebar.el

diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index dd481032e7e..60d76d059da 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1459,6 +1459,7 @@ erc-networks--rename-server-buffer
          ;; When this ends up being the current buffer, either we have
          ;; a "given" ID or the buffer was reused on reconnecting.
          (existing (get-buffer name)))
+    (process-put new-proc 'erc-networks--id erc-networks--id)
     (cond ((or (not existing)
                (erc-networks--id-given erc-networks--id)
                (eq existing (current-buffer)))
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index f11faa3db10..c06ba53f3ae 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -45,6 +45,13 @@
 ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and
 ;; close the sidebar on all frames.
 
+;; In addition to the commands above, you can also try the all-in-one,
+;; "DWIM" command, `erc-bufbar-mode'.  See its doc string for usage.
+
+;; If you want the status sidebar enabled whenever you use ERC, add
+;; `bufbar' to `erc-modules'.  Note that this library also has a major
+;; mode, `erc-status-sidebar-mode', which is for internal use.
+
 ;;; Code:
 
 (require 'erc)
@@ -53,8 +60,15 @@
 (require 'seq)
 
 (defgroup erc-status-sidebar nil
-  "A sidebar for ERC channel status."
-  :group 'convenience)
+  "A responsive side window listing all connected ERC buffers.
+More commonly known as a window list or \"buflist\", this side
+panel displays clickable buffer names for switching to with the
+mouse.  By default, ERC highlights the name corresponding to the
+selected window's buffer, if any.  Here, \"connected buffer\"
+means one belonging to a session context for a server that ERC is
+currently communicating with.  For information on how the window
+itself works, see Info node `(elisp) Side Windows'."
+  :group 'erc)
 
 (defcustom erc-status-sidebar-buffer-name "*ERC Status*"
   "Name of the sidebar buffer."
@@ -80,9 +94,78 @@ erc-status-sidebar-channel-sort
 
 (defcustom erc-status-sidebar-channel-format
   'erc-status-sidebar-default-chan-format
-  "Function used to format channel names for display in the sidebar."
+  "Function used to format channel names for display in the sidebar.
+Only consulted for certain values of `erc-status-sidebar-style'."
   :type 'function)
 
+(defcustom erc-status-sidebar-highlight-active-buffer t
+  "Whether to highlight the selected window's buffer in the sidebar.
+ERC uses the same instance across all frames.  May not be
+compatible with all values of `erc-status-sidebar-style'."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defcustom erc-status-sidebar-style 'all-queries-first
+  "Preset style for rendering the sidebar.
+
+When set to `channels-only', ERC limits the items in the
+status bar to uniquified channels.  It uses the options
+and functions
+
+  `erc-channel-list',
+  `erc-status-sidebar-channel-sort',
+  `erc-status-sidebar-get-channame',
+  `erc-status-sidebar-channel-format'
+  `erc-status-sidebar-default-insert'
+
+for selecting, formatting, naming, and inserting entries.  When
+set to one of the various \\=`all-*' values, such as `all-mixed',
+ERC shows channels and queries under their respective server
+buffers, using the functions
+
+  `erc-status-sidebar-all-target-buffers',
+  `erc-status-sidebar-default-allsort',
+  `erc-status-sidebar-prefer-target-as-name',
+  `erc-status-sidebar-default-chan-format',
+  `erc-status-sidebar-pad-hierarchy'
+
+for the above-mentioned purposes.  ERC also accepts a list of
+functions to preform these roles a la carte.  See doc strings for
+a description of their expected arguments and return values."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const channels-only)
+                 (const all-mixed)
+                 (const all-queries-first)
+                 (const all-channels-first)
+                 (list (function :tag "Buffer lister")
+                       (function :tag "Buffer sorter")
+                       (function :tag "Name extractor")
+                       (function :tag "Name formatter")
+                       (function :tag "Name inserter"))))
+
+(defcustom erc-status-sidebar-click-display-action t
+  "How to display a buffer when clicked.
+Values can be anything recognized by `display-buffer' for its
+ACTION parameter."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type '(choice (const :tag "Always use/create other window" t)
+                 (const :tag "Let `display-buffer' decide" nil)
+                 (const :tag "Same window" (display-buffer-same-window
+                                            (inhibit-same-window . nil)))
+                 (cons :tag "Action"
+                       (choice function (repeat function))
+                       (alist :tag "Action arguments"
+                              :key-type symbol
+                              :value-type (sexp :tag "Value")))))
+
+(defcustom erc-status-sidebar-singular t
+  "Whether to show the sidebar on all frames or just one (default)."
+  :package-version '(ERC . "5.6") ; FIXME sync on release
+  :type 'boolean)
+
+(defvar hl-line-mode)
+(declare-function hl-line-highlight "hl-line" nil)
+
 (defun erc-status-sidebar-display-window ()
   "Display the status buffer in a side window.  Return the new window."
   (display-buffer
@@ -94,7 +177,8 @@ erc-status-sidebar-get-window
   "Return the created/existing window displaying the status buffer.
 
 If NO-CREATION is non-nil, the window is not created."
-  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name)))
+  (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name
+                                           erc-status-sidebar-singular)))
     (unless (or sidebar-window no-creation)
       (with-current-buffer (erc-status-sidebar-get-buffer)
         (setq-local vertical-scroll-bar nil))
@@ -144,22 +228,50 @@ erc-status-sidebar-open
   "Open or create a sidebar."
   (interactive)
   (save-excursion
-    (let ((sidebar-exists (erc-status-sidebar-buffer-exists-p))
-          (sidebar-buffer (erc-status-sidebar-get-buffer))
-          ;; (sidebar-window (erc-status-sidebar-get-window))
-          )
-      (unless sidebar-exists
-        (with-current-buffer sidebar-buffer
-          (erc-status-sidebar-mode)
-          (erc-status-sidebar-refresh))))))
+    (if (erc-status-sidebar-buffer-exists-p)
+        (erc-status-sidebar-get-window)
+      (with-current-buffer (erc-status-sidebar-get-buffer)
+        (erc-status-sidebar-mode)
+        (erc-status-sidebar-refresh)))))
+
+;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t)
+(define-erc-module bufbar nil
+  "Show `erc-track'-like activity in a side window.
+When enabling, show the sidebar immediately if called from a
+connected ERC buffer.  Otherwise, arrange for doing so on connect
+or whenever next displaying a new ERC buffer.  When disabling,
+hide the status window if it's showing.  With a negative prefix
+arg, also shutdown the session."
+  ((unless erc-track-mode
+     (unless (memq 'track erc-modules)
+       (erc--warn-once-before-connect 'erc-bufbar-mode
+         "Module `bufbar' needs global module `track'. Enabling now."
+         " This will affect \C-]all\C-] ERC sessions."
+         " Add `track' to `erc-modules' to silence this message."))
+     (erc-track-mode +1))
+   (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (unless erc--updating-modules-p
+     (if (erc-with-server-buffer erc-server-connected)
+         (erc-status-sidebar-open)
+       (setq erc-bufbar-mode nil)
+       (user-error "`%s' not called from a connected ERC buffer."
+                   'erc-bufbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (erc-status-sidebar-close erc-status-sidebar-singular)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-status-sidebar-kill))))
 
 ;;;###autoload
 (defun erc-status-sidebar-toggle ()
-  "Toggle the sidebar open/closed on the current frame."
+  "Toggle the sidebar open/closed on the current frame.
+Do this regardless of `erc-status-sidebar-singular'."
   (interactive)
   (if (get-buffer-window erc-status-sidebar-buffer-name nil)
       (erc-status-sidebar-close)
-    (erc-status-sidebar-open)))
+    (let (erc-status-sidebar-singular)
+      (erc-status-sidebar-open))))
 
 (defun erc-status-sidebar-get-channame (buffer)
   "Return name of BUFFER with all leading \"#\" characters removed."
@@ -174,6 +286,98 @@ erc-status-sidebar-default-chansort
                    (string< (erc-status-sidebar-get-channame x)
                             (erc-status-sidebar-get-channame y)))))
 
+(defvar erc-status-sidebar--trimpat nil)
+(defvar erc-status-sidebar--prechan nil)
+
+(defun erc-status-sidebar-prefer-target-as-name (buffer)
+  "Return some name to represent buffer in the sidebar."
+  (if-let ((target (buffer-local-value 'erc--target buffer)))
+      (cond ((and erc-status-sidebar--trimpat (erc--target-channel-p target))
+             (string-trim-left (erc--target-string target)
+                               erc-status-sidebar--trimpat))
+            ((and erc-status-sidebar--prechan (erc--target-channel-p target))
+             (concat erc-status-sidebar--prechan
+                     (erc--target-string target)))
+            (t (erc--target-string target)))
+    (buffer-name buffer)))
+
+;; This could be converted into an option if people want.
+(defvar erc-status-sidebar--show-disconnected t)
+
+(defun erc-status-sidebar-all-target-buffers (process)
+  (erc-buffer-filter (lambda ()
+                       (and erc--target
+                            (or erc-status-sidebar--show-disconnected
+                                (erc-server-process-alive))))
+                     process))
+
+;; FIXME profile this.  Rebuilding the graph every time track updates
+;; seems wasteful for occasions where server messages are processed
+;; unthrottled, such as during history playback.  If it's a problem,
+;; we should look into rewriting this using `ewoc' or some other
+;; solution that maintains a persistent model.
+(defun erc-status-sidebar-default-allsort (target-buffers)
+  "Return a list of servers interspersed with their targets."
+  (mapcan (pcase-lambda (`(,proc . ,chans))
+            (cons (process-buffer proc)
+                  (let ((erc-status-sidebar--trimpat
+                         (and (eq erc-status-sidebar-style 'all-mixed)
+                              (with-current-buffer (process-buffer proc)
+                                (when-let ((ch-pfxs (erc--get-isupport-entry
+                                                     'CHANTYPES 'single)))
+                                  (regexp-quote ch-pfxs)))))
+                        (erc-status-sidebar--prechan
+                         (and (eq erc-status-sidebar-style
+                                  'all-queries-first)
+                              "\C-?")))
+                    (sort chans
+                          (lambda (x y)
+                            (string<
+                             (erc-status-sidebar-prefer-target-as-name x)
+                             (erc-status-sidebar-prefer-target-as-name y)))))))
+          (sort (seq-group-by (lambda (b)
+                                (buffer-local-value 'erc-server-process b))
+                              target-buffers)
+                (lambda (a b)
+                  (string< (buffer-name (process-buffer (car a)))
+                           (buffer-name (process-buffer (car b))))))))
+
+(defvar-local erc-status-sidebar--active-marker nil
+  "Marker indicating currently active buffer.")
+
+(defun erc-status-sidebar--set-active-line (erc-buffer)
+  (when (and erc-status-sidebar-highlight-active-buffer
+             (eq (window-buffer (and (minibuffer-window-active-p
+                                      (selected-window))
+                                     (minibuffer-selected-window)))
+                 erc-buffer))
+    (set-marker erc-status-sidebar--active-marker (point))))
+
+(defun erc-status-sidebar-default-insert (channame chanbuf _chanlist)
+  "Insert CHANNAME followed by a newline.
+Maybe arrange to highlight line if CHANBUF is showing in the
+focused window."
+  (erc-status-sidebar--set-active-line chanbuf)
+  (insert channame "\n"))
+
+(defun erc-status-sidebar-pad-hierarchy (bufname buffer buflist)
+  "Prefix BUFNAME to emphasize BUFFER's role in BUFLIST."
+  (if (and (buffer-live-p buffer) (buffer-local-value 'erc--target buffer))
+      (insert " ")
+    (unless (eq buffer (car buflist))
+      (insert "\n"))) ;  ^L
+  (when bufname
+    (erc-status-sidebar--set-active-line buffer))
+  (insert (or bufname
+              (and-let* (((not (buffer-live-p buffer)))
+                         (next (cadr (member buffer buflist)))
+                         ((buffer-live-p next))
+                         (proc (buffer-local-value 'erc-server-process next))
+                         (id (process-get proc 'erc-networks--id)))
+                (symbol-name (erc-networks--id-symbol id)))
+              "???")
+          "\n"))
+
 (defun erc-status-sidebar-default-chan-format (channame
                                                &optional num-messages erc-face)
   "Format CHANNAME for display in the sidebar.
@@ -193,43 +397,111 @@ erc-status-sidebar-default-chan-format
 (defun erc-status-sidebar-refresh ()
   "Update the content of the sidebar."
   (interactive)
-  (let ((chanlist (apply erc-status-sidebar-channel-sort
-                         (erc-channel-list nil) nil)))
+  (pcase-let* ((`(,list-fn ,sort-fn ,name-fn ,fmt-fn ,insert-fn)
+                (pcase erc-status-sidebar-style
+                  ('channels-only (list #'erc-channel-list
+                                        erc-status-sidebar-channel-sort
+                                        #'erc-status-sidebar-get-channame
+                                        erc-status-sidebar-channel-format
+                                        #'erc-status-sidebar-default-insert))
+                  ((or 'all-mixed 'all-queries-first 'all-channels-first)
+                   '(erc-status-sidebar-all-target-buffers
+                     erc-status-sidebar-default-allsort
+                     erc-status-sidebar-prefer-target-as-name
+                     erc-status-sidebar-default-chan-format
+                     erc-status-sidebar-pad-hierarchy))
+                  (v v)))
+               (chanlist (apply sort-fn (funcall list-fn nil) nil))
+               (window nil)
+               (winstart nil))
     (with-current-buffer (erc-status-sidebar-get-buffer)
+      (setq window (get-buffer-window nil erc-status-sidebar-singular)
+            winstart (and window (window-start window)))
       (erc-status-sidebar-writable
        (delete-region (point-min) (point-max))
        (goto-char (point-min))
+       (if erc-status-sidebar--active-marker
+           (set-marker erc-status-sidebar--active-marker nil)
+         (setq erc-status-sidebar--active-marker (make-marker)))
        (dolist (chanbuf chanlist)
          (let* ((tup (seq-find (lambda (tup) (eq (car tup) chanbuf))
                                erc-modified-channels-alist))
                 (count (if tup (cadr tup)))
                 (face (if tup (cddr tup)))
-                (channame (apply erc-status-sidebar-channel-format
-                                 (buffer-name chanbuf) count face nil))
+                (face (if (or (not (buffer-live-p chanbuf))
+                              (not (erc-server-process-alive chanbuf)))
+                          `(shadow ,face)
+                        face))
+                (channame (apply fmt-fn
+                                 (copy-sequence (funcall name-fn chanbuf))
+                                 count face nil))
                 (cnlen (length channame)))
            (put-text-property 0 cnlen 'erc-buf chanbuf channame)
            (put-text-property 0 cnlen 'mouse-face 'highlight channame)
            (put-text-property
             0 cnlen 'help-echo
             "mouse-1: switch to buffer in other window" channame)
-           (insert channame "\n")))))))
+           (funcall insert-fn channame chanbuf chanlist)))
+       (when winstart
+         (set-window-point window winstart)
+         (with-selected-window window (recenter 0)))
+       (when (and erc-status-sidebar-highlight-active-buffer
+                  (marker-buffer erc-status-sidebar--active-marker))
+         (goto-char erc-status-sidebar--active-marker)
+         (require 'hl-line)
+         (unless hl-line-mode (hl-line-mode +1))
+         (hl-line-highlight))))))
 
 (defun erc-status-sidebar-kill ()
   "Close the ERC status sidebar and its buffer."
   (interactive)
+  (when (and erc-bufbar-mode (not erc--module-toggle-prefix-arg))
+    (erc-bufbar-mode -1))
   (ignore-errors (kill-buffer erc-status-sidebar-buffer-name)))
 
 (defun erc-status-sidebar-click (event)
   "Handle click EVENT in `erc-status-sidebar-mode-map'."
   (interactive "e")
   (save-excursion
-    (let ((window (posn-window (event-end event)))
+    (let ((window (posn-window (event-start event)))
           (pos (posn-point (event-end event))))
-      (set-buffer (window-buffer window))
-      (let ((buf (get-text-property pos 'erc-buf)))
-        (when buf
-          (select-window window)
-          (switch-to-buffer-other-window buf))))))
+      ;; Current buffer is "ERC Status" and its window is selected
+      (cl-assert (eq major-mode 'erc-status-sidebar-mode))
+      (cl-assert (eq (selected-window) window))
+      (cl-assert (eq (window-buffer window) (current-buffer)))
+      (when-let ((buf (get-text-property pos 'erc-buf)))
+        ;; Option operates relative to last selected window
+        (select-window (get-mru-window nil nil 'not-selected))
+        (pop-to-buffer buf erc-status-sidebar-click-display-action)))))
+
+(defun erc-status-sidebar-scroll-up (lines)
+  "Scroll sidebar buffer's content LINES linse upward.
+If LINES is nil, scroll up a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window lines)))
+
+(defun erc-status-sidebar-scroll-down (lines)
+  "Scroll sidebar buffer's content LINES lines downward.
+If LINES is nil, scroll down a full screen's worth."
+  (interactive "P")
+  (let ((other-window-scroll-buffer (erc-status-sidebar-get-buffer)))
+    (scroll-other-window-down lines)))
+
+(defun erc-status-sidebar-recenter (arg)
+  "Recenter the status sidebar.
+Expect `erc-status-sidebar-highlight-active-buffer' to be non-nil
+and to be invoked in a buffer matching the line currently
+highlighted."
+  (interactive "P")
+  (let* ((buf (erc-status-sidebar-get-buffer))
+         (win (get-buffer-window buf)))
+    (with-current-buffer buf
+      (when (and erc-status-sidebar--active-marker
+                 (marker-position erc-status-sidebar--active-marker))
+        (with-selected-window win
+          (goto-char erc-status-sidebar--active-marker)
+          (recenter arg t))))))
 
 (defvar erc-status-sidebar-mode-map
   (let ((map (make-sparse-keymap)))
@@ -268,13 +540,17 @@ erc-status-sidebar-set-window-preserve-size
 Note that preserve status needs to be reset when the window is
 manually resized, so `erc-status-sidebar-mode' adds this function
 to the `window-configuration-change-hook'."
-  (when (and (eq (selected-window) (erc-status-sidebar-get-window))
+  (when (and (eq (selected-window) (let (erc-status-sidebar-singular)
+                                     (erc-status-sidebar-get-window)))
              (fboundp 'window-preserve-size))
     (unless (eq (window-total-width) (window-min-size nil t))
       (apply #'window-preserve-size (selected-window) t t nil))))
 
 (define-derived-mode erc-status-sidebar-mode special-mode "ERC Sidebar"
   "Major mode for ERC status sidebar."
+  ;; Users invoking M-x erc-status-sidebar-mode most likely expect to
+  ;; summon the module's minor-mode, `erc-bufbar-mode'.
+  :interactive nil
   ;; Don't scroll the buffer horizontally, if a channel name is
   ;; obscured then the window can be resized.
   (setq-local auto-hscroll-mode nil)
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
new file mode 100644
index 00000000000..aec61333e0b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -0,0 +1,93 @@
+;;; erc-scenarios-status-sidebar.el --- sidebar/speedbar -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+(require 'erc-status-sidebar)
+
+
+(ert-deftest erc-scenarios-status-sidebar--bufbar ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(bufbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit"))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (ert-info ("Activity marker is in the right spot")
+        (let ((obuf (window-buffer))) ; *scratch*
+          (set-window-buffer (selected-window) "#foo")
+          (erc-d-t-wait-for 5
+              (when noninteractive
+                (erc-status-sidebar-refresh))
+            (with-current-buffer "*ERC Status*"
+              (and (marker-position erc-status-sidebar--active-marker)
+                   (goto-char erc-status-sidebar--active-marker)
+                   ;; The " [N]" suffix disappears because it's selected
+                   (search-forward "#foo" (pos-eol) t))))
+          (set-window-buffer (selected-window) obuf))))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "*ERC Status*"))
+      (ert-info ("Hierarchy printed correctly")
+        (funcall expect 10 "barnet [")
+        (funcall expect 10 "#bar [")
+        (funcall expect 10 "foonet [")
+        (funcall expect 10 "#foo")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (should (get-buffer-window "*ERC Status*"))
+        (erc-bufbar-mode -1)
+        (should-not (get-buffer-window "*ERC Status*"))
+        (erc-status-sidebar-kill)
+        (should-not (get-buffer "*ERC Status*"))))))
+
+;;; erc-scenarios-status-sidebar.el ends here
diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
index 4ac4a3e5968..10b742fdb34 100644
--- a/test/lisp/erc/resources/base/gapless-connect/foonet.eld
+++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
@@ -1,7 +1,7 @@
 ;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :foonet:changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
  (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
  (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
  (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
@@ -21,7 +21,7 @@
  ;; No mode answer
  (0 ":irc.znc.in 306 tester :You have been marked as being away")
  (0 ":tester!~u@HIDDEN JOIN #foo")
- (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob tester")
  (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
  (0 ":***!znc@HIDDEN PRIVMSG #foo :Buffer Playback...")
  (0 ":alice!~u@HIDDEN PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.")
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0004-5.6-Add-erc-status-sidebar-integration-to-erc-speedb.patch

From fd2ec89c40dd52322c8196c3653e06c937176bc7 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 4/5] [5.6] Add erc-status-sidebar integration to erc-speedbar

* lisp/erc/erc-speedbar.el: Require `erc-button' atop file and don't
bother loading `dframe', which `speedbar' handles for us.
(erc-speedbar-hide-mode-topic): New option determining whether to hide
the mode and topic.
(erc-speedbar-my-nick-face): New option for determining face to use
when displaying user's current nick.
(erc-speedbar-browser): Call `erc-install-speedbar-variables'
explicitly and remove top-level `with-eval-after-load'.
(erc-speedbar-insert-target): Add parenthesized channel count after
channel name in server and channel views.
(erc-speedbar-expand-channel): Hide mode and topic depending on option
`erc-speedbar-hide-mode-topic' and pass buffer to
`erc-speedbar-insert-user'.
(erc-speedbar--nick-face-function): New internal function-interface
variable.
(erc-speedbar--highlight-self-and-ops): New function to serve as
default value for `erc-speedbar--nick-face-function'.
(erc-speedbar--on-click): Dispatch `erc-nick-popup' after trimming
status chars.
(erc-speedbar-insert-user): Revise doc string.  Call
`erc-speedbar--nick-face-function' to determine face.  Change
token for both expansion and on-click text props.  Assign
`erc-speedbar--on-click' as the mouse handler for nick items.
(erc-speedbar-emulated-sidebar-width): New option to control width
of nicknames list window.
(erc-speedbar): Mention `erc-nickbar-mode' in group doc string.
(erc-speedbar--buffer-options): Variable to override options locally
in speedbar buffer.
(erc-speedbar--hidden-speedbar-frame): Add variable to hold original
`speedbar-frame' before spoofing by setting to selected frame
containing window showing ERC buffer.
(erc-speedbar--dframe-controlled) Add function to overwrite
`speedbar-frame-mode' as `dframe-controlled' in speedbar buffer.
(erc-speedbar--emulate-sidebar-set-window-preserve-size,
erc-speedbar--status-sidebar-mode--unhook): Add function
to ensure status sidebar is showing correctly and helper to
unregister from hook on teardown.
(erc-speedbar--emulate-sidebar): Add function to
control sidebar nicknames setup.
(erc-speedbar--toggle-nicknames-sidebar): Add toggle function
for sidebar or speedbar.
(erc-speedbar--ensure): Add helper function to show speedbar if its
hidden or create one if none exists.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable):
Add new module.
(erc-speedbar-toggle-nicknames-window-lock,
erc-speedbar-close-nicknames-window): Add commands to close speedbar
window and toggle its cyclability.
(erc-speedbar--compose-nicks-face): Add helper for nicks integration.
* test/lisp/erc/erc-scenarios-status-sidebar.el
(erc-scenarios-status-sidebar--nickbar): New test, unfortunately only
runs in terminals.
---
 lisp/erc/erc-speedbar.el                      | 284 ++++++++++++++++--
 test/lisp/erc/erc-scenarios-status-sidebar.el |  76 +++++
 2 files changed, 342 insertions(+), 18 deletions(-)

diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index a9443e0ea17..21ad4c6f97a 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -32,20 +32,31 @@
 ;;   update-channel, update-nick, remove-nick-from-channel, ...
 ;; * Use indicator-strings for op/voice
 ;; * Extract/convert face notes field from bbdb if available
+;; * Write tests that run in a term-mode subprocess
 ;;
 ;;; Code:
 
 (require 'erc)
 (require 'erc-goodies)
+(require 'erc-button)
 (require 'speedbar)
-(condition-case nil (require 'dframe) (error nil))
 
 ;;; Customization:
 
 (defgroup erc-speedbar nil
-  "Integration of ERC in the Speedbar."
+  "Speedbar integration for ERC.
+To open an ERC-flavored speedbar in a separate frame, run the
+command `erc-speedbar-browser'.  To use a window-based proxy
+instead, run \\[erc-nickbar-mode] in a connected ERC buffer or
+put `nickbar' in `erc-modules' before connecting.  See Info
+node `(speedbar) Top' for more about the underlying integration."
   :group 'erc)
 
+(defcustom erc-speedbar-nicknames-window-width 18
+  "Default width of the nicknames sidebar (in columns)."
+  :package-version '(ERC . "5.7")
+  :type 'integer)
+
 (defcustom erc-speedbar-sort-users-type 'activity
   "How channel nicknames are sorted.
 
@@ -56,6 +67,23 @@ erc-speedbar-sort-users-type
 		 (const :tag "Sort users alphabetically" alphabetical)
 		 (const :tag "Do not sort users" nil)))
 
+(defcustom erc-speedbar-hide-mode-topic 'headerline
+  "Hide mode and topic lines."
+  :package-version '(ERC . "5.7") ; FIXME sync on release
+  :type '(choice (const :tag "Always show" nil)
+                 (const :tag "Always hide" t)
+                 (const :tag "Omit when headerline visible" headerline)))
+
+(defcustom erc-speedbar-my-nick-face t
+  "A face to use for your nickname.
+When the value is t, ERC uses `erc-current-nick-face' if
+`erc-match' has been loaded and `erc-my-nick-face' otherwise.
+When using the `nicks' module, you can see your nick as it
+appears to others by coordinating with the option
+`erc-nicks-skip-faces'."
+  :package-version '(ERC . "5.7")
+  :type '(choice face (const :tag "Match or own input face" t)))
+
 (defvar erc-speedbar-key-map nil
   "Keymap used when in erc display mode.")
 
@@ -88,10 +116,6 @@ erc-speedbar-menu-items
 		     (looking-at "[0-9]+: *.-. "))])
   "Additional menu-items to add to speedbar frame.")
 
-;; Make sure our special speedbar major mode is loaded
-(with-eval-after-load 'speedbar
-  (erc-install-speedbar-variables))
-
 ;;; ERC hierarchy display method
 ;;;###autoload
 (defun erc-speedbar-browser ()
@@ -99,6 +123,7 @@ erc-speedbar-browser
 This will add a speedbar major display mode."
   (interactive)
   (require 'speedbar)
+  (erc-install-speedbar-variables)
   ;; Make sure that speedbar is active
   (speedbar-frame-mode 1)
   ;; Now, throw us into Info mode on speedbar.
@@ -169,12 +194,18 @@ erc-speedbar-channel-buttons
 	  t)))))
 
 (defun erc-speedbar-insert-target (buffer depth)
-  (if (with-current-buffer buffer
-	(erc-channel-p (erc-default-target)))
-      (speedbar-make-tag-line
-       'bracket ?+ 'erc-speedbar-expand-channel buffer
-       (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
-       depth)
+  (if (erc--target-channel-p (buffer-local-value 'erc--target buffer))
+      (progn
+        (speedbar-make-tag-line
+         'bracket ?+ 'erc-speedbar-expand-channel buffer
+         (erc--target-string (buffer-local-value 'erc--target buffer))
+         'erc-speedbar-goto-buffer buffer nil
+         depth)
+        (save-excursion
+          (forward-line -1)
+          (let ((table (buffer-local-value 'erc-channel-users buffer)))
+            (speedbar-add-indicator (format "(%d)" (hash-table-count table)))
+            (rx "(" (+ (any "0-9")) ")"))))
     ;; Query target
     (speedbar-make-tag-line
      nil nil nil nil
@@ -220,6 +251,13 @@ erc-speedbar-expand-channel
 	    'angle ?i nil nil
 	    (concat "Topic: " topic) nil nil nil
 	    (1+ indent)))
+         (unless (pcase erc-speedbar-hide-mode-topic
+                   ('nil 'show)
+                   ('headerline (null erc-header-line-format)))
+           (save-excursion
+             (goto-char (point-max))
+             (forward-line (if (string= topic "") -1 -2))
+             (put-text-property (pos-bol) (point-max) 'invisible t)))
 	 (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical)
 			     (erc-sort-channel-users-alphabetically
 			      (with-current-buffer channel
@@ -233,17 +271,52 @@ erc-speedbar-expand-channel
 	   (when names
 	     (speedbar-with-writable
 	      (dolist (entry names)
-		(erc-speedbar-insert-user entry ?+ (1+ indent))))))))))
+                (erc-speedbar-insert-user entry ?+ (1+ indent) channel)))))))))
    ((string-search "-" text)
     (speedbar-change-expand-button-char ?+)
     (speedbar-delete-subblock indent))
    (t (error "Ooops... not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun erc-speedbar-insert-user (entry exp-char indent)
+(defvar erc-speedbar--nick-face-function #'erc-speedbar--highlight-self-and-ops
+  "Function called when finding a face for fontifying nicks.
+Called with the proposed nick, the `erc-server-user', and the
+`erc-channel-user'.  Should return any valid face, possibly
+composed or anonymous, or nil.")
+
+(defun erc-speedbar--highlight-self-and-ops (buffer user cuser)
+  "Highlight own nick and op'd users in the speedbar."
+  (with-current-buffer buffer
+    (if (erc-current-nick-p (erc-server-user-nickname user))
+        (pcase erc-speedbar-my-nick-face
+          ('t (if (featurep 'erc-match)
+                  'erc-current-nick-face
+                'erc-my-nick-face))
+          (v v))
+      ;; FIXME overload `erc-channel-user-owner-p' and friends to
+      ;; accept an `erc-channel-user' object and replace this unrolled
+      ;; stuff with a single call to `erc-get-user-mode-prefix'.
+      (and cuser (or (erc-channel-user-owner cuser)
+                     (erc-channel-user-admin cuser)
+                     (erc-channel-user-op cuser)
+                     (erc-channel-user-halfop cuser)
+                     (erc-channel-user-voice cuser))
+           erc-button-nickname-face))))
+
+(defun erc-speedbar--on-click (nick sbtoken _indent)
+  ;; 0: finger, 1: name, 2: info, 3: buffer-name
+  (with-current-buffer (nth 3 sbtoken)
+    (erc-nick-popup (string-trim-left nick "[~&@%+]+"))))
+
+(defun erc-speedbar-insert-user (entry exp-char indent &optional buffer)
   "Insert one user based on the channel member list ENTRY.
-EXP-CHAR is the expansion character to use.
-INDENT is the current indentation level."
+Expect EXP-CHAR to be the expansion character to use, INDENT the
+current indentation level, and BUFFER the associated channel or
+query buffer.  Set the `speedbar-function' text property to
+`erc-speedbar--on-click', which is called with the formatted
+nick, a so-called \"token\", and the indent level.  The token is
+a list of four items: the userhost, the GECOS, the current
+`erc-server-user' info slot, and the associated buffer."
   (let* ((user (car entry))
 	 (cuser (cdr entry))
 	 (nick (erc-server-user-nickname user))
@@ -255,11 +328,12 @@ erc-speedbar-insert-user
 	 (op (and cuser (erc-channel-user-op cuser)))
 	 (nick-str (concat (if op "@" "") (if voice "+" "") nick))
 	 (finger (concat login (when (or login host) "@") host))
-	 (sbtoken (list finger name info)))
+         (sbtoken (list finger name info (buffer-name buffer))))
     (if (or login host name info) ; we want to be expandable
 	(speedbar-make-tag-line
 	 'bracket ?+ 'erc-speedbar-expand-user sbtoken
-	 nick-str nil sbtoken nil
+         nick-str #'erc-speedbar--on-click sbtoken
+         (funcall erc-speedbar--nick-face-function buffer user cuser)
 	 indent)
       (when (equal exp-char ?-)
 	(forward-line -1)
@@ -357,6 +431,180 @@ erc-speedbar-item-info
 	  (t
 	   (message "%s" txt)))))
 
+
+;;;; Status-sidebar integration
+
+(defvar erc-status-sidebar-buffer-name)
+(declare-function erc-status-sidebar-set-window-preserve-size
+                  "erc-status-sidebar" nil)
+(declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil)
+
+(defvar erc-speedbar--buffer-options
+  '((speedbar-update-flag . t)
+    (speedbar-use-images . nil)
+    (speedbar-hide-button-brackets-flag . t)))
+
+(defvar erc-speedbar--hidden-speedbar-frame nil)
+
+(defun erc-speedbar--emulate-sidebar-set-window-preserve-size ()
+  (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer))
+        (display-buffer-overriding-action
+         `(display-buffer-in-side-window
+           . ((side . right)
+              (window-width . ,erc-speedbar-nicknames-window-width)))))
+    (erc-status-sidebar-set-window-preserve-size)
+    (when-let ((window (get-buffer-window speedbar-buffer)))
+      (set-window-parameter window 'no-other-window nil)
+      (internal-show-cursor window t))))
+
+(defun erc-speedbar--status-sidebar-mode--unhook ()
+  "Remove hooks installed by `erc-status-sidebar-mode'."
+  (remove-hook 'window-configuration-change-hook
+               #'erc-speedbar--emulate-sidebar-set-window-preserve-size))
+
+(defun erc-speedbar--emulate-sidebar ()
+  (require 'erc-status-sidebar)
+  (cl-assert speedbar-frame)
+  (cl-assert (eq speedbar-buffer (current-buffer)))
+  (cl-assert (eq speedbar-frame (selected-frame)))
+  (setq erc-speedbar--hidden-speedbar-frame speedbar-frame
+        dframe-controlled #'erc-speedbar--dframe-controlled)
+  (add-hook 'window-configuration-change-hook
+            #'erc-speedbar--emulate-sidebar-set-window-preserve-size nil t)
+  (add-hook 'kill-buffer-hook
+            #'erc-speedbar--status-sidebar-mode--unhook nil t)
+  (with-current-buffer speedbar-buffer
+    (pcase-dolist (`(,var . ,val) erc-speedbar--buffer-options)
+      (set (make-local-variable var) val)))
+  (when (memq 'nicks erc-modules)
+    (with-current-buffer speedbar-buffer
+      (add-function :around (local 'erc-speedbar--nick-face-function)
+                    #'erc-speedbar--compose-nicks-face))))
+
+(defun erc-speedbar--toggle-nicknames-sidebar (arg)
+  (let ((force (numberp arg)))
+    (if speedbar-buffer
+        (progn
+          (cl-assert (buffer-live-p speedbar-buffer))
+          (if (or (and force (< arg 0))
+                  (and (not force) (get-buffer-window speedbar-buffer nil)))
+              (erc-speedbar-close-nicknames-window nil)
+            (when (or (not force) (>= arg 0))
+              (with-selected-frame speedbar-frame
+                (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
+      (when (or (not force) (>= arg 0))
+        (let ((speedbar-frame-parameters (backquote-list*
+                                          '(visibility . nil)
+                                          '(no-other-frame . t)
+                                          speedbar-frame-parameters))
+              (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
+          (erc-speedbar-browser)
+          ;; If we put the remaining parts in the "create hook" along
+          ;; with everything else, the frame with `window-main-window'
+          ;; gets raised and steals focus if you've switched away from
+          ;; Emacs in the meantime.
+          (make-frame-invisible speedbar-frame)
+          (select-frame (setq speedbar-frame (previous-frame)))
+          (erc-speedbar--emulate-sidebar-set-window-preserve-size))))))
+
+(defun erc-speedbar--ensure (&optional force)
+  (when (or (erc-server-buffer) force)
+    (erc-speedbar--toggle-nicknames-sidebar +1)
+    (speedbar-enable-update)))
+
+;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
+(define-erc-module nickbar nil
+  "Show nicknames in a side window.
+When enabling, create a speedbar session if one doesn't exist and
+show its buffer in an `erc-status-sidebar' window instead of a
+separate frame.  When disabling, close the window or, with a
+negative prefix arg, destroy the session.
+
+WARNING: it's suspected that this module may perform unwanted
+side effects like raising frames and/or stealing input focus.  If
+you witness such an occurrence, and can reproduce it, please file
+a bug report with \\[erc-bug]."
+  ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (erc-speedbar--ensure)
+   (unless (or erc--updating-modules-p
+               (and-let* ((speedbar-buffer)
+                          (win (get-buffer-window speedbar-buffer 'all-frames))
+                          ((eq speedbar-frame (window-frame win))))))
+     (if speedbar-buffer
+         (erc-speedbar--ensure 'force)
+       (cl-assert (not (derived-mode-p 'erc-mode)))
+       (setq erc-nickbar-mode nil)
+       (user-error "Cannot initialize `%s' in a non-ERC buffer"
+                   'erc-nickbar-mode))))
+  ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (speedbar-disable-update)
+   (erc-speedbar--toggle-nicknames-sidebar -1)
+   (when-let* ((arg erc--module-toggle-prefix-arg)
+               ((numberp arg))
+               ((< arg 0)))
+     (erc-speedbar-close-nicknames-window 'kill))))
+
+(defun erc-speedbar--dframe-controlled (arg)
+  (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
+    (when erc-nickbar-mode
+      (erc-nickbar-mode -1))
+    (setq speedbar-frame erc-speedbar--hidden-speedbar-frame
+          erc-speedbar--hidden-speedbar-frame nil)
+    ;; It's unknown whether leaving the frame invisible interferes
+    ;; with the upstream teardown procedure.
+    (when (display-graphic-p)
+      (make-frame-visible speedbar-frame))
+    (speedbar-frame-mode arg)
+    (when speedbar-buffer
+      (kill-buffer speedbar-buffer)
+      (setq speedbar-buffer nil))))
+
+(defun erc-speedbar-toggle-nicknames-window-lock ()
+  "Toggle whether nicknames window is selectable with \\[other-window]."
+  (interactive)
+  (unless erc-nickbar-mode
+    (user-error "`erc-nickbar-mode' inactive"))
+  (when-let* ((window (get-buffer-window speedbar-buffer)))
+    (let ((val (window-parameter window 'no-other-window)))
+      (set-window-parameter window 'no-other-window (not val))
+      (message "nick-window: %s" (if val "selectable" "protected")))))
+
+(defun erc-speedbar-close-nicknames-window (kill)
+  (interactive "P")
+  (if kill
+      (with-current-buffer speedbar-buffer
+        (dframe-close-frame)
+        (cl-assert (not erc-nickbar-mode))
+        (setq erc-speedbar--hidden-speedbar-frame nil))
+    (dolist (window (get-buffer-window-list speedbar-buffer nil t))
+      (unless (frame-root-window-p window)
+        (when erc-speedbar--hidden-speedbar-frame
+          (cl-assert (not (eq (window-frame window)
+                              erc-speedbar--hidden-speedbar-frame))))
+        (delete-window window)))))
+
+
+;;;; Nicks integration
+
+(defvar erc-nicks--phony-face)
+(declare-function erc-nicks--highlight "erc-nicks" (nick-object))
+
+(defun erc-speedbar--compose-nicks-face (orig buffer user cuser)
+  (require 'erc-nicks)
+  (let ((rv (funcall orig buffer user cuser)))
+    (if-let* ((nobj (make-erc-button--nick
+                     :downcased (erc-downcase (erc-server-user-nickname user))
+                     :user user
+                     :cuser cuser))
+              (erc-nicks--phony-face (or rv t))
+              (nobj (with-current-buffer buffer
+                      (erc-nicks--highlight nobj)))
+              (face (erc-button--nick-erc-button-nickname-face nobj))
+              ((not (eq face erc-button-nickname-face))))
+        (cons face (ensure-list rv))
+      rv)))
+
+
 (provide 'erc-speedbar)
 ;;; erc-speedbar.el ends here
 ;;
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index aec61333e0b..6ac1821ebb7 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -90,4 +90,80 @@ erc-scenarios-status-sidebar--bufbar
         (erc-status-sidebar-kill)
         (should-not (get-buffer "*ERC Status*"))))))
 
+;; No need to pollute the global obarray since we can't currently run
+;; this on EMBA (it requires a terminal).  Please try running this
+;; test interactively with both graphical Emacs and non.
+(declare-function erc-nickbar-mode "erc-speedbar" (arg))
+(declare-function erc-speedbar-close-nicknames-window "erc-speedbar" (kill))
+(declare-function speedbar-timer-fn "speedbar" nil)
+(defvar erc-nickbar-mode)
+(defvar speedbar-buffer)
+
+(ert-deftest erc-scenarios-status-sidebar--nickbar ()
+  :tags '(:unstable :expensive-test)
+  (when noninteractive (ert-skip "Interactive only"))
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/gapless-connect")
+       (erc-server-flood-penalty 0.1)
+       (erc-server-flood-penalty erc-server-flood-penalty)
+       (erc-modules `(nickbar ,@erc-modules))
+       (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to two different endpoints")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "MOTD File is missing"))
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "barnet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "marked as being away")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#bar"))
+    (with-current-buffer (pop-to-buffer "#bar")
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "his second fit")
+      (erc-d-t-wait-for 10 (and speedbar-buffer (get-buffer speedbar-buffer)))
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#bar (3)")
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 '(| "@mike" "joe"))
+        (funcall expect 10 "tester")))
+
+    (erc-d-t-wait-for 20 (get-buffer "#foo"))
+    (with-current-buffer (pop-to-buffer "#foo")
+      (delete-other-windows)
+      (funcall expect 10 "was created on")
+      (funcall expect 2 "no use of him")
+      (speedbar-timer-fn)
+      (with-current-buffer speedbar-buffer
+        (funcall expect 10 "#foo (3)")
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 '(| "alice" "@bob"))
+        (funcall expect 10 "tester")))
+
+    (with-current-buffer "#foo"
+      (ert-info ("Core toggle and kill commands work")
+        ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
+        ;; etc. for testing commands that call those same functions.
+        (erc-nickbar-mode -1)
+        (should-not (and speedbar-buffer
+                         (get-buffer-window speedbar-buffer)))
+        (erc-nickbar-mode +1)
+        (should (and speedbar-buffer
+                     (get-buffer-window speedbar-buffer)))
+        (should (get-buffer " SPEEDBAR"))
+        (erc-speedbar-close-nicknames-window 'kill)
+        (should-not (get-buffer " SPEEDBAR"))
+        (should-not erc-nickbar-mode)
+        (should-not (cdr (frame-list)))))))
+
 ;;; erc-scenarios-status-sidebar.el ends here
-- 
2.40.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0005-5.6-Add-new-ERC-modules-bufbar-and-nickbar.patch

From 93f31ce4e062acd8ea6e87ea8023707b9e4b383b Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Thu, 4 May 2023 00:01:11 -0700
Subject: [PATCH 5/5] [5.6] Add new ERC modules bufbar and nickbar

* doc/misc/erc.texi: Add `bufbar' and `nickbar' to known modules.
* erc/ERC-NEWS: Mention erc-status-sidebar and erc-speedbar
improvements.
* lisp/erc/erc.el (erc-modules): Add `bufbar' and `nickbar' to
selection of offered modules.
* test/lisp/erc/erc-tests.el (erc-tests--modules): Add `bufbar' and
`nickbar'.
---
 doc/misc/erc.texi          |  9 +++++++++
 etc/ERC-NEWS               | 16 ++++++++++++++++
 lisp/erc/erc.el            |  2 ++
 test/lisp/erc/erc-tests.el |  4 ++--
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index f7036e57638..7c625c2fd02 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -418,6 +418,10 @@ Modules
 @item bbdb
 Integrate with the Big Brother Database
 
+@cindex modules, bufbar
+@item bufbar
+List ERC buffers belonging to a live connection in a side window
+
 @cindex modules, button
 @item button
 Buttonize URLs, nicknames, and other text
@@ -463,6 +467,11 @@ Modules
 @item nicks
 Automatically colorize nicks
 
+@cindex modules, nickbar
+@item nickbar
+List participating nicks for the current target buffer in a side
+window
+
 @cindex modules, noncommands
 @item noncommands
 Don't display non-IRC commands after evaluation
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 41af8b88277..6922ae22482 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -72,6 +72,22 @@ widget has been an age-old annoyance for new users.  Previously
 ineffective, this method now actually works, but it also admonishes
 users to edit the 'erc-modules' widget instead.
 
+** ERC's status-sidebar now has an accompanying module.
+Users can now add 'bufbar' to 'erc-modules' to achieve the same effect
+as toggling 'erc-status-sidebar-open' manually at the start of an IRC
+session.  The module has also been outfitted to show channels and
+queries under their respective servers by default.  To avoid
+confusion, the major mode used for the sidebar buffer itself,
+'erc-status-sidebar-mode', is no longer available interactively.
+
+** A new spin on a classic integration in erc-speedbar.
+Add 'nickbar' to 'erc-modules' to spawn a dynamically updating side
+window listing all the users in any target buffer.  It's powered by
+the same speedbar.el integration you've always known, except this
+one's optionally accessible from the keyboard, just like any other
+side window.  Hit '<RET>' over a nick to spawn a "/QUERY" or a
+"Lastlog" (Occur) session.  See 'erc-nickbar-mode' for more.
+
 ** The option 'erc-timestamp-use-align-to' is more versatile.
 While this option has always offered to right-align stamps via the
 'display' text property, it's now more effective at doing so when set
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 5a3b312b53b..2f26985f74d 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2006,6 +2006,7 @@ erc-modules
     :greedy t
     (const :tag "autoaway: Set away status automatically" autoaway)
     (const :tag "autojoin: Join channels automatically" autojoin)
+    (const :tag "bufbar: Show ERC buffers in a side window" bufbar)
     (const :tag "button: Buttonize URLs, nicknames, and other text" button)
     (const :tag "capab: Mark unidentified users on servers supporting CAPAB"
            capab-identify)
@@ -2026,6 +2027,7 @@ erc-modules
            move-to-prompt)
     (const :tag "netsplit: Detect netsplits" netsplit)
     (const :tag "networks: Provide data about IRC networks" networks)
+    (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar)
     (const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks)
     (const :tag "noncommands: Don't display non-IRC commands after evaluation"
            noncommands)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index de472527bde..4432dc58082 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1951,9 +1951,9 @@ erc-handle-irc-url
     (kill-buffer "#chan")))
 
 (defconst erc-tests--modules
-  '( autoaway autojoin button capab-identify completion dcc fill identd
+  '( autoaway autojoin bufbar button capab-identify completion dcc fill identd
      imenu irccontrols keep-place list log match menu move-to-prompt netsplit
-     networks nicks noncommands notifications notify page readonly
+     networks nickbar nicks noncommands notifications notify page readonly
      replace ring sasl scrolltobottom services smiley sound
      spelling stamp track truncate unmorse xdcc))
 
-- 
2.40.0


--=-=-=--



------------=_1689300482-2649-1--


Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Tue, 25 Jul 2023 13:33:01 +0000
Resent-Message-ID: <handler.63595.B63595.169029196622427 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169029196622427
          (code B ref 63595); Tue, 25 Jul 2023 13:33:01 +0000
Received: (at 63595) by debbugs.gnu.org; 25 Jul 2023 13:32:46 +0000
Received: from localhost ([127.0.0.1]:44907 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qOI9d-0005pd-NK
	for submit <at> debbugs.gnu.org; Tue, 25 Jul 2023 09:32:46 -0400
Received: from mail-108-mta102.mxroute.com ([136.175.108.102]:46747)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qOI9a-0005pQ-UB
 for 63595 <at> debbugs.gnu.org; Tue, 25 Jul 2023 09:32:44 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta102.mxroute.com (ZoneMTA) with ESMTPSA id
 1898d4079020004cef.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Tue, 25 Jul 2023 13:32:40 +0000
X-Zone-Loop: caf529c14763c309c8bf617e81cecd6efb66f9f1130a
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=QIXpA43qmWN8el5ptuYtzd7lqkrIYK43+gtLx3RL68U=; b=gIQfNu/xl4FCFxMcAz5qF/VjjI
 ZYxQQ/UkvSYwwNIPsObnCKijDJU9a9fe/J2KAKd4tA1kvY1KCt2UbUQZVNgPs4CPobqwPVyTN9p5R
 //odzQtL7862jlol0GrSo6XsoiFrqEMuW6qyzUfkxkyYDiOjmNWiuexvtjIqIlFWVWmYGq5RNsYQ0
 duAG6JT/VYsuLDr+tZ9BlSqmdN6H7EtBGSnVaOeUuke7ZuEorSiNpDmYPrJRC77TuF10UYzRz77ob
 XYs5v8BwUXY7H9QaULtjLOPA4GwcJIMebFSn6IztSdxwzs5t3U6CN2VhNF+vE02uUnCm4SZj2SiST
 PPyv3iPA==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Tue, 25 Jul 2023 06:32:36 -0700
Message-ID: <87o7k0yv4b.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

This may come as a shock, but problems exist in the `bufbar' changes
recently introduced (by me) to erc-status-sidebar.el.

The first involves the new boolean option `erc-status-sidebar-singular'.
No matter what its doc string says, the purpose of this option remains
difficult to describe and its behavior hard to predict. This makes it
only really practical as an internal flag, which is what it should have
been from the get-go and how it's been repurposed in the attached patch.
Initially, this option was intended to alter the behavior of the
minor-mode toggle `erc-bufbar-mode' so that when the option is nil,
toggling the mode in a frame where the sidebar is hidden would summon
it, regardless of the value of the mode's variable. This kind of extreme
DWIM'ness may suit normal, standalone minor modes, but users likely
expect mode toggles for global ERC modules to work more or less
traditionally.

A somewhat related problem stems from my altering the original behavior
of existing status-sidebar commands, like `erc-status-sidebar-open', to
accommodate and promote `erc-bufbar-mode' as a unified entry point. In
retrospect, that probably threatens to anger the rare person who's
become accustomed to those commands over the past couple years and who
may not be interested in the new module at all (for whatever reason).
I've attempted to rectify this in the attached patch so that the newer
behavior only takes effect when `erc-bufbar-mode' is active. This means
users of the module must now issue an M-x erc-status-sidebar-open RET to
see the sidebar in (additional) frames that don't yet have one, but
non-module users will still only ever encounter a single sidebar
instance in an Emacs session.

The last issue involves the sidebar intermittently clobbering the
window's scroll position. I've tried to eradicate this while also
improving the overall responsiveness by having it refresh when users
select another window. Basically, updates were initially tethered to
mode-line changes, which often left users with the wrong buffer
highlighted whenever updates were few and far between. Although this is
now much improved, the change likely adds some overhead, so I've
included an escape hatch while we investigate further.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Simplify-multi-frame-behavior-of-erc-bufbar-mode.patch

From 7b47f05fbc7093db798f2ee421a3082c9febc363 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Sun, 23 Jul 2023 23:09:42 -0700
Subject: [PATCH 1/2] [5.6] Simplify multi-frame behavior of erc-bufbar-mode

* lisp/erc/erc-status-sidebar.el (erc-status-sidebar-singular,
erc-status-sidebar--singular-p): Replace public option, new in ERC
5.6, with the latter, an internal state flag.
(erc-status-sidebar-get-window): Use new name for option turned
ordinary variable `erc-status-sidebar--singular-p'.
(erc-status-sidebar-close): Add comment.
(erc-status-sidebar--open): New function containing the old body of
`erc-status-sidebar-open'.
(erc-bufbar-mode, erc-bufbar-enable, erc-bufbar-disable): Update
variable names.  When disabling, always close window on all frames.
Don't set mode variable to nil when enabling outside of an `erc-mode'
buffer.  This may have made some practical sense but was illogical
since the `erc--setup-buffer-hook' was left as is, meaning the
activation state was still partially enabled.
(erc-status-sidebar-open): Move definition to lower down in file,
after `erc-bufbar-mode'.  When `erc-bufbar-mode' is active, always
create a sidebar if needed, even when another frame is already
displaying one.
(erc-status-toggle-sidebar): When `erc-bufbar-mode' is disabled,
revert to pre-5.6 behavior, ignoring bug fixes.  When the module is
enabled, adopt new behavior of always ensuring the current frame shows
a sidebar, even if another frame already has one.
(erc-status-sidebar-refresh): Save and restore window start in all
windows showing status sidebar buffer after refreshing.  Update
option and variable names.
(erc-status-sidebar--refresh-unless-input): New function to run
`erc-status-sidebar-refresh' unless input is pending or the selected
window's buffer is a minibuffer.
(erc-status-sidebar--post-refresh): Call `erc-status-sidebar-refresh'
wrapper `erc-status-sidebar--refresh-unless-input' instead.
(erc-status-sidebar-refresh-triggers): Add doc string, noting that the
variable is set locally when the option
`erc-status-sidebar-highlight-active-buffer' is non-nil.
(erc-status-sidebar--highlight-refresh-triggers): New variable
containing additional triggers enabled when the option
`erc-status-highlight-active-buffer' is non-nil.
(erc-status-sidebar-set-window-preserve-size): Update var name to
`erc-status-sidebar--singular-p'.
(erc-status-sidebar-mode): Run `erc-status-sidebar--post-refresh' on
`window-selection-change-functions' globally when highlighting active
buffers.  (bug#63595)
---
 lisp/erc/erc-status-sidebar.el | 107 +++++++++++++++++++++------------
 1 file changed, 70 insertions(+), 37 deletions(-)

diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index b8bd7b0065e..a82c846ff1a 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -45,8 +45,8 @@
 ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and
 ;; close the sidebar on all frames.
 
-;; In addition to the commands above, you can also try the all-in-one,
-;; "DWIM" command, `erc-bufbar-mode'.  See its doc string for usage.
+;; In addition to the commands above, you can also try the all-in-one
+;; entry point `erc-bufbar-mode'.  See its doc string for usage.
 
 ;; If you want the status sidebar enabled whenever you use ERC, add
 ;; `bufbar' to `erc-modules'.  Note that this library also has a major
@@ -130,8 +130,11 @@ erc-status-sidebar-style
   `erc-status-sidebar-pad-hierarchy'
 
 for the above-mentioned purposes.  ERC also accepts a list of
-functions to preform these roles a la carte.  See doc strings for
-a description of their expected arguments and return values."
+functions to preform these roles a la carte.  Since the members
+of the above sets aren't really interoperable, we don't offer
+them here as customization choices, but you can still specify
+them manually.  See doc strings for a description of their
+expected arguments and return values."
   :package-version '(ERC . "5.6") ; FIXME sync on release
   :type '(choice (const channels-only)
                  (const all-mixed)
@@ -158,10 +161,12 @@ erc-status-sidebar-click-display-action
                               :key-type symbol
                               :value-type (sexp :tag "Value")))))
 
-(defcustom erc-status-sidebar-singular t
-  "Whether to show the sidebar on all frames or just one (default)."
-  :package-version '(ERC . "5.6") ; FIXME sync on release
-  :type 'boolean)
+(defvar erc-status-sidebar--singular-p t
+  "Whether to restrict the sidebar to a single frame.
+This variable only affects `erc-bufbar-mode'.  Disabling it does
+not arrange for automatically showing the sidebar in all frames.
+Rather, disabling it allows for displaying the sidebar in the
+selected frame even if it's already showing in some other frame.")
 
 (defvar hl-line-mode)
 (declare-function hl-line-highlight "hl-line" nil)
@@ -178,7 +183,7 @@ erc-status-sidebar-get-window
 
 If NO-CREATION is non-nil, the window is not created."
   (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name
-                                           erc-status-sidebar-singular)))
+                                           erc-status-sidebar--singular-p)))
     (unless (or sidebar-window no-creation)
       (with-current-buffer (erc-status-sidebar-get-buffer)
         (setq-local vertical-scroll-bar nil))
@@ -214,7 +219,7 @@ erc-status-sidebar-close
 containing it on the current frame is closed.  See
 `erc-status-sidebar-kill'."
   (interactive "P")
-  (mapcar #'delete-window
+  (mapcar #'delete-window ; FIXME use `mapc'.
           (get-buffer-window-list (erc-status-sidebar-get-buffer)
                                   nil (if all-frames t))))
 
@@ -223,10 +228,8 @@ erc-status-sidebar-writable
   `(let ((buffer-read-only nil))
      ,@body))
 
-;;;###autoload
-(defun erc-status-sidebar-open ()
-  "Open or create a sidebar."
-  (interactive)
+(defun erc-status-sidebar--open ()
+  "Maybe open the sidebar, respecting `erc-status-sidebar--singular-p'."
   (save-excursion
     (if (erc-status-sidebar-buffer-exists-p)
         (erc-status-sidebar-get-window)
@@ -237,11 +240,15 @@ erc-status-sidebar-open
 ;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t)
 (define-erc-module bufbar nil
   "Show `erc-track'-like activity in a side window.
-When enabling, show the sidebar immediately if called from a
-connected ERC buffer.  Otherwise, arrange for doing so on connect
-or whenever next displaying a new ERC buffer.  When disabling,
-hide the status window if it's showing.  With a negative prefix
-arg, also shutdown the session."
+When enabling, show the sidebar immediately in the current frame
+if called from a connected ERC buffer.  Otherwise, arrange for
+doing so on connect or whenever next displaying a new ERC buffer.
+When disabling, hide the status window in all frames.  With a
+negative prefix arg, also shutdown the session.  Normally, this
+module only allows one sidebar window in an Emacs session.  To
+override this, use `erc-status-sidebar-open' to force creation
+and `erc-status-sidebar-close' to hide a single instance on the
+current frame only."
   ((unless erc-track-mode
      (unless (memq 'track erc-modules)
        (erc--warn-once-before-connect 'erc-bufbar-mode
@@ -249,30 +256,38 @@ bufbar
          " This will affect \C-]all\C-] ERC sessions."
          " Add `track' to `erc-modules' to silence this message."))
      (erc-track-mode +1))
-   (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
+   (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
    (unless erc--updating-modules-p
      (if (erc-with-server-buffer erc-server-connected)
-         (erc-status-sidebar-open)
-       (setq erc-bufbar-mode nil)
+         (erc-status-sidebar--open)
        (when (derived-mode-p 'erc-mode)
          (erc-error "Not initializing `erc-bufbar-mode' in %s"
                     (current-buffer))))))
-  ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open)
-   (erc-status-sidebar-close erc-status-sidebar-singular)
+  ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
+   (erc-status-sidebar-close 'all-frames)
    (when-let ((arg erc--module-toggle-prefix-arg)
               ((numberp arg))
               ((< arg 0)))
      (erc-status-sidebar-kill))))
 
+;;;###autoload
+(defun erc-status-sidebar-open ()
+  "Open or create a sidebar window in the current frame.
+When `erc-bufbar-mode' is active, do this even if one already
+exists in another frame."
+  (interactive)
+  (let ((erc-status-sidebar--singular-p (not erc-bufbar-mode)))
+    (erc-status-sidebar--open)))
+
 ;;;###autoload
 (defun erc-status-sidebar-toggle ()
   "Toggle the sidebar open/closed on the current frame.
-Do this regardless of `erc-status-sidebar-singular'."
+When opening and `erc-bufbar-mode' is active, create a sidebar
+even if one already exists in another frame."
   (interactive)
   (if (get-buffer-window erc-status-sidebar-buffer-name nil)
       (erc-status-sidebar-close)
-    (let (erc-status-sidebar-singular)
-      (erc-status-sidebar-open))))
+    (erc-status-sidebar-open)))
 
 (defun erc-status-sidebar-get-channame (buffer)
   "Return name of BUFFER with all leading \"#\" characters removed."
@@ -413,11 +428,10 @@ erc-status-sidebar-refresh
                      erc-status-sidebar-pad-hierarchy))
                   (v v)))
                (chanlist (apply sort-fn (funcall list-fn nil) nil))
-               (window nil)
-               (winstart nil))
+               (windows nil))
     (with-current-buffer (erc-status-sidebar-get-buffer)
-      (setq window (get-buffer-window nil erc-status-sidebar-singular)
-            winstart (and window (window-start window)))
+      (dolist (window (get-buffer-window-list nil nil t))
+        (push (cons window (window-start window)) windows))
       (erc-status-sidebar-writable
        (delete-region (point-min) (point-max))
        (goto-char (point-min))
@@ -443,9 +457,10 @@ erc-status-sidebar-refresh
             0 cnlen 'help-echo
             "mouse-1: switch to buffer in other window" channame)
            (funcall insert-fn channame chanbuf chanlist)))
-       (when winstart
-         (set-window-point window winstart)
-         (with-selected-window window (recenter 0)))
+       (when windows
+         (pcase-dolist (`(,window . ,winstart) windows)
+           (set-window-point window winstart)
+           (with-selected-window window (recenter 0))))
        (when (and erc-status-sidebar-highlight-active-buffer
                   (marker-buffer erc-status-sidebar--active-marker))
          (goto-char erc-status-sidebar--active-marker)
@@ -519,14 +534,28 @@ erc-status-sidebar-refresh-triggers
     erc-kill-server-hook
     erc-kick-hook
     erc-disconnected-hook
-    erc-quit-hook))
+    erc-quit-hook)
+  "Hooks to refresh the sidebar on.
+This may be set locally in the status-sidebar buffer under
+various conditions, like when the option
+`erc-status-sidebar-highlight-active-buffer' is non-nil.")
+
+(defvar erc-status-sidebar--highlight-refresh-triggers
+  '(window-selection-change-functions)
+  "Triggers enabled with `erc-status-sidebar-highlight-active-buffer'.")
+
+(defun erc-status-sidebar--refresh-unless-input ()
+  "Run `erc-status-sidebar-refresh' unless there are unread commands.
+Also abstain when the user is interacting with the minibuffer."
+  (unless (or (input-pending-p) (minibuffer-window-active-p (selected-window)))
+    (erc-status-sidebar-refresh)))
 
 (defun erc-status-sidebar--post-refresh (&rest _ignore)
   "Schedule sidebar refresh for execution after command stack is cleared.
 
 Ignore arguments in IGNORE, allowing this function to be added to
 hooks that invoke it with arguments."
-  (run-at-time 0 nil #'erc-status-sidebar-refresh))
+  (run-at-time 0 nil #'erc-status-sidebar--refresh-unless-input))
 
 (defun erc-status-sidebar-mode--unhook ()
   "Remove hooks installed by `erc-status-sidebar-mode'."
@@ -541,7 +570,7 @@ erc-status-sidebar-set-window-preserve-size
 Note that preserve status needs to be reset when the window is
 manually resized, so `erc-status-sidebar-mode' adds this function
 to the `window-configuration-change-hook'."
-  (when (and (eq (selected-window) (let (erc-status-sidebar-singular)
+  (when (and (eq (selected-window) (let (erc-status-sidebar--singular-p)
                                      (erc-status-sidebar-get-window)))
              (fboundp 'window-preserve-size))
     (unless (eq (window-total-width) (window-min-size nil t))
@@ -563,6 +592,10 @@ erc-status-sidebar-mode
 
   (add-hook 'window-configuration-change-hook
             #'erc-status-sidebar-set-window-preserve-size nil t)
+  (when erc-status-sidebar-highlight-active-buffer
+    (setq-local erc-status-sidebar-refresh-triggers
+                `(,@erc-status-sidebar--highlight-refresh-triggers
+                  ,@erc-status-sidebar-refresh-triggers)))
   (dolist (hk erc-status-sidebar-refresh-triggers)
     (add-hook hk #'erc-status-sidebar--post-refresh))
 
-- 
2.41.0


--=-=-=--




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Sat, 29 Jul 2023 00:01:02 +0000
Resent-Message-ID: <handler.63595.B63595.169058880913064 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169058880913064
          (code B ref 63595); Sat, 29 Jul 2023 00:01:02 +0000
Received: (at 63595) by debbugs.gnu.org; 29 Jul 2023 00:00:09 +0000
Received: from localhost ([127.0.0.1]:46275 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qPXNQ-0003Nq-Kc
	for submit <at> debbugs.gnu.org; Fri, 28 Jul 2023 20:00:09 -0400
Received: from mail-108-mta146.mxroute.com ([136.175.108.146]:37343)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qPXNO-0003E2-7z
 for 63595 <at> debbugs.gnu.org; Fri, 28 Jul 2023 20:00:07 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta146.mxroute.com (ZoneMTA) with ESMTPSA id
 1899ef1f6280004cef.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Sat, 29 Jul 2023 00:00:04 +0000
X-Zone-Loop: bae8f8544f8923673a2f385de1a10cd38659506f1920
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=fjZxvKFgE/Y5lqzq5JEq7mBn/QdLj4EWDxnvVBo+Yt8=; b=d1EY04v/tE+HNpmdVK2cLpnMyn
 5CdJ+lhW0JXYQSYSpMzgsHxkrEj/6UOLsMmFmksKyh2rZfiHwPkKqwIrcdX6mvmpqo8/6J/VG+Wg3
 GqVO+Psf63mBx3D6khZOf3iAUZWYt8KkDUkux3FczEAsQ/TtfdOCtTL6VquXGSswzi6rgR/76xBbu
 Jl6lL6ITdOD/TNNTQSKVa0YKZEE+loywt/e/RF9nEXqZxf450hbCtjjcnH1/B6wzJP+kvGbxmN+ZI
 faENHFwqinz3uGhpH6WwXhZaykyOJ7NM4sWBsD4TEXVDZwYsF8HsUyv8ffOzRs9G7NTqTN9b+BN13
 tncXorug==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87o7k0yv4b.fsf@HIDDEN> (J. P.'s message of "Tue, 25 Jul
 2023 06:32:36 -0700")
References: <87lehkt97a.fsf@HIDDEN> <87o7k0yv4b.fsf@HIDDEN>
Date: Fri, 28 Jul 2023 17:00:01 -0700
Message-ID: <871qgrsi2m.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

"J.P." <jp@HIDDEN> writes:

> This may come as a shock, but problems exist in the `bufbar' changes
> recently introduced (by me) to erc-status-sidebar.el.

I've attempted to address these issues in

  deb74de4 Simplify multi-frame behavior in erc-bufbar-mode

Thanks.




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Wed, 16 Aug 2023 14:05:02 +0000
Resent-Message-ID: <handler.63595.B63595.169219468314253 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169219468314253
          (code B ref 63595); Wed, 16 Aug 2023 14:05:02 +0000
Received: (at 63595) by debbugs.gnu.org; 16 Aug 2023 14:04:43 +0000
Received: from localhost ([127.0.0.1]:41735 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qWH8c-0003hn-TM
	for submit <at> debbugs.gnu.org; Wed, 16 Aug 2023 10:04:43 -0400
Received: from mail-108-mta140.mxroute.com ([136.175.108.140]:33815)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qWH8a-0003he-QF
 for 63595 <at> debbugs.gnu.org; Wed, 16 Aug 2023 10:04:42 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta140.mxroute.com (ZoneMTA) with ESMTPSA id
 189fea99aa0000d7b6.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Wed, 16 Aug 2023 14:04:35 +0000
X-Zone-Loop: 41c0d243dc9e67aaa847a0cac01ace96775dad027fc9
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=8M8J8n5QBlJWd1eRSDhxaMy16vKzx73KIA9lBvT0/pQ=; b=hbbGPqAAHeOSEQK9L9rztrylBl
 mLclJtAdRaNsWxDMeWVkaKYkrmglEIlh0ieCdA4SCa+/6rkf6ZHGj7mFRkWasY8KH+RYdAb6XSz/W
 7etuQlDn9UahfwzuXCVUB/e5Ftx4TXpTcfD5YXQhgdqrkwNj9frskiut7WweyTqZ3FLF7i00Tu28U
 0OYJ8l/beyMICf4a4GZrkSQyhkwaDkNbamEqboo9kOMafxJzu64DezhL3K68GI+vbVVf6GKYw7eOu
 n5hdWZrQ5hxiy7IsyylzZFt0vRtLSlUtk8OKNMmDQVWZDsz3XDIq2GiPCV/3fDeZ/a7wjSi3vlJmo
 nCFlvY3w==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Wed, 16 Aug 2023 07:04:26 -0700
Message-ID: <87jztvdqxh.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

Some issues with the `nickbar' module have surfaced that may be related
to another issue involving unexpected connection loss. Thanks to Corwin
for reporting this.

It appears that the teardown logic in `erc-nickbar-disable' was calling
`dframe-close-frame', `speedbar-set-timer', and `speedbar-timer-fn'
repeatedly and unnecessarily, which resulted in redundant scheduling of
the same update timer (there should only be one per speedbar instance).
Other problems involving the variable `speedbar-update-flag' were also
discovered, as well as a possible bug in `dframe-set-timer', which I'll
leave for future people familiar with dframe to deal with if necessary.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Prevent-unwanted-recursion-in-erc-nickbar-disabl.patch

From 645af24230bdf9032f1f0d79ff7e62f5ecf7b72a Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Tue, 15 Aug 2023 21:14:07 -0700
Subject: [PATCH] [5.6] Prevent unwanted recursion in erc-nickbar-disable

* lisp/erc/erc-speedbar.el (erc-status-sidebar-mode--unhook): Remove
forward declaration.
(erc-speedbar--toggle-nicknames-sidebar): Inline
`erc-speedbar-close-nicknames-window'.  Don't call
`erc-speedbar-browser' to avoid excess timers being added.
(erc-speedbar--ensure): Inline `speedbar-enable-update' to avoid
unneeded call to `speedbar-set-timer', and ensure it runs in
`speedbar-buffer'.
(erc-speedbar--shutting-down-p): New flag variable to avoid recursive
calls to `dframe-close-frame' and friends.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable): Move
logic formerly performed by `speedbar-disable-update' to
`erc-speedbar--toggle-nicknames-sidebar'.  When disabling, guard
against recursive calls to `dframe-close-frame' and friends.
(erc-speedbar--get-timers): New helper function.
(erc-speedbar--dframe-controlled): Bind
`erc-speedbar--shutting-down-p' flag non-nil around call to
`erc-nickbar-mode'.  Remove excess timer left behind due to
incompatible behavior from `dframe-close-frame'.  Let caller kill
buffer.
(erc-speedbar-close-nicknames-window): Remove unused command, new in
ERC 5.6 and Emacs 30.
(erc-speedbar--destroy-nicknames-frame): New function to perform
common teardown.
* test/lisp/erc/erc-scenarios-status-sidebar.el
(erc-speedbar-close-nicknames-window): Remove forward declaration.
(erc-speedbar--get-timers): Add forward declaration.
(erc-scenarios-status-sidebar--nickbar): Fix faulty expectations of
desired behavior when disabling module.  Ensure timers canceled.
* test/lisp/erc/resources/erc-scenarios-common.el
(erc-scenarios-common--make-bindings): Shadow `timer-idle-list' to
avoid polluting global test environment with stray timers.
(Bug#63595)
---
 lisp/erc/erc-speedbar.el                      | 112 +++++++++++-------
 test/lisp/erc/erc-scenarios-status-sidebar.el |  13 +-
 .../erc/resources/erc-scenarios-common.el     |   1 +
 3 files changed, 79 insertions(+), 47 deletions(-)

diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index f5fbaac767d..88400f034ba 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -439,7 +439,6 @@ erc-track--switch-fallback-blockers
 (defvar erc-status-sidebar-buffer-name)
 (declare-function erc-status-sidebar-set-window-preserve-size
                   "erc-status-sidebar" nil)
-(declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil)
 
 (defvar erc-speedbar--buffer-options
   '((speedbar-update-flag . t)
@@ -490,36 +489,64 @@ erc-speedbar--toggle-nicknames-sidebar
           (cl-assert (buffer-live-p speedbar-buffer))
           (if (or (and force (< arg 0))
                   (and (not force) (get-buffer-window speedbar-buffer nil)))
-              (erc-speedbar-close-nicknames-window nil)
+              ;; Close associated windows and stop updating but leave timer.
+              (progn
+                (dolist (window (get-buffer-window-list speedbar-buffer nil t))
+                  (unless (frame-root-window-p window)
+                    (when erc-speedbar--hidden-speedbar-frame
+                      (cl-assert
+                       (not (eq (window-frame window)
+                                erc-speedbar--hidden-speedbar-frame))))
+                    (delete-window window)))
+                (with-current-buffer speedbar-buffer
+                  (setq speedbar-update-flag nil)
+                  (speedbar-set-mode-line-format)))
             (when (or (not force) (>= arg 0))
               (with-selected-frame speedbar-frame
                 (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
-      (when (or (not force) (>= arg 0))
-        (let ((speedbar-frame-parameters (backquote-list*
-                                          '(visibility . nil)
-                                          '(no-other-frame . t)
-                                          speedbar-frame-parameters))
-              (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
-          (erc-speedbar-browser)
-          ;; If we put the remaining parts in the "create hook" along
-          ;; with everything else, the frame with `window-main-window'
-          ;; gets raised and steals focus if you've switched away from
-          ;; Emacs in the meantime.
-          (make-frame-invisible speedbar-frame)
-          (select-frame (setq speedbar-frame (previous-frame)))
-          (erc-speedbar--emulate-sidebar-set-window-preserve-size))))))
+      (when-let (((or (not force) (>= arg 0)))
+                 (speedbar-frame-parameters (backquote-list*
+                                             '(visibility . nil)
+                                             '(no-other-frame . t)
+                                             speedbar-frame-parameters))
+                 (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
+        (erc-install-speedbar-variables)
+        ;; Run before toggling mode to prevent timer from being
+        ;; created twice.
+        (speedbar-change-initial-expansion-list "ERC")
+        (speedbar-frame-mode 1)
+        ;; If we put the remaining parts in the "create hook" along
+        ;; with everything else, the frame with `window-main-window'
+        ;; gets raised and steals focus if you've switched away from
+        ;; Emacs in the meantime.
+        (make-frame-invisible speedbar-frame)
+        (select-frame (setq speedbar-frame (previous-frame)))
+        (erc-speedbar--emulate-sidebar-set-window-preserve-size))))
+  (cl-assert (not (cdr (erc-speedbar--get-timers))) t))
 
 (defun erc-speedbar--ensure (&optional force)
   (when (or (erc-server-buffer) force)
     (when erc-track-mode
       (cl-pushnew '(derived-mode . speedbar-mode)
                   erc-track--switch-fallback-blockers :test #'equal))
+    (unless (display-graphic-p)
+      (unless speedbar-update-flag
+        (erc-button--display-error-notice-with-keys
+         (erc-server-buffer)
+         "Module `nickbar' needs `speedbar-update-flag' to be non-nil"
+         " in non-graphic terminals.  Setting to t for the current"
+         " Emacs session. Customize it to avoid this message."))
+      (setq speedbar-update-flag t))
     (erc-speedbar--toggle-nicknames-sidebar +1)
-    (speedbar-enable-update)))
+    (with-current-buffer speedbar-buffer
+      (setq speedbar-update-flag t)
+      (speedbar-set-mode-line-format))))
+
+(defvar erc-speedbar--shutting-down-p nil)
 
 ;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
 (define-erc-module nickbar nil
-  "Show nicknames in a side window.
+  "Show nicknames for current target buffer in a side window.
 When enabling, create a speedbar session if one doesn't exist and
 show its buffer in an `erc-status-sidebar' window instead of a
 separate frame.  When disabling, close the window or, with a
@@ -527,8 +554,8 @@ nickbar
 
 WARNING: this module may produce unwanted side effects, like the
 raising of frames or the stealing of input focus.  If you witness
-such an occurrence, and can reproduce it, please file a bug
-report with \\[erc-bug]."
+such a thing and can reproduce it, please file a bug report with
+\\[erc-bug]."
   ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
    (erc-speedbar--ensure)
    (unless (or erc--updating-modules-p
@@ -542,31 +569,44 @@ nickbar
          (erc-error "Not initializing `erc-nickbar-mode' in %s"
                     (current-buffer))))))
   ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
-   (speedbar-disable-update)
    (when erc-track-mode
      (setq erc-track--switch-fallback-blockers
            (remove '(derived-mode . speedbar-mode)
                    erc-track--switch-fallback-blockers)))
    (erc-speedbar--toggle-nicknames-sidebar -1)
-   (when-let ((arg erc--module-toggle-prefix-arg)
+   (when-let (((not erc-speedbar--shutting-down-p))
+              (arg erc--module-toggle-prefix-arg)
               ((numberp arg))
               ((< arg 0)))
-     (erc-speedbar-close-nicknames-window 'kill))))
+     (with-current-buffer speedbar-buffer
+       (dframe-close-frame)
+       (setq erc-speedbar--hidden-speedbar-frame nil)))))
+
+(defun erc-speedbar--get-timers ()
+  (cl-remove #'dframe-timer-fn timer-idle-list
+             :key #'timer--function
+             :test-not #'eq))
 
 (defun erc-speedbar--dframe-controlled (arg)
+  (when speedbar-buffer
+    (cl-assert (eq speedbar-buffer (current-buffer))))
   (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
     (when erc-nickbar-mode
-      (erc-nickbar-mode -1))
+      (let ((erc-speedbar--shutting-down-p t))
+        (erc-nickbar-mode -1)))
     (setq speedbar-frame erc-speedbar--hidden-speedbar-frame
           erc-speedbar--hidden-speedbar-frame nil)
     ;; It's unknown whether leaving the frame invisible interferes
-    ;; with the upstream teardown procedure.
+    ;; with the upstream teardown sequence.
     (when (display-graphic-p)
       (make-frame-visible speedbar-frame))
-    (speedbar-frame-mode arg)
-    (when speedbar-buffer
-      (kill-buffer speedbar-buffer)
-      (setq speedbar-buffer nil))))
+    (speedbar-frame-mode arg) ; -1
+    ;; As of Emacs 29, `dframe-set-timer' can't remove `dframe-timer'.
+    (cl-assert (= 1 (length (erc-speedbar--get-timers))) t)
+    (cancel-function-timers #'dframe-timer-fn)
+    ;; `dframe-close-frame' kills the buffer but no function in
+    ;; erc-speedbar.el resets this to nil.
+    (setq speedbar-buffer nil)))
 
 (defun erc-speedbar-toggle-nicknames-window-lock ()
   "Toggle whether nicknames window is selectable with \\[other-window]."
@@ -578,20 +618,6 @@ erc-speedbar-toggle-nicknames-window-lock
       (set-window-parameter window 'no-other-window (not val))
       (message "nick-window: %s" (if val "selectable" "protected")))))
 
-(defun erc-speedbar-close-nicknames-window (kill)
-  (interactive "P")
-  (if kill
-      (with-current-buffer speedbar-buffer
-        (dframe-close-frame)
-        (cl-assert (not erc-nickbar-mode))
-        (setq erc-speedbar--hidden-speedbar-frame nil))
-    (dolist (window (get-buffer-window-list speedbar-buffer nil t))
-      (unless (frame-root-window-p window)
-        (when erc-speedbar--hidden-speedbar-frame
-          (cl-assert (not (eq (window-frame window)
-                              erc-speedbar--hidden-speedbar-frame))))
-        (delete-window window)))))
-
 
 ;;;; Nicks integration
 
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index 92229121c9f..3a047bf3983 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -94,7 +94,7 @@ erc-scenarios-status-sidebar--bufbar
 ;; terminal, and we lack a fixture for that.  Please try running this
 ;; test interactively with both graphical Emacs and non.
 (declare-function erc-nickbar-mode "erc-speedbar" (arg))
-(declare-function erc-speedbar-close-nicknames-window "erc-speedbar" (kill))
+(declare-function erc-speedbar--get-timers "erc-speedbar" nil)
 (declare-function speedbar-timer-fn "speedbar" nil)
 (defvar erc-nickbar-mode)
 (defvar speedbar-buffer)
@@ -154,16 +154,21 @@ erc-scenarios-status-sidebar--nickbar
       (ert-info ("Core toggle and kill commands work")
         ;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
         ;; etc. for testing commands that call those same functions.
-        (erc-nickbar-mode -1)
+        (call-interactively #'erc-nickbar-mode)
+        (should-not erc-nickbar-mode)
         (should-not (and speedbar-buffer
                          (get-buffer-window speedbar-buffer)))
+        (should speedbar-buffer)
+
         (erc-nickbar-mode +1)
         (should (and speedbar-buffer
                      (get-buffer-window speedbar-buffer)))
         (should (get-buffer " SPEEDBAR"))
-        (erc-speedbar-close-nicknames-window 'kill)
+        (erc-nickbar-mode -1)
         (should-not (get-buffer " SPEEDBAR"))
         (should-not erc-nickbar-mode)
-        (should-not (cdr (frame-list)))))))
+        (should-not (cdr (frame-list)))))
+
+    (should-not (erc-speedbar--get-timers))))
 
 ;;; erc-scenarios-status-sidebar.el ends here
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el
index 972faa5c73f..2eb040d28d9 100644
--- a/test/lisp/erc/resources/erc-scenarios-common.el
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -122,6 +122,7 @@ erc-scenarios-common--print-trace
       (inhibit-interaction t)
       (auth-source-do-cache nil)
       (timer-list (copy-sequence timer-list))
+      (timer-idle-list (copy-sequence timer-idle-list))
       (erc-auth-source-parameters-join-function nil)
       (erc-autojoin-channels-alist nil)
       (erc-server-auto-reconnect nil)
-- 
2.41.0


--=-=-=--




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: Corwin Brust <corwin@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Sun, 20 Aug 2023 17:24:01 +0000
Resent-Message-ID: <handler.63595.B63595.169255223218446 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: "J.P." <jp@HIDDEN>
Cc: 63595 <at> debbugs.gnu.org, emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169255223218446
          (code B ref 63595); Sun, 20 Aug 2023 17:24:01 +0000
Received: (at 63595) by debbugs.gnu.org; 20 Aug 2023 17:23:52 +0000
Received: from localhost ([127.0.0.1]:54739 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qXm9X-0004nS-KV
	for submit <at> debbugs.gnu.org; Sun, 20 Aug 2023 13:23:51 -0400
Received: from mail-ot1-f52.google.com ([209.85.210.52]:47528)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <mplscorwin@HIDDEN>) id 1qXm9V-0004nE-Nb
 for 63595 <at> debbugs.gnu.org; Sun, 20 Aug 2023 13:23:50 -0400
Received: by mail-ot1-f52.google.com with SMTP id
 46e09a7af769-6bcbb0c40b1so2191803a34.3
 for <63595 <at> debbugs.gnu.org>; Sun, 20 Aug 2023 10:23:47 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20221208; t=1692552222; x=1693157022;
 h=content-transfer-encoding:cc:to:subject:message-id:date:from
 :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=1aErz4Se5n7VzBDDRbaHF9qOqnvAgpOniAoVHY+zLLo=;
 b=ZbnESVu0Uz/HXI254zo78dSezDImGaRc1E1LcjHEEdB5AtaA5o4I/JUvNuBB5wNteh
 Na+cW3sRWjzXqLj++9knWc5XVBoXRnESKGQEWrdVLqmClLpGCyBj4v5L+vFP4hH8uqLB
 VPQZH8wEuMVlcMFFYuMQW/Vp3TcVU94vgXmvHrt8naJ/sC4BOTIIO3K8HHmW9k/+vVIy
 CzDadfuwIhV8BCuhu5viTTPHEbDC3QX0gO5kvbMbFJYjV8GGLRL9x2OOzZ/o7kin1iY5
 mBQUF23tqRC70JJkK6gMWq+0fHqUg7fI8JA3oYhaYqY5knazHPjxkpZtLurNVEkocyAW
 kxnQ==
X-Gm-Message-State: AOJu0YzYeEvCaaUdQnYM0veyROY8ZiP9GQxAPPVfPiIb0BRzZezzXnjL
 oVq+YpRsaeCmih7LmR2Adtyh7VZcfDFOVESvQTWDtxNP7yY=
X-Google-Smtp-Source: AGHT+IGBRxAFcEyhFkolK9fRTL8BHEoFJrUZt6JsH0DDqIvNI9nl2onhNqTWsJgkV0mRfgszijsvlyzkO6RPZt+UptQ=
X-Received: by 2002:a05:6830:1309:b0:6bc:fdbd:ccb8 with SMTP id
 p9-20020a056830130900b006bcfdbdccb8mr6689975otq.13.1692552222067; Sun, 20 Aug
 2023 10:23:42 -0700 (PDT)
MIME-Version: 1.0
References: <87lehkt97a.fsf@HIDDEN> <87jztvdqxh.fsf@HIDDEN>
In-Reply-To: <87jztvdqxh.fsf@HIDDEN>
From: Corwin Brust <corwin@HIDDEN>
Date: Sun, 20 Aug 2023 12:23:30 -0500
Message-ID: <CAJf-WoRybO12qgFH7Hd1AZA4jKAeGTLuHdzcQisceLOrPwBd-w@HIDDEN>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: 0.5 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.5 (/)

TL;DR: Couldn't apply; can you double check?

detail below and thanks for the insta-response!

On Wed, Aug 16, 2023 at 9:04=E2=80=AFAM J.P. <jp@HIDDEN> wrote:
>
> Some issues with the `nickbar' module have surfaced that may be related
> to another issue involving unexpected connection loss. Thanks to Corwin
> for reporting this.
>

corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
$ git apply /c/Users/corwi/Downloads/0001-5.6-Prevent-unwanted-recursion-in=
-erc-nickbar-disabl.patch
error: patch failed: lisp/erc/erc-speedbar.el:439
error: lisp/erc/erc-speedbar.el: patch does not apply
error: patch failed: test/lisp/erc/erc-scenarios-status-sidebar.el:94
error: test/lisp/erc/erc-scenarios-status-sidebar.el: patch does not apply
error: patch failed: test/lisp/erc/resources/erc-scenarios-common.el:122
error: test/lisp/erc/resources/erc-scenarios-common.el: patch does not appl=
y

corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
$




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Sun, 20 Aug 2023 19:57:01 +0000
Resent-Message-ID: <handler.63595.B63595.169256140321230 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: Corwin Brust <corwin@HIDDEN>
Cc: 63595 <at> debbugs.gnu.org, emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169256140321230
          (code B ref 63595); Sun, 20 Aug 2023 19:57:01 +0000
Received: (at 63595) by debbugs.gnu.org; 20 Aug 2023 19:56:43 +0000
Received: from localhost ([127.0.0.1]:54896 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qXoXS-0005WJ-0I
	for submit <at> debbugs.gnu.org; Sun, 20 Aug 2023 15:56:43 -0400
Received: from mail-108-mta181.mxroute.com ([136.175.108.181]:39763)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qXoXO-0005W9-GP
 for 63595 <at> debbugs.gnu.org; Sun, 20 Aug 2023 15:56:40 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta181.mxroute.com (ZoneMTA) with ESMTPSA id
 18a148548be000d7b6.002 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Sun, 20 Aug 2023 19:56:33 +0000
X-Zone-Loop: 8f3857473f226c33cd58e38fb9d3569524342ebccd21
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=8J8+3V3WEKFuO7s8c/A53FfGhpUSmH6UGK5RX7MshtI=; b=WuubFQoiKzyf5p4BSw/RGxFJWb
 dBakFkcTwSuI47dQNq7PvY4Kl09886ePSGxjNcdwepzXnSuF5HCGm5UtRC+/ukSSkhhJM2sV0/hlU
 DxtbpTWGmhHwU3DjunwWQaZfnCjUdcH4KAFesVqrikPnpMBBqokWk95GrswO1Q9n1WPZo+EqcxnN6
 eaBkT+5MP3sZSNmElpBSnPDncDjGG1rlO6yp9seCnayOlQPOdNYPuLg0oYgpT7RoGZe4SlEbnQNep
 qElQ4ZEcXYJGJIgmWwxPRyiFTgKBwxDAASOUgoiX0fpRt5Nn2OC1T3vrFQtaWv2o2WubSqS4bQCRP
 KCb3H0RQ==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <CAJf-WoRybO12qgFH7Hd1AZA4jKAeGTLuHdzcQisceLOrPwBd-w@HIDDEN>
 (Corwin Brust's message of "Sun, 20 Aug 2023 12:23:30 -0500")
References: <87lehkt97a.fsf@HIDDEN> <87jztvdqxh.fsf@HIDDEN>
 <CAJf-WoRybO12qgFH7Hd1AZA4jKAeGTLuHdzcQisceLOrPwBd-w@HIDDEN>
Date: Sun, 20 Aug 2023 12:56:30 -0700
Message-ID: <87350da3o1.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Corwin Brust <corwin@HIDDEN> writes:

> TL;DR: Couldn't apply; can you double check?

Hm, I'm able to apply that patch atop a563ea8 [1].

  $ cd /tmp
  $ git clone --depth 1 https://git.savannah.gnu.org/git/emacs.git
  $ cd emacs
  $ curl -L "$url [2]" | git am

  Applying: Prevent unwanted recursion in erc-nickbar-disable

  $ git status

  On branch master
  Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)
  
  nothing to commit, working tree clean

  $ git log -n2 --oneline

  5104bc0 Prevent unwanted recursion in erc-nickbar-disable
  a563ea8 * lisp/isearch.el (isearch-resume): Add isearch-push-state (bug#65379).

However, as I type this, I'm thinking I should have also tried it with a
minimal ~/.gitconfig as well as after running ./autogen.sh. That said, I
do both in CI (with a slightly updated patch), and it works fine.

> detail below and thanks for the insta-response!
>
> corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
> $ git status
> On branch master
> Your branch is up to date with 'origin/master'.
>
> nothing to commit, working tree clean
>
> corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
> $ git apply /c/Users/corwi/Downloads/0001-5.6-Prevent-unwanted-recursion-in-erc-nickbar-disabl.patch
> error: patch failed: lisp/erc/erc-speedbar.el:439
> error: lisp/erc/erc-speedbar.el: patch does not apply
> error: patch failed: test/lisp/erc/erc-scenarios-status-sidebar.el:94
> error: test/lisp/erc/erc-scenarios-status-sidebar.el: patch does not apply
> error: patch failed: test/lisp/erc/resources/erc-scenarios-common.el:122
> error: test/lisp/erc/resources/erc-scenarios-common.el: patch does not apply
>
> corwi@Avalon MINGW64 /h/emacs-dev/emacs-nt
> $

I find it unlikely that none of the hunks apply cleanly. Perhaps this
has something to do with white space/line endings? Maybe you need to
change core.autocrlf or similar?

[1] https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=a563ea89633963fb20c4159bd5e8da825ffc2248
[2] https://debbugs.gnu.org/cgi/bugreport.cgi?filename=0001-5.6-Prevent-unwanted-recursion-in-erc-nickbar-disabl.patch;msg=23;bug=63595;att=1




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: Corwin Brust <corwin@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Mon, 21 Aug 2023 13:57:02 +0000
Resent-Message-ID: <handler.63595.B63595.169262616831969 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: "J.P." <jp@HIDDEN>
Cc: emacs-erc@HIDDEN, 63595 <at> debbugs.gnu.org
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169262616831969
          (code B ref 63595); Mon, 21 Aug 2023 13:57:02 +0000
Received: (at 63595) by debbugs.gnu.org; 21 Aug 2023 13:56:08 +0000
Received: from localhost ([127.0.0.1]:57344 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qY5O4-0008JZ-66
	for submit <at> debbugs.gnu.org; Mon, 21 Aug 2023 09:56:08 -0400
Received: from mail-ot1-f44.google.com ([209.85.210.44]:60628)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <mplscorwin@HIDDEN>) id 1qY5O1-0008JC-J6
 for 63595 <at> debbugs.gnu.org; Mon, 21 Aug 2023 09:56:06 -0400
Received: by mail-ot1-f44.google.com with SMTP id
 46e09a7af769-6bc9811558cso2497664a34.0
 for <63595 <at> debbugs.gnu.org>; Mon, 21 Aug 2023 06:56:03 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20221208; t=1692626157; x=1693230957;
 h=content-transfer-encoding:cc:to:subject:message-id:date:from
 :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=p03wrP5sJp5f4ldgWGjtbe6NsR4NklmfCSfOvF3PDNw=;
 b=Z6A7Mv11BLbgscWNITooDu2XklPiRw6MuaLJa7tsm8OCZdep+KWWEY4O2mH/POZj3w
 Sqf8KW7Oyrg1mpXMnWMhveb8ZfFmEZtU3o1oWP5emiPu0qs8QTFV0xbFsM3VO3pXQFtT
 j+2dGzgeEN6Y45QrpPh2BX+OnvMPLusWHs3g072ifqCGUc0HRDsaNMVmxHSv7IGxEEvw
 HJT091b1ODfVamcTTY1mH08p/9NQZ7uDr6UojEmTsC0KZK6Jx2/hmBzkN/Z7HJzp6TSp
 NKu73Z/6hh+gXLVATJj54gKchEvP3SNdDak2NxlRhoPMslsIgMdMu1d9Dul4HLfNnm0Y
 rLxA==
X-Gm-Message-State: AOJu0YzlEgIpnl5IOu97BNzUwSgaxazUGya290T2Qe+Zu3VoEmzoB2Y+
 UPmo/2dTy76+y93+gMC8P1A251x0WLzU2wJJVPg=
X-Google-Smtp-Source: AGHT+IGDe75lmsNwm4mnnflZHFIXZPN/e3xcVmm2vHdhlJTJ6iO0gVRHEk/NoH80m/IohbDbb8kpM2CzTXOlrwCUeA0=
X-Received: by 2002:a05:6870:6490:b0:1bf:607:e0ed with SMTP id
 cz16-20020a056870649000b001bf0607e0edmr10022630oab.39.1692626157407; Mon, 21
 Aug 2023 06:55:57 -0700 (PDT)
MIME-Version: 1.0
References: <87lehkt97a.fsf@HIDDEN> <87jztvdqxh.fsf@HIDDEN>
 <CAJf-WoRybO12qgFH7Hd1AZA4jKAeGTLuHdzcQisceLOrPwBd-w@HIDDEN>
 <87350da3o1.fsf@HIDDEN>
In-Reply-To: <87350da3o1.fsf@HIDDEN>
From: Corwin Brust <corwin@HIDDEN>
Date: Mon, 21 Aug 2023 08:55:45 -0500
Message-ID: <CAJf-WoSXYGWpM0_x_KbAJ+8VbKzwy4UPvNAy2gTt3ZP2vxh5DA@HIDDEN>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: 0.5 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.5 (/)

Thank you; I think this fixes things and should be applied.

On Sun, Aug 20, 2023 at 2:56=E2=80=AFPM J.P. <jp@HIDDEN> wrote:
>
> Corwin Brust <corwin@HIDDEN> writes:
>
> > TL;DR: Couldn't apply; can you double check?
>
>   $ curl -L "$url [2]" | git am
>
> I find it unlikely that none of the hunks apply cleanly. Perhaps this
>
> [2] https://debbugs.gnu.org/cgi/bugreport.cgi?filename=3D0001-5.6-Prevent=
-unwanted-recursion-in-erc-nickbar-disabl.patch;msg=3D23;bug=3D63595;att=3D=
1
>

Quite right; thanks for pointing out the improbability of no hunks
applying; the command you suggested worked fine.

Moreover, I believe this patch solves the issue (or helps enough I
can't notice it).  Since applying I see no difference in how often I'm
disconnected between patched ERC, ERC without nickbar, and hexchat,
all running on the same system connected to the same bouncer.  (Prior
to the patch ERC with nickbar running was disconnected much more often
than hexchat).




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Thu, 31 Aug 2023 13:32:02 +0000
Resent-Message-ID: <handler.63595.B63595.169348866322757 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169348866322757
          (code B ref 63595); Thu, 31 Aug 2023 13:32:02 +0000
Received: (at 63595) by debbugs.gnu.org; 31 Aug 2023 13:31:03 +0000
Received: from localhost ([127.0.0.1]:55187 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qbhlG-0005uy-Vi
	for submit <at> debbugs.gnu.org; Thu, 31 Aug 2023 09:31:03 -0400
Received: from mail-108-mta174.mxroute.com ([136.175.108.174]:36677)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qbhlF-0005uj-2a
 for 63595 <at> debbugs.gnu.org; Thu, 31 Aug 2023 09:31:02 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta174.mxroute.com (ZoneMTA) with ESMTPSA id
 18a4bca1d85000d7b6.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Thu, 31 Aug 2023 13:30:51 +0000
X-Zone-Loop: c9f6a538591f4b723329c8c71e0cd867051bc32e5d71
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=mVa6qeFhp+GrQ5fpeaXwyPLz4llE2/+sV6yXZtxt0/4=; b=L8u1SrlRfLDbaYkPLoF6WE/Nzo
 OXWqKt2M/hx5qW+efJeANBmhtmKKw/hL4Wi3ruxAOchi7HEMAnccoSnlDi0O64rl8O1Q0cMeOoB2R
 mEGyk8R8v4523uUlTNVUR+Q7IPpTR1HMN6EhFkhNJ3TeQY4c8Lwy4BvUsrN9TAXQVFuWTN0ba/VY6
 eINpXUgGldDawlGwRdsURIz3H5U1eYqH3QkLABidNkqHgsnXQCS70wjXWguQtVJjYWkH8QMr5d3Wd
 sH85jruR2BC/QZ2H3wxzM8YoD7rE7IfCXELak5BkVHvCUJTPGzcgkO7wWKS6v6mDsI900c4o0eIt7
 82x3u67A==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Thu, 31 Aug 2023 06:30:43 -0700
Message-ID: <87jztbxrss.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

This feature introduced a couple auxiliary modules to serve as higher
level wrappers around newer functionality that was awkwardly bolted onto
the existing libraries erc-status-sidebar and erc-speedbar. One of the
stated aims of this bug's initial proposal was to unify the UI for this
flavor of transitory, command-focused module [1]. However, anyone paying
close enough attention will have noticed I've already faltered in this
regard.

Look at the minor-mode toggle `erc-bufbar-mode' and notice that, when
disabling, it tears down the mode completely, destroying all assets. To
make it easy to show and hide its window without alternately shutting
down and starting anew with every other toggle, I turned to contextually
overloading the existing commands `erc-status-sidebar-toggle' and
friends to behave specially when `erc-bufbar-mode' is active [2].

Contrast this with the approach taken for `erc-nickbar-mode', whose
namesake command is of the all-in-one, kitchen-sink variety. Toggling
off merely hides its window and preserves the speedbar session (its
hidden frame, buffer, etc.). To actually kill it off completely, you
invoke the toggle with a negative prefix argument.

Obviously, these must be reconciled somehow, or one must be made to
mimic the other. I'm leaning toward changing `nickbar' by adding a
second command to toggle it without shutting it down, and then having
the main minor-mode toggle always do a full shutdown. This probably
aligns more with prevailing expectations and traditional Emacs semantics
that assume a nil `erc-nickbar-mode' variable indicates not only a
logical disabled activation state but that the mode is completely
destroyed.

Therefore, unless anyone has any better ideas, I'll provide a patch
shortly that does something to this effect.

Thanks.


[1] To recap, the trend in recent years has been to downplay the use of
    a module's minor-mode toggle as a viable entry point for enabling
    its functionality. Rather, there's been a focus on emphasizing
    membership in `erc-modules' as the preferred means of doing so. The
    reasons are manifold but ultimately rooted in attaining more
    predictable behavior and tighter inter-module interop across the
    board. However, this paradigm necessarily couples a module's
    activation state to the lifetime of an IRC session, which doesn't
    always make sense. Some modules, by their very nature, are
    intrinsically interactive and ephemeral. IOW, they're minor-modes
    first and modules second.

[2] Note the traditional library namespace prefix, which probably
    hampers discoverability for users of the module. We could alias the
    transitory toggles (at least) to reflect the new module names, but
    that may just confuse things further because the new options would
    all continue to sport library prefixes.




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Thu, 31 Aug 2023 13:34:01 +0000
Resent-Message-ID: <handler.63595.B63595.169348880422960 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: Corwin Brust <corwin@HIDDEN>, emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.169348880422960
          (code B ref 63595); Thu, 31 Aug 2023 13:34:01 +0000
Received: (at 63595) by debbugs.gnu.org; 31 Aug 2023 13:33:24 +0000
Received: from localhost ([127.0.0.1]:55197 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1qbhnY-0005yG-14
	for submit <at> debbugs.gnu.org; Thu, 31 Aug 2023 09:33:24 -0400
Received: from mail-108-mta237.mxroute.com ([136.175.108.237]:37355)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1qbhnV-0005y8-Nz
 for 63595 <at> debbugs.gnu.org; Thu, 31 Aug 2023 09:33:22 -0400
Received: from mail-111-mta2.mxroute.com ([136.175.111.2]
 filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta237.mxroute.com (ZoneMTA) with ESMTPSA id
 18a4bcc379c000d7b6.002 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Thu, 31 Aug 2023 13:33:09 +0000
X-Zone-Loop: e106b3378aaf771a6f39d264a2ee97eb05ab2e61803a
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=qBUo2eOpeBoPLx9aVVNj1OtSvSzYj+1bAgsG/47vmk4=; b=B+52DOMVwB+EdefHqNEgDRPXD6
 fsxd/BeEjBP4L/Tr4XS2ie28rdbkF9daCp1iJAlUBAFsRrQY+DJyUj6FqBMR0RR9kAGZMTgD4P+HV
 fqY5pIf1DcFhAMxbSVRFyXqipdo5YcjqX/XqPbGybYQHJRHLIXh+KEEh4hDhg9o4GQBImcii7Y0AQ
 /RJkzYdCkBjwWjaLSWtpSEGKckyB72wggd6xpyU4lutSV9yxbXjBWSY5Dlfe/ZOmtYcD2YZ+KsHuW
 Zlp6NFjLXyzVj0kGnLa6Tn6U5zikRGq1mK3Ed0/8SkNVAIc1nYCDPD4rBGBEGPzMtkyDeSsILhzZf
 PHgT/EkQ==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <CAJf-WoSXYGWpM0_x_KbAJ+8VbKzwy4UPvNAy2gTt3ZP2vxh5DA@HIDDEN>
 (Corwin Brust's message of "Mon, 21 Aug 2023 08:55:45 -0500")
References: <87lehkt97a.fsf@HIDDEN> <87jztvdqxh.fsf@HIDDEN>
 <CAJf-WoRybO12qgFH7Hd1AZA4jKAeGTLuHdzcQisceLOrPwBd-w@HIDDEN>
 <87350da3o1.fsf@HIDDEN>
 <CAJf-WoSXYGWpM0_x_KbAJ+8VbKzwy4UPvNAy2gTt3ZP2vxh5DA@HIDDEN>
Date: Thu, 31 Aug 2023 06:33:02 -0700
Message-ID: <87fs3zxrox.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Corwin Brust <corwin@HIDDEN> writes:

> Moreover, I believe this patch solves the issue (or helps enough I
> can't notice it).  Since applying I see no difference in how often I'm
> disconnected between patched ERC, ERC without nickbar, and hexchat,
> all running on the same system connected to the same bouncer.  (Prior
> to the patch ERC with nickbar running was disconnected much more often
> than hexchat).

FTR, this was applied as:

  commit f8b710e54fb8b29f39bf021ccfb993f881b0134a
  Author: F. Jason Park <jp@HIDDEN>
  Date:   Tue Aug 15 21:14:07 2023 -0700
  
      Prevent unwanted recursion in erc-nickbar-disable
      
   lisp/erc/erc-speedbar.el                        | 112 +++++++++++++++---------
   test/lisp/erc/erc-scenarios-status-sidebar.el   |  13 ++-
   test/lisp/erc/resources/erc-scenarios-common.el |   1 +
   3 files changed, 79 insertions(+), 47 deletions(-)

Thanks.




Message received at fakecontrol@fakecontrolmessage:


Received: (at fakecontrol) by fakecontrolmessage;
To: internal_control <at> debbugs.gnu.org
From: Debbugs Internal Request <help-debbugs@HIDDEN>
Subject: Internal Control
Message-Id: bug archived.
Date: Fri, 29 Sep 2023 11:24:10 +0000
User-Agent: Fakemail v42.6.9

# This is a fake control message.
#
# The action:
# bug archived.
thanks
# This fakemail brought to you by your local debbugs
# administrator


Message received at control <at> debbugs.gnu.org:


Received: (at control) by debbugs.gnu.org; 7 Dec 2023 04:26:30 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Dec 06 23:26:30 2023
Received: from localhost ([127.0.0.1]:40817 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rB5y1-0004jf-Iw
	for submit <at> debbugs.gnu.org; Wed, 06 Dec 2023 23:26:30 -0500
Received: from mail-108-mta203.mxroute.com ([136.175.108.203]:37677)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rB5xw-0004jQ-MR
 for control <at> debbugs.gnu.org; Wed, 06 Dec 2023 23:26:28 -0500
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta203.mxroute.com (ZoneMTA) with ESMTPSA id
 18c4286a906000190b.001 for <control <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Thu, 07 Dec 2023 04:26:10 +0000
X-Zone-Loop: 7d66de06770f87787d4a1345818933f3dee4ea51a0f0
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=HS9z7FdyXxgffVyoOisKlWc/ypLj4oAJMzDuyVFj6U4=; b=I/MklbCCQmSFZ7xe8h86aUrho8
 8AERMKBT+Mk0v/VnOVNJAYFBZUo8wPqBJa8MFLIDvrzeIaxgEtCnwyB2y/FjIGFwv5aMELD43tNVX
 CKRtRe0n0Vfv0fpZw8TKVHC7eiMvI9NYvimHR+gcfDY89U2S8pOkWkcDwpLMGugWl1CccqxI7Aig8
 2+K4AhV68fAaDRq743F+jDVNiwWNnCp7A/VzXJmfiqvH3Lm7xNFhMqLJc6dd9TClyqp988u4gWokd
 fvZQOyBZCx631CJOh/DvbBVq3lpbfJ7bwUWNSrAx+DOI7Mzw0VNOkODzBMLvRGUAN81ZyYc6SFtDn
 CKOdGSkA==;
From: "J.P." <jp@HIDDEN>
To: control <at> debbugs.gnu.org
Subject: control message for bug #63595
Date: Wed, 06 Dec 2023 20:26:07 -0800
Message-ID: <87zfymd4f4.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: control
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

unarchive 63595
quit





Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Thu, 07 Dec 2023 07:27:02 +0000
Resent-Message-ID: <handler.63595.B63595.170193399025359 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.170193399025359
          (code B ref 63595); Thu, 07 Dec 2023 07:27:02 +0000
Received: (at 63595) by debbugs.gnu.org; 7 Dec 2023 07:26:30 +0000
Received: from localhost ([127.0.0.1]:40935 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rB8mD-0006ax-NV
	for submit <at> debbugs.gnu.org; Thu, 07 Dec 2023 02:26:30 -0500
Received: from mail-108-mta7.mxroute.com ([136.175.108.7]:42909)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rB8mA-0006am-U6
 for 63595 <at> debbugs.gnu.org; Thu, 07 Dec 2023 02:26:27 -0500
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta7.mxroute.com (ZoneMTA) with ESMTPSA id 18c432b773e000190b.001
 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Thu, 07 Dec 2023 07:26:11 +0000
X-Zone-Loop: 65dd285c1b215e15455996d059da4c037764634d5ec2
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=06TC4u0+Z9VN1af5fHxEv8fSEwpf87kCI/GfNpwv1zI=; b=G2aAbV8HPqR70bg/WQJbh6RJwT
 liZKtgn+/8nTfoJfKTpS6+DXnMTJEPvo+ZK8tZb1Om68/ebkADWBo2BqrlmDg/U9qQ6Ozl9fYMHlW
 5ZbOqB1rixwCleGwUyV2z8CK/PNyeTZhcygcMgu1Gy1xFVUSrK+j2B9zoASnGC00QYFe248IK5e4U
 TIYF6iGhzcH3D0+Boo539OOagCuLVWct676csL3cMDIIn2seSNS3UW4uph8x3AlLIfyM3ll9bKB1m
 wWzKyXf5kSERyj6R5gSabOy30yNAq7BearHOowLBWVA1wR0YoDmdhMNiNZfSQM3FDJ5tP25Ym651z
 9ELYFJQQ==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Wed, 06 Dec 2023 23:26:07 -0800
Message-ID: <87v89a5v8w.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

One thing this feature left unaddressed was the inclusion of all
available channel-membership prefixes in the "nickbar" (speedbar).
Currently, only members with a "+" or "@" have their nicks augmented.
Given the recent improvements to channel-mode parsing, it's now easier
to offer the full slate of prefixes. See attached.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0009-5.6-Make-erc-get-user-mode-prefix-more-flexible.patch

From 401bc01ace91aac6f3423fc8a04fe7a95b67987c Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Mon, 27 Nov 2023 22:53:00 -0800
Subject: [PATCH 09/11] [5.6] Make erc-get-user-mode-prefix more flexible

* lisp/erc/erc-speedbar.el (erc-speedbar-insert-user): Use
`erc-get-channel-membership-prefix' so that nicks in the nickbar can
have prefixes beyond just voice and op.
* lisp/erc/erc.el (erc-get-user-mode-prefix,
erc-get-channel-membership-prefix): Rename former to latter because
"user-mode" suggests the function somehow involves user modes, but it
exclusively concerns channel modes.  Also, overload the only parameter
in order to avoid redundantly looking up `erc-channel-user' object
with every predicate call.  In the near future, ERC will likely need
to offer an alternate version of this function that returns multiple
prefixes instead of just one.
(erc-format-@nick): Use `channel-data' parameter.
(erc-format-my-nick, erc--format-channel-status-prefix): Use new name
for function `erc-get-user-mode-prefix'.  (Bug#63595)
---
 etc/ERC-NEWS             |  7 +++++++
 lisp/erc/erc-speedbar.el |  4 +---
 lisp/erc/erc.el          | 30 ++++++++++++++++++++----------
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 540d9e98751..4fdfe7a9dcb 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -433,6 +433,13 @@ The 'fill' module is now defined by 'define-erc-module'.  The same
 goes for ERC's imenu integration, which has 'imenu' now appearing in
 the default value of 'erc-modules'.
 
+*** Function 'erc-get-user-mode-prefix' renamed.
+This utility has been renamed to 'erc-get-channel-membership-prefix'
+to better reflect its role of delivering a formatted "status prefix",
+like "+" (for "voice"), and to avoid confusion with user modes, like
+"+i" (for "invisible").  Additionally, its lone parameter is now
+overloaded to accept an 'erc-channel-user' object as well as a string.
+
 *** Hidden messages contain a preceding rather than trailing newline.
 ERC has traditionally only offered to hide messages involving fools,
 but plans are to make hiding more powerful.  Anyone depending on the
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index 93be7b9f074..90d7376fc0c 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -319,9 +319,7 @@ erc-speedbar-insert-user
 	 (info (erc-server-user-info user))
 	 (login (erc-server-user-login user))
 	 (name (erc-server-user-full-name user))
-	 (voice (and cuser (erc-channel-user-voice cuser)))
-	 (op (and cuser (erc-channel-user-op cuser)))
-	 (nick-str (concat (if op "@" "") (if voice "+" "") nick))
+         (nick-str (concat (erc-get-channel-membership-prefix cuser) nick))
 	 (finger (concat login (when (or login host) "@") host))
          (sbtoken (list finger name info (buffer-name buffer))))
     (if (or login host name info) ; we want to be expandable
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 98621302abd..8e7162fec89 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -5815,21 +5815,31 @@ erc-format-nick
 See also `erc-format-nick-function'."
   (when user (erc-server-user-nickname user)))
 
-(defun erc-get-user-mode-prefix (user)
+(define-obsolete-function-alias 'erc-get-user-mode-prefix
+  #'erc-get-channel-membership-prefix "30.1")
+(defun erc-get-channel-membership-prefix (user)
+  "Return channel membership prefix for USER as a string.
+Ensure returned string has a `help-echo' text property with the
+corresponding verbose membership type, like \"voice\", as its
+value.  Expect USER to be an `erc-channel-user' object or a
+string nickname, not necessarily downcased."
   (when user
-    (cond ((erc-channel-user-owner-p user)
+    (when (stringp user)
+      (setq user (and erc-channel-users (cdr (erc-get-channel-user user)))))
+    (cond ((null user) "")
+          ((erc-channel-user-owner user)
            (propertize "~" 'help-echo "owner"))
-          ((erc-channel-user-admin-p user)
+          ((erc-channel-user-admin user)
            (propertize "&" 'help-echo "admin"))
-          ((erc-channel-user-op-p user)
+          ((erc-channel-user-op user)
            (propertize "@" 'help-echo "operator"))
-          ((erc-channel-user-halfop-p user)
+          ((erc-channel-user-halfop user)
            (propertize "%" 'help-echo "half-op"))
-          ((erc-channel-user-voice-p user)
+          ((erc-channel-user-voice user)
            (propertize "+" 'help-echo "voice"))
           (t ""))))
 
-(defun erc-format-@nick (&optional user _channel-data)
+(defun erc-format-@nick (&optional user channel-data)
   "Format the nickname of USER showing if USER has a voice, is an
 operator, half-op, admin or owner.  Owners have \"~\", admins have
 \"&\", operators have \"@\" and users with voice have \"+\" as a
@@ -5838,7 +5848,7 @@ erc-format-@nick
   (when user
     (let ((nick (erc-server-user-nickname user)))
       (concat (propertize
-               (erc-get-user-mode-prefix nick)
+               (erc-get-channel-membership-prefix channel-data)
                'font-lock-face 'erc-nick-prefix-face)
 	      nick))))
 
@@ -5848,7 +5858,7 @@ erc-format-my-nick
       (let* ((open "<")
              (close "> ")
              (nick (erc-current-nick))
-             (mode (erc-get-user-mode-prefix nick)))
+             (mode (erc-get-channel-membership-prefix nick)))
         (erc--ensure-spkr-prop nick)
         (concat
          (propertize open 'font-lock-face 'erc-default-face)
@@ -8486,7 +8496,7 @@ erc--format-user-modes
 (defun erc--format-channel-status-prefix ()
   "Return the current channel membership prefix."
   (and (erc--target-channel-p erc--target)
-       (erc-get-user-mode-prefix (erc-current-nick))))
+       (erc-get-channel-membership-prefix (erc-current-nick))))
 
 (defun erc--format-modes (&optional no-query-p)
   "Return a string of channel modes in channels and user modes elsewhere.
-- 
2.42.0


--=-=-=--




Message received at fakecontrol@fakecontrolmessage:


Received: (at fakecontrol) by fakecontrolmessage;
To: internal_control <at> debbugs.gnu.org
From: Debbugs Internal Request <help-debbugs@HIDDEN>
Subject: Internal Control
Message-Id: bug archived.
Date: Thu, 04 Jan 2024 12:24:11 +0000
User-Agent: Fakemail v42.6.9

# This is a fake control message.
#
# The action:
# bug archived.
thanks
# This fakemail brought to you by your local debbugs
# administrator


Message received at control <at> debbugs.gnu.org:


Received: (at control) by debbugs.gnu.org; 19 Jan 2024 02:33:45 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Jan 18 21:33:44 2024
Received: from localhost ([127.0.0.1]:57084 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rQehU-0004TY-Lj
	for submit <at> debbugs.gnu.org; Thu, 18 Jan 2024 21:33:44 -0500
Received: from mail-108-mta4.mxroute.com ([136.175.108.4]:39939)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rQehS-0004TP-7s
 for control <at> debbugs.gnu.org; Thu, 18 Jan 2024 21:33:43 -0500
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta4.mxroute.com (ZoneMTA) with ESMTPSA id 18d1f9106740003727.001
 for <control <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 19 Jan 2024 02:33:34 +0000
X-Zone-Loop: 71742b037c5f653badb06600011ced7d3ad79d1d81eb
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=HS9z7FdyXxgffVyoOisKlWc/ypLj4oAJMzDuyVFj6U4=; b=OE/oN0sq+Q1Dbj97Au52iTiz/u
 IkE7Wb1jwklsRJjIFptBOXWoYmcs5vaODvXYFHb8Hx3VC5rO4tEiZjgfz8RiO2Un1sNXYUfujq3Wl
 sVUf+Noz0Y8gX84J0WVOfQ2xAD0GzdE45BvwmNRR1c/RryvHlb4O+1MWF+beoP9RYMd5w1azOoH+u
 lqzBuk561NOpO/iVAX11T9U72bCWLtPQAKK0Mj8J2vTXqp5rvkBOKRlgH2ruNuLyUg3sgiXql0B5n
 7xFduFL/RKtsIGz0i6eGErMqDT6y2e8v1WzdTQwIgPDaRQ6Ng3DblAkz8az0aqtLdu2WoxpmLcOWB
 bN509GCQ==;
From: "J.P." <jp@HIDDEN>
To: control <at> debbugs.gnu.org
Subject: control message for bug #63595
Date: Thu, 18 Jan 2024 18:33:31 -0800
Message-ID: <87sf2uqcg4.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: control
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

unarchive 63595
quit





Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Fri, 19 Jan 2024 02:44:02 +0000
Resent-Message-ID: <handler.63595.B63595.170563218718145 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.170563218718145
          (code B ref 63595); Fri, 19 Jan 2024 02:44:02 +0000
Received: (at 63595) by debbugs.gnu.org; 19 Jan 2024 02:43:07 +0000
Received: from localhost ([127.0.0.1]:57092 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rQeqY-0004ib-O1
	for submit <at> debbugs.gnu.org; Thu, 18 Jan 2024 21:43:06 -0500
Received: from mail-108-mta196.mxroute.com ([136.175.108.196]:33641)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rQeqW-0004iR-IR
 for 63595 <at> debbugs.gnu.org; Thu, 18 Jan 2024 21:43:05 -0500
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta196.mxroute.com (ZoneMTA) with ESMTPSA id
 18d1f99a1ed0003727.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 19 Jan 2024 02:42:58 +0000
X-Zone-Loop: f5ddcc092f9221f8da301c1f8f605eaf7d6c5a246fd1
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=CZHoejPB0lAnYAA7CIYKsPg6fYDCQJhrn+axn7Jqqzg=; b=bcETkGxq07uMxoCqgxkLQ9ZKfF
 /kkv6g11TPVsScIGgJsgngtQk8ocOASiljz36SBW2zCtIcZMNQFwB0hZJICEJVbNnJZ4VShbXfYhM
 wwQVblzIGXmxB8/MpFI9ZtWtaSMg6XAohhgw4jsEIpyR3XjrhUn8BgmvjeoqwHoeKhDNZh++yzKxQ
 dC9t0a37ihoUHNEVJUeB5VFRAvNDMSQt7I+vpeZ7SFASmNBidtEzixowEsrOOtpNnNtZZ06kUmnE2
 gXZBL3fch0cLtLSiZYGw6dBBW40aIJztwIcdnRG69NsDpWuBPVqsNcZr9/diHQSw7GmmKvSUi/+3t
 e+qC7onQ==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Thu, 18 Jan 2024 18:42:55 -0800
Message-ID: <875xzqqc0g.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

I'm unsure whether there's a regression present on HEAD affecting
erc-speedbar (now the `nickbar' module). I've been noticing the idle
timer only seems to run after user input has been received and dealt
with. IOW, updates don't occur if simply leaving the window open and
otherwise not interacting with Emacs. I suppose we could run the timer
function manually, like on `erc-post-insert-hook' (perhaps guarded by
some debouncing logic), but I'd only want to do so if we can confirm
this isn't a regression.




Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Thu, 25 Jan 2024 21:43:02 +0000
Resent-Message-ID: <handler.63595.B63595.17062189448303 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.17062189448303
          (code B ref 63595); Thu, 25 Jan 2024 21:43:02 +0000
Received: (at 63595) by debbugs.gnu.org; 25 Jan 2024 21:42:24 +0000
Received: from localhost ([127.0.0.1]:49368 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rT7UN-00029r-Lp
	for submit <at> debbugs.gnu.org; Thu, 25 Jan 2024 16:42:24 -0500
Received: from mail-108-mta128.mxroute.com ([136.175.108.128]:43355)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rT7UL-00029h-WA
 for 63595 <at> debbugs.gnu.org; Thu, 25 Jan 2024 16:42:23 -0500
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta128.mxroute.com (ZoneMTA) with ESMTPSA id
 18d4292c2100003727.001 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Thu, 25 Jan 2024 21:42:10 +0000
X-Zone-Loop: c9c5f89b776eda482b17e9f4dba8d3255399e2a2c434
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=FEq3CxK29dSZgMbPxHOOtuxTD/b8q+ayCFHEqnWBqZw=; b=DiX4DGb001yEzE589unzvqw5yv
 wIPm351u2I9AfUlXrb26BfVp1YaSvqFA530Qgy1Ag0+ckP4Lfsi86d6yy71UO5wg4zDHo8xN2PFu2
 l9r8yKiCNvm1F4bwk5Ck2liY6hWZmcB69sf4ysS9AMXc+a+C+YNxSJIgRAHOJWoAwSvEOkF9qmxnt
 R1wibkE4ebSvRM4TwHrKJsRCYh0fy3RB1dgb3d2xl9ss99NOQWH85iPSMjIMVlisAflUriaPR8uLd
 hS0BYlAejvt5U2xeCulA9+h12sqh4Yf2xDBewjDDFllNYDCJWZHtIo8xDFXJNIq5iA3mfF3L5jXzq
 ZwhiE/gg==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <875xzqqc0g.fsf@HIDDEN> (J. P.'s message of "Thu, 18 Jan
 2024 18:42:55 -0800")
References: <87lehkt97a.fsf@HIDDEN> <875xzqqc0g.fsf@HIDDEN>
Date: Thu, 25 Jan 2024 13:41:52 -0800
Message-ID: <87le8d6qfz.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

"J.P." <jp@HIDDEN> writes:

> I'm unsure whether there's a regression present on HEAD affecting
> erc-speedbar (now the `nickbar' module). I've been noticing the idle
> timer only seems to run after user input has been received and dealt
> with. IOW, updates don't occur if simply leaving the window open and
> otherwise not interacting with Emacs. I suppose we could run the timer
> function manually, like on `erc-post-insert-hook' (perhaps guarded by
> some debouncing logic), but I'd only want to do so if we can confirm
> this isn't a regression.

This wasn't a regression but rather a faulty observation on account of
my ignorance regarding how idle timers work. In essence: no input, no
reset (no next run). To address this, I've implemented something like
the more robust manual trigger approach mentioned above:

  https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=aae131b8

This bug is already closed.




Message received at fakecontrol@fakecontrolmessage:


Received: (at fakecontrol) by fakecontrolmessage;
To: internal_control <at> debbugs.gnu.org
From: Debbugs Internal Request <help-debbugs@HIDDEN>
Subject: Internal Control
Message-Id: bug archived.
Date: Fri, 23 Feb 2024 12:24:16 +0000
User-Agent: Fakemail v42.6.9

# This is a fake control message.
#
# The action:
# bug archived.
thanks
# This fakemail brought to you by your local debbugs
# administrator


Message received at control <at> debbugs.gnu.org:


Received: (at control) by debbugs.gnu.org; 31 Mar 2024 23:50:00 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sun Mar 31 19:49:59 2024
Received: from localhost ([127.0.0.1]:49005 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rr4w3-0002Si-JI
	for submit <at> debbugs.gnu.org; Sun, 31 Mar 2024 19:49:59 -0400
Received: from mail-108-mta109.mxroute.com ([136.175.108.109]:42151)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rr4w1-0002SF-I9
 for control <at> debbugs.gnu.org; Sun, 31 Mar 2024 19:49:58 -0400
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta109.mxroute.com (ZoneMTA) with ESMTPSA id
 18e96eb5f5f0003bea.001 for <control <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Sun, 31 Mar 2024 23:49:51 +0000
X-Zone-Loop: 5cd108f3192f5eb308e08241dc289b5508bb1d8bc81e
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender:
 Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description:
 Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
 In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=HS9z7FdyXxgffVyoOisKlWc/ypLj4oAJMzDuyVFj6U4=; b=NmvioGxH9gEYb9P/CFERC8Fryi
 BqBt4O6JHPmm2P50v8Rm7oezP1VGjufsBtA22kbgXaMSBxwAJoHiMbTD4TJGPplQyaVq9eI29WkoX
 jGstKGhZAS42I4P8a45HeuZOxuwzYaY5podFAKTnv9yqF1LAT8oQEYngYGZ9yBaAAbgBTZwAEF5jO
 v013ia43j1QsCufOkrCHi72itfbpMwvHtRNpZGrUeOSzXLYfq9pxpzPJSY/ZGAzBjIdmZCEEpCkyf
 1SnbJKHr5Qnx28s5MdjrUrG/FTzgB6rIwE0IeXsyFcbfq33KaDu38H+yzdzd3p/yvrnese9QSGjEC
 ENeYwxiw==;
From: "J.P." <jp@HIDDEN>
To: control <at> debbugs.gnu.org
Subject: control message for bug #63595
Date: Sun, 31 Mar 2024 16:49:48 -0700
Message-ID: <87plvagdwj.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: control
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

unarchive 63595
quit





Message sent to bug-gnu-emacs@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: bug#63595: 30.0.50; ERC 5.6: Add buffer-list and nick-list modules
Resent-From: "J.P." <jp@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@HIDDEN
Resent-Date: Mon, 01 Apr 2024 01:43:02 +0000
Resent-Message-ID: <handler.63595.B63595.171193575011021 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 63595
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: patch
To: 63595 <at> debbugs.gnu.org
Cc: emacs-erc@HIDDEN
Received: via spool by 63595-submit <at> debbugs.gnu.org id=B63595.171193575011021
          (code B ref 63595); Mon, 01 Apr 2024 01:43:02 +0000
Received: (at 63595) by debbugs.gnu.org; 1 Apr 2024 01:42:30 +0000
Received: from localhost ([127.0.0.1]:49177 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rr6gv-0002rh-QJ
	for submit <at> debbugs.gnu.org; Sun, 31 Mar 2024 21:42:30 -0400
Received: from mail-108-mta43.mxroute.com ([136.175.108.43]:42873)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1rr6gs-0002rX-Np
 for 63595 <at> debbugs.gnu.org; Sun, 31 Mar 2024 21:42:28 -0400
Received: from filter006.mxroute.com ([136.175.111.2] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta43.mxroute.com (ZoneMTA) with ESMTPSA id 18e9752516a0003bea.001
 for <63595 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Mon, 01 Apr 2024 01:42:18 +0000
X-Zone-Loop: 606b040dcff6101959f99f124469ddea8a9e75e704cd
X-Originating-IP: [136.175.111.2]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=ROTdZJJBQT0qckbXnpQj/JUw00k/EZLFbSnLK75vxkQ=; b=GFO5W9o0lU/ToweaAPRhWjIxvZ
 ampiqldKQKeWORdouvgKZCz1cHTSxwJCL5xNkCp3e6bbcpoVWU1f73xWAr1ZN+ErNeYo2CEBK2k1h
 Jv/YJKrOXCR38fpBP0m23EsSG2/36B+RjAzpD2ycQ1wW9Yz0lcrjQDpOGRAfAjrquwmGbDn25ynyp
 xo+Idlc6dJUMIPJwEv3snpWN82x/opsf2DTYsZsEJYAq6rIih57i4BseFwwOHuEi7b0zPVihsNj6t
 h30LnOcuHsAJsk6AZbXkMFiSA550xobGNDRor5cgMo/+ubErvfCLMdjACQebovNluY1OcrBWeT003
 VjJWxBeg==;
From: "J.P." <jp@HIDDEN>
In-Reply-To: <87lehkt97a.fsf@HIDDEN> (J. P.'s message of "Fri, 19 May
 2023 12:25:29 -0700")
References: <87lehkt97a.fsf@HIDDEN>
Date: Sun, 31 Mar 2024 18:42:15 -0700
Message-ID: <87h6glg8p4.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

It's been reported that the nickbar (speedbar) window doesn't display
the cursor on at least one user's setup. I've found this to be true by
default on non-graphic displays. The attached patch should fix the
latter regression. As to whether it also fixes the reporter's issue is
TBD.

It's also been reported that the dframe timer can signal a

  (wrong-type-argument window-live-p nil)

which then gets trapped by the

  (with-demoted-errors "DFRAME TIMER ERROR: %S"...)

in `dframe-timer-fn'. Unfortunately, remediation is trickier here
because we've got to inspect calls to `window-live-p' stemming from
`speedbar-timer-fn', possibly via `erc-speedbar-insert-user'. (What we
really need is a backtrace from the bug reporter.)


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-5.6-Fix-invisible-erc-speedbar-cursor-in-text-termin.patch

From 910b6981da743bdc661241f54e26e9b163f239d1 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Sun, 31 Mar 2024 16:32:44 -0700
Subject: [PATCH] [5.6] Fix invisible erc-speedbar cursor in text terminals

* lisp/erc/erc-speedbar.el
(erc-speedbar--reset-last-ran-on-timer): Use `with-current-buffer'
instead of `setf' and `buffer-local-value'.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable)
(erc-speedbar-toggle-nicknames-window-lock): Revise doc string.
(erc-speedbar-toggle-nicknames-window-lock): Set `cursor-type' in
speedbar buffer.
(erc-nickbar-toggle-nicknames-window-lock): New function alias.  Note
that this name flouts traditional library namespacing conventions.
* lisp/erc/erc-status-sidebar.el (erc-status-sidebar-get-window): Use
`cursor-type' instead of `internal-show-cursor'.
(Bug#63595)
---
 lisp/erc/erc-speedbar.el       | 23 ++++++++++++++---------
 lisp/erc/erc-status-sidebar.el |  2 +-
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index a81a3869436..b156f61d5d9 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -566,9 +566,8 @@ erc-speedbar--run-timer-on-post-insert
 (defun erc-speedbar--reset-last-ran-on-timer ()
   "Reset `erc-speedbar--last-ran'."
   (when speedbar-buffer
-    (with-suppressed-warnings ((obsolete buffer-local-value)) ; <=29
-      (setf (buffer-local-value 'erc-speedbar--last-ran speedbar-buffer)
-            (current-time)))))
+    (with-current-buffer speedbar-buffer
+      (setq erc-speedbar--last-ran (current-time)))))
 
 ;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
 (define-erc-module nickbar nil
@@ -578,10 +577,12 @@ nickbar
 separate frame.  When disabling, close the window or, with a
 negative prefix arg, destroy the session.
 
-WARNING: this module may produce unwanted side effects, like the
-raising of frames or the stealing of input focus.  If you witness
-such a thing and can reproduce it, please file a bug report with
-\\[erc-bug]."
+For controlling whether the speedbar window is selectable with
+`other-window', see `erc-nickbar-toggle-nicknames-window-lock'.
+Note that during initialization, this module may produce unwanted
+side effects, like the raising of frames or the stealing of input
+focus.  If you witness such a thing and can reproduce it, please
+file a bug report with \\[erc-bug]."
   ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
    (add-hook 'erc-insert-post-hook #'erc-speedbar--run-timer-on-post-insert)
    (add-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer)
@@ -638,8 +639,8 @@ erc-speedbar--dframe-controlled
 
 (defun erc-speedbar-toggle-nicknames-window-lock (arg)
   "Toggle whether nicknames window is selectable with \\[other-window].
-When arg is a number, lock the window if non-negative, otherwise
-unlock."
+When ARG is a number, lock the window if non-negative.  Otherwise,
+unlock the window."
   (interactive "P")
   (unless erc-nickbar-mode
     (user-error "`erc-nickbar-mode' inactive"))
@@ -648,10 +649,14 @@ erc-speedbar-toggle-nicknames-window-lock
                      ((integerp arg) nil)
                      (t (not (window-parameter window
                                                'no-other-window))))))
+      (with-current-buffer speedbar-buffer
+        (setq cursor-type (not val)))
       (set-window-parameter window 'no-other-window val)
       (unless (numberp arg)
         (message "nick-window: %s" (if val "protected" "selectable"))))))
 
+(defalias 'erc-nickbar-toggle-nicknames-window-lock
+  #'erc-speedbar-toggle-nicknames-window-lock)
 
 ;;;; Nicks integration
 
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index b7695651e4c..dcdef7cfafc 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -192,7 +192,7 @@ erc-status-sidebar-get-window
       (set-window-parameter sidebar-window 'no-delete-other-windows t)
       ;; Don't cycle to this window with `other-window'.
       (set-window-parameter sidebar-window 'no-other-window t)
-      (internal-show-cursor sidebar-window nil)
+      (setq cursor-type nil)
       (set-window-fringes sidebar-window 0 0)
       ;; Set a custom display table so the window doesn't show a
       ;; truncation symbol when a channel name is too big.
-- 
2.44.0


--=-=-=--





Last modified: Mon, 1 Apr 2024 01:45:01 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.