Draft patch: Supporting buffer-local `erc-hide-*'

Alcor <[email protected]> Fri, 22 Nov 2024 19:22:12 +0100
Newsgroups gmane.emacs.erc.general
Message-ID <[email protected]>
--=-=-=
Content-Type: text/plain

Hi Erc'ers,

I've tried modifying Erc to support buffer-local erc-hide-*
variables. The idea is to support message type filtering per channel
buffer, which is useful for "noisy" channels.

Attached is a patch with an implementation idea, which I have tested out
for a couple of hours. The approach is as follows:

1. Extract out a function `erc-buffer-expand' (perhaps a different name
might be better?) from `erc--route-insertion' that normalizes Erc's
buffer specification values to lists.

2. Add a helper `erc-hide-current-message-in-buffer-p' that evaluates
`erc-hide-current-message-p' in a (with-current-buffer ...) context.

3. Modify `erc-display-message' to use #1 & #2, ensuring only non-hidden
messages as per the predicate from #2 get inserted.

Feedback welcome. I'm still a bit dissatisfied with some aspects of the
patch and am left wondering if there's a way to avoid adding an extra
argument to `erc--route-insertion'. Testing on a number of IRC channels
with (setq-local erc-hide-list '("PART" "JOIN" "QUIT")) while comparing
with the defaults yields good results however, with all specified
messages being correctly filtered out.

Cheers,
-A.

PS: Regarding the terminology - "erc-hide-*" feels slightly
misleading. I'm not familiar with Erc's internals but I have not found a
way to "unhide" messages, so this feature (as it is) is more of
"discard" or "drop" compared to the similarly-named functionality in
Circe, which is reversible.


--=-=-=
Content-Type: text/x-diff
Content-Disposition: attachment;
 filename=0001-Support-buffer-local-erc-hide-list-erc-channel-hide-.patch

From 0086b2cfc73cae92c2aa505ba166e02e67739942 Mon Sep 17 00:00:00 2001
From: Alcor <[email protected]>
Date: Fri, 22 Nov 2024 17:46:12 +0000
Subject: [PATCH] Support buffer-local `erc-hide-list', `erc-channel-hide-list'
 & Co.

* lisp/erc/erc.el (erc-buffer-expand): New function.
  (erc-hide-current-message-in-buffer-p): New function.
  (erc-display-message): Insert into non-hidden buffers.
  (erc--route-insertion): Refactor to use erc-buffer-expand.
---
 lisp/erc/erc.el | 61 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 24 deletions(-)

diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 7028d0a..ea384d2 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -3550,26 +3550,14 @@ modification hooks)."
   "Check if NICK is a valid IRC nickname."
   (string-match (concat "\\`" erc-valid-nick-regexp "\\'") nick))
 
-(defun erc--route-insertion (string buffer)
+(defun erc--route-insertion (string buffer &optional setprops)
   "Insert STRING in BUFFER.
 See `erc-display-message' for acceptable BUFFER types."
   (let (seen msg-props)
-    (dolist (buf (cond
-                  ((bufferp buffer) (list buffer))
-                  ((consp buffer)
-                   (setq msg-props erc--msg-props)
-                   buffer)
-                  ((processp buffer) (list (process-buffer buffer)))
-                  ((eq 'all buffer)
-                   ;; Hmm, or all of the same session server?
-                   (erc-buffer-list nil erc-server-process))
-                  ((and-let* (((eq 'active buffer))
-                              (b (erc-active-buffer)))
-                        (list b)))
-                  ((erc-server-buffer-live-p)
-                   (list (process-buffer erc-server-process)))
-                  (t (list (current-buffer)))))
-      (when (buffer-live-p buf)
+    (when setprops
+      (setq msg-props erc--msg-props))
+    (dolist (buf buffer)
+      (when (and (buffer-live-p buf))
         (when msg-props
           (setq erc--msg-props (copy-hash-table msg-props)))
         (erc-insert-line string buf)
@@ -4007,6 +3995,21 @@ returns non-nil."
         (member command current-hide-list)
         (and (member command erc-lurker-hide-list) (erc-lurker-p sender)))))
 
+(defun erc-buffer-expand (buffer)
+  "Normalize an Erc buffer specification BUFFER into a list of buffer objects."
+  (cond
+   ((bufferp buffer) (list buffer))
+   ((consp buffer) buffer)
+   ((processp buffer) (list (process-buffer buffer)))
+   ((eq 'all buffer) (erc-buffer-list nil erc-server-process))
+   ((and-let* (((eq 'active buffer)) (b (erc-active-buffer))) (list b)))
+   ((erc-server-buffer-live-p) (list (process-buffer erc-server-process)))
+   (t (list (current-buffer)))))
+
+(defun erc-hide-current-message-in-buffer-p (parsed buffer)
+  "Call ERC-HIDE-CURRENT-MESSAGE-P in BUFFER scope."
+  (with-current-buffer buffer (erc-hide-current-message-p parsed)))
+
 (defun erc-display-message (parsed type buffer msg &rest args)
   "Display MSG in BUFFER.
 
@@ -4086,13 +4089,23 @@ various default response handlers may appear to presume nil."
             (erc-display-message-highlight type string))))
 
     (if (not (erc-response-p parsed))
-        (erc--route-insertion string buffer)
-      (unless (erc-hide-current-message-p parsed)
-        (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
-	(when (erc-response.tags parsed)
-	  (erc-put-text-property 0 (length string) 'tags (erc-response.tags parsed)
-				 string))
-        (erc--route-insertion string buffer)))))
+        (erc--route-insertion string (erc-buffer-expand buffer) (consp buffer))
+      (let* ((expanded-buffers (erc-buffer-expand buffer))
+             (visible-buffers
+              (seq-remove
+               (lambda (buffer)
+                 (erc-hide-current-message-in-buffer-p parsed buffer))
+               expanded-buffers)))
+        (when visible-buffers
+          (mapc (lambda (buffer)
+                  (with-current-buffer buffer
+                    (erc-put-text-property
+                     0 (length string) 'erc-parsed parsed string)))
+                visible-buffers)
+          (when (erc-response.tags parsed)
+            (erc-put-text-property
+             0 (length string) 'tags (erc-response.tags parsed) string))
+          (erc--route-insertion string visible-buffers (consp buffer)))))))
 
 (defun erc-message-type-member (position list)
   "Return non-nil if the erc-parsed text-property at POSITION is in LIST.
-- 
2.43.0


--=-=-=--