Subject: [PATCH] Implement search for nnvirtual Gnus groups

From: Björn Bidar <[email-masked]>
Date: Mon, 16 Dec 2024 01:55:37 +0200

Tags: patch

This patch implements search for nnvirtual. I'm using publi-inbox's
with nnvirtual to group each group into one.
However searching wasn't possible in these nnvirtual groups.
I implemented gnus-search-run-search based on the existing
nnselect gnus-search-run-search function.

I'm looking for feedback on the patch. I don't exactly know how
the search function is called when multiple groups of the same type are
involved. For nnvirtual each group is its on server, does that mean the
function will be always called only for each group? In that case
everything should be good.

In GNU Emacs 31.0.50 (build 1, x86_64-suse-linux-gnu, GTK+ Version
3.24.43, cairo version 1.18.2)
Repository revision: b25fba0ef8f38f95a9e65548f9ebb6c92739857e
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101014
System Description: openSUSE Tumbleweed

Configured using:
 'configure --disable-build-details --without-pop --with-mailutils
 --without-hesiod --with-gameuser=:games --with-kerberos
 --with-kerberos5 --with-file-notification=inotify --with-modules
 --enable-autodepend --enable-link-time-optimization --prefix=/usr
 --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share
 --localstatedir=/var --sharedstatedir=/var/lib
 --libexecdir=/usr/libexec --with-file-notification=yes
 --libdir=/usr/lib64 --with-native-compilation=aot
 --enable-locallisppath=/usr/share/emacs/31.0.50/site-lisp:/usr/share/emacs/site-lisp
 --with-x --with-xim --with-sound --with-xpm --with-jpeg --with-tiff
 --with-gif --with-png --with-rsvg --with-dbus --with-xft --without-gpm
 --with-tree-sitter --with-x-toolkit=gtk --without-pgtk
 --with-toolkit-scroll-bars --x-includes=/usr/include
 --x-libraries=/usr/lib64 --with-libotf --with-m17n-flt --with-cairo
 --build=x86_64-suse-linux --with-dumping=pdumper
 build_alias=x86_64-suse-linux 'CC=sccache cc' 'CFLAGS=-O2 -Wall
 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -fstack-protector-strong
 -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection
 -Werror=return-type -flto=auto -march=znver3 -mmmx -mpopcnt -msse
 -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -msse4a -mno-fma4
 -mno-xop -mfma -mbmi -mbmi2 -maes -mpclmul -mno-gfni -mvpclmulqdq
 -mno-3dnow -madx -mabm -mno-cldemote -mclflushopt -mclwb -mclzero
 -mcx16 -mno-enqcmd -mf16c -mfsgsbase -mfxsr -mno-hle -msahf -mno-lwp
 -mlzcnt -mmovbe -mno-movdir64b -mno-movdiri -mmwaitx -mno-pconfig -mpku
 -mprfchw -mno-ptwrite -mrdpid -mrdrnd -mrdseed -mno-rtm -mno-serialize
 -mno-sgx -msha -mshstk -mno-tbm -mno-tsxldtrk -mvaes -mno-waitpkg
 -mwbnoinvd -mxsave -mxsavec -mxsaveopt -mxsaves -mno-amx-tile
 -mno-amx-int8 -mno-amx-bf16 -mno-uintr -mno-hreset -mno-kl -mno-widekl
 -mno-avxvnni -mno-avxifma -mno-avxvnniint8 -mno-avxneconvert
 -mno-cmpccxadd -mno-amx-fp16 -mno-prefetchi -mno-raoint
 -mno-amx-complex --param l1-cache-size=32 --param l1-cache-line-size=64
 --param l2-cache-size=512 -mtune=znver3 -fno-optimize-sibling-calls -O2
 -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -fstack-protector-strong
 -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection
 -Werror=return-type -flto=auto -g -D_GNU_SOURCE
 -DGDK_DISABLE_DEPRECATION_WARNINGS -DGLIB_DISABLE_DEPRECATION_WARNINGS
 -pipe -Wno-pointer-sign -Wno-unused-variable -Wno-unused-label
 -DPDMP_BASE='\''"emacs-gtk"'\''' LDFLAGS=-Wl,-O2 'CXX=sccache c++'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

