Subject: Re: bug#74934: 30.0.92; Unexpected behavior by which-function-mode in erc-mode buffers

From: "J.P." <[email-masked]>
Date: Tue, 17 Dec 2024 18:24:02 -0800

Hi Anush,

Appreciate you reporting this.

Anush V <[email-masked]> writes:

> steps to reproduce:
> emacs --no-init
> M-x erc
> ;; join some channel.
> M-x which-function-mode
>
> Current behavior:
> In erc buffers, which-function-mode displays either "[n/a]" or a string based on
> the chat history in the mode line.

FTR, I'm able to reproduce it.

> Expected behavior:
> which-function-mode shouldn’t be adding any string to mode line in erc buffers

The first of the attached patches should hopefully address the issue.

Thanks,
J.P.

>From 76eab2b23f46c885051f2bcb985ab15c3e851033 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <[email-masked]>
Date: Tue, 17 Dec 2024 17:53:34 -0800
Subject: [PATCH 1/2] [5.6.1] Disable which-func-mode in erc-imenu buffers

* lisp/erc/erc-imenu.el (erc-imenu-setup): Move after module definition
so the variable `erc-imenu-mode' is defined.  Run teardown code when
module is deactivated.  Set `which-func-mode' to nil locally.
(erc-imenu-mode, erc-imenu-enable, erc-imenu-disable): Manage membership
of `erc-imenu--disable-which-func' in `which-function-mode-hook'.
(erc-imenu--disable-which-func): New function.  (Bug#74934)
---
 lisp/erc/erc-imenu.el | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 4c9cbfc1580..68c7895e2dd 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -132,23 +132,36 @@ erc-create-imenu-index
 (defvar-local erc-imenu--create-index-function nil
   "Previous local value of `imenu-create-index-function', if any.")
 
-(defun erc-imenu-setup ()
-  "Wire up support for Imenu in an ERC buffer."
-  (when (and (local-variable-p 'imenu-create-index-function)
-             imenu-create-index-function)
-    (setq erc-imenu--create-index-function imenu-create-index-function))
-  (setq imenu-create-index-function #'erc-create-imenu-index))
-
 ;;;###autoload(autoload 'erc-imenu-mode "erc-imenu" nil t)
 (define-erc-module imenu nil
   "Simple Imenu integration for ERC."
   ((add-hook 'erc-mode-hook #'erc-imenu-setup)
+   (add-hook 'which-function-mode-hook #'erc-imenu--disable-which-func)
    (unless erc--updating-modules-p (erc-buffer-do #'erc-imenu-setup)))
   ((remove-hook 'erc-mode-hook #'erc-imenu-setup)
-   (erc-with-all-buffers-of-server nil nil
-     (when erc-imenu--create-index-function
-       (setq imenu-create-index-function erc-imenu--create-index-function)
-       (kill-local-variable 'erc-imenu--create-index-function)))))
+   (remove-hook 'which-function-mode-hook #'erc-imenu--disable-which-func)
+   (erc-buffer-do #'erc-imenu-setup)))
+
+(defun erc-imenu-setup ()
+  "Set up or tear down Imenu integration."
+  (if erc-imenu-mode
+      (progn
+        (when (and (local-variable-p 'imenu-create-index-function)
+                   imenu-create-index-function)
+          (setq erc-imenu--create-index-function imenu-create-index-function))
+        (setq imenu-create-index-function #'erc-create-imenu-index)
+        (when (boundp 'which-func-mode)
+          (setq which-func-mode nil)))
+    (when erc-imenu--create-index-function
+      (setq imenu-create-index-function erc-imenu--create-index-function))
+    (kill-local-variable 'erc-imenu--create-index-function)
+    (kill-local-variable 'which-func-mode)))
+
+(defun erc-imenu--disable-which-func ()
+  "Silence `which-function-mode' in ERC buffers."
+  (defvar which-func-mode)
+  (erc-with-all-buffers-of-server nil nil
+    (setq which-func-mode nil)))
 
 (provide 'erc-imenu)
 
-- 
2.47.1

>From 6b331f127a7c4f1c4085521ea74c68f644f93cce Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <[email-masked]>
Date: Mon, 22 Apr 2024 18:11:24 -0700
Subject: [PATCH 2/2] [5.6.1] Add lisp-imenu-generic-expression for ERC hacking

* lisp/erc/erc-backend.el (define-erc-response-handler): Add
`doc-string' to `declare' specification.
* lisp/erc/erc-imenu.el (erc-imenu-add-devel-patterns(): Add locally
autoloaded function for defining `imenu' patterns when hacking on ERC.
---
 lisp/erc/erc-backend.el |  1 +
 lisp/erc/erc-imenu.el   | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index e72fa036f17..311e3a624e6 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1662,6 +1662,7 @@ define-erc-response-handler
                                   ([&or integerp symbolp]
                                    &rest [&or integerp symbolp])]
                            &optional sexp sexp def-body))
+           (doc-string 2)
            (indent defun))
   (if (numberp name) (setq name (intern (format "%03i" name))))
   (setq aliases (mapcar (lambda (a)
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 68c7895e2dd..c6cb5655e2d 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -163,6 +163,29 @@ erc-imenu--disable-which-func
   (erc-with-all-buffers-of-server nil nil
     (setq which-func-mode nil)))
 
+;;;###autoload
+(defun erc-imenu-add-devel-patterns ()
+  "Tell `imenu' about ERC-defined macros."
+  ;; This currently produces results like "ERC response FOO BAR".  I'd
+  ;; obviously be nicer to end up with "erc-response-FOO" and
+  ;; "erc-response-BAR", possibly as separate items.  Likewise for
+  ;; modules: "erc-foo-mode" instead of "ERC module foo".
+  (cl-pushnew `("ERC response"
+                ,(rx bol (* (syntax whitespace))
+                     "(define-erc-response-handler (" (group (+ nonl)) ")")
+                1)
+              lisp-imenu-generic-expression
+              :test #'equal)
+  (cl-pushnew `("ERC module"
+                ,(rx bol (* (syntax whitespace))
+                     ;; Lisp-mode-symbol.
+                     "(define-erc-module " (group (+ (| (syntax word)
+                                                        (syntax symbol)
+                                                        (: "\\" nonl)))))
+                1)
+              lisp-imenu-generic-expression
+              :test #'equal))
+
 (provide 'erc-imenu)
 
 ;;; erc-imenu.el ends here
-- 
2.47.1