7.7.1 Select Groups

Gnus provides the nnselect method for creating virtual groups composed of collections of messages, even when these messages come from groups that span multiple servers and backends. For the most part these virtual groups behave like any other group: messages may be threaded, marked, moved, deleted, copied, etc.; groups may be ephemeral or persistent; groups may be created via gnus-group-make-group or browsed as foreign via gnus-group-browse-foreign-server.

The key to using an nnselect group is specifying the messages to include. Each nnselect group has a group parameter nnselect-specs which is an alist with two elements: a function nnselect-function; and arguments nnselect-args to be passed to the function, if any.

The function nnselect-function must return a vector. Each element of this vector is in turn a 3-element vector corresponding to one message. The 3 elements are: the fully-qualified group name; the message number; and a "score" that can be used for additional sorting. The values for the score are arbitrary, and are not used directly by the nnselect method—they may, for example, all be set to 100.

Here is an example:

(nnselect-specs
 (nnselect-function . identity)
 (nnselect-args
  . [["nnimap+work:mail" 595 100]
     ["nnimap+home:sent" 223 100]
     ["nntp+news.gmane.io:gmane.emacs.gnus.general" 23666 100]]))

The function is the identity and the argument is just the list of messages to include in the virtual group.

Or we may wish to create a group from the results of a search query:

(nnselect-specs
 (nnselect-function . gnus-search-run-query)
 (nnselect-args
  (search-query-spec
   (query . "mark:flag"))
  (search-group-spec
   ("nnimap:home")
   ("nnimap:work"))))

This creates a group including all flagged messages from all groups on two IMAP servers, "home" and "work".

And one last example. Here is a function that runs a search query to find all messages that have been received recently from certain groups:

(defun my-recent-email (args)
  (let ((query-spec
         (list
          (cons 'query
                (format-time-string "SENTSINCE %d-%b-%Y"
                                    (time-subtract nil
                                                   (days-to-time (car args)))))
          (cons 'criteria "")))
        (group-spec (cadr args)))
    (gnus-search-run-query (list (cons 'search-query-spec query-spec)
                                 (cons 'search-group-spec group-spec)))))

Then the following nnselect-specs:

(nnselect-specs
 (nnselect-function . my-recent-email)
 (nnselect-args . (7 (("nnimap:home") ("nnimap:work")))))

will provide a group composed of all messages on the home and work servers received in the last 7 days.

Refreshing the selection of an nnselect group by running the nnselect-function may take a long time to complete. Consequently nnselect groups are not refreshed by default when gnus-group-get-new-news is invoked. In those cases where running the function is not too time-consuming, a non-nil group parameter of nnselect-rescan will allow automatic refreshing. A refresh can always be invoked manually through gnus-group-get-new-news-this-group.

By default a compressed version of the selection is stored (for permanent groups) along with other group information in the newsrc. For cases where this might be undesirable (for example if the selection is a very long list that doesn’t compress well) a non-nil group parameter of nnselect-always-regenerate will prevent the list from being stored, and instead regenerate the list each time it is needed. If more flexibility is desired, nnselect-get-artlist-override-function and nnselect-store-artlist-override-function may be set to functions that get and store the list of articles.

Gnus includes engines for searching a variety of backends. While the details of each search engine vary, the result of a search is always a vector of the sort used by the nnselect method, and the results of queries are usually viewed using an nnselect group. Indeed the standard search function gnus-group-read-ephemeral-search-group just creates an ephemeral nnselect group with the appropriate search query as the nnselect-specs.