>From 4b24c759e19aa2998a150f424e8187b052d7d5e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Bidar?= <[email-masked]>
Date: Mon, 16 Dec 2024 01:28:16 +0200
Subject: [PATCH] Implement search for nnvirtual Gnus groups

* lisp/gnus/nnvirtual.el (nnvirtual-request-list): Implement
request list backend function for nnvirtual.
* lisp/gnus/gnus-search.el (gnus-search-nnvirtual): Implement
function to build search queries for nnvirtual.
(gnus-search-default-search-engines, gnus-search-server-to-enngine):
Include nnvirtual.
---
 lisp/gnus/gnus-search.el | 29 ++++++++++++++++++++++++++---
 lisp/gnus/nnvirtual.el   |  7 +++++++
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index ca82546ef82..4a7cf902b32 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -795,6 +795,9 @@ shared-initialize
 (defclass gnus-search-nnselect (gnus-search-engine)
   nil)
 
+(defclass gnus-search-nnvirtual (gnus-search-engine)
+  nil)
+
 (defclass gnus-search-imap (gnus-search-engine)
   ((literal-plus
     :initarg :literal-plus
@@ -953,14 +956,16 @@ 'nnir-method-default-engines
   'gnus-search-default-engines "28.1")
 
 (defcustom gnus-search-default-engines '((nnimap . gnus-search-imap)
-                                         (nnselect . gnus-search-nnselect))
+                                         (nnselect . gnus-search-nnselect)
+                                         (nnvirtual . gnus-search-nnvirtual))
   "Alist of default search engines keyed by server method."
-  :version "26.1"
+  :version "31.1"
   :type `(repeat (cons (choice (const nnimap) (const nntp) (const nnspool)
 			       (const nneething) (const nndir) (const nnmbox)
 			       (const nnml) (const nnmh) (const nndraft)
 			       (const nnfolder) (const nnmaildir)
-                               (const nnselect))
+                               (const nnselect)
+                               (const nnvirtual))
 		       (choice
 			,@(mapcar
 			   (lambda (el) (list 'const (intern (car el))))
@@ -1086,6 +1091,23 @@ gnus-search-run-search
                                (cons 'search-group-spec group-spec))))))))
     artlist))
 
+;; nnvirtual interface
+(cl-defmethod gnus-search-run-search ((_engine gnus-search-nnvirtual)
+                               srv query-spec _groups)
+  ;; fixme groups vs srv which of?
+  ;; in theory the function could get multiple groups of one server
+  ;; but for nnvirtual server = group
+  (save-excursion
+    (let* (;; Not really a server but the matching groups for the nnvirtual group
+          (grouplist (mapcar #'gnus-group-short-name (gnus-search-get-active srv)))
+          ;; group each group as list containing each server and their groups
+          (group-spec (nnselect-categorize grouplist (lambda (x) (gnus-group-server x))))
+          (artlist []))
+      (setq artlist (vconcat artlist
+                             (gnus-search-run-query
+                              (list (cons 'search-query-spec query-spec)
+                                    (cons 'search-group-spec group-spec)))))
+      artlist)))
 
 ;; imap interface
 (cl-defmethod gnus-search-run-search ((engine gnus-search-imap)
@@ -2153,6 +2175,7 @@ gnus-search-server-to-engine
 	    ('namazu 'gnus-search-namazu)
 	    ('find-grep 'gnus-search-find-grep)
 	    ('imap 'gnus-search-imap)
+            ('nnvirtual 'gnus-search-nnvirtual)
 	    (_ server))
 	  inst
 	  (cond
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index 79747dca31f..edc97a8ca63 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -293,6 +293,13 @@ nnvirtual-close-group
     (nnvirtual-update-read-and-marked t t))
   t)
 
+(deffoo nnvirtual-request-list (&optional server)
+  (when (nnvirtual-possibly-change-server server)
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (dolist (group nnvirtual-component-groups)
+        (insert (format "%S 0  1 y\n" group))))
+    t))
 
 (deffoo nnvirtual-request-newgroups (_date &optional _server)
   (nnheader-report 'nnvirtual "NEWGROUPS is not supported."))
-- 
2.45.2