emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Turning Gnus groups into real objects


From: Eric Abrahamsen
Subject: Re: Turning Gnus groups into real objects
Date: Sat, 20 Jul 2019 18:41:01 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Lars Ingebrigtsen <address@hidden> writes:

> Eric Abrahamsen <address@hidden> writes:
>

[...]

> Oh, I see -- want the objects to be in Gnus, not just in the backends?
> Yes, then I can see how that'd be more complicated to have the two
> interfaces.
>
> But I don't there's that much value in carrying around the backend
> objects inside Gnus. I think the current list-based server objects
> could still live on the Gnus side. And I think moving away from those
> would lead to, basically, breaking half the Gnus users'.gnus.el files.

Okay, maybe this whole thing would end up being too intrusive, then. The
point would be to change calling conventions of the server functions, to
increase code re-use and composability. I suppose it might be possible
to do a bare minimum of replacing nnoo with structs, but then we
wouldn't be able to replace deffoo with generics. And I don't see how we
could use structs inside the backend file, but lists in the rest of the
code.

>> I'd aim at a few general principles:
>>
>> 1. Move more code into the methods, in particular the base methods.
>
> I'm not sure what you mean here...

See below

>> 2. Where possible, give servers their own process buffer (for if we ever
>> want to make Gnus threaded).
>
> Don't they have that already?

Near as I can tell, all the backends dump their remote responses into
`nntp-server-buffer'. That works fine because they each dump and read in
turn, and erase the buffer when they start. With threading, the
responses get dumped in more or less random order, so they end up
reading each other's responses. I ran into this when I was working on
gnus-search.el, and got excited about searching multiple IMAP servers
concurrently, using threads.

>> 3. Let all servers keep track of a list of "their" groups.
>
> Keep track in what way?
>
>> 4. Wherever possible, pass servers as arguments instead of guessing them
>>    from the environment.
>
> Sure.
>
>> 5. Keep a "real" list of servers, equivalent to `(cons gnus-select-method
>>    (append gnus-secondary-select-methods gnus-server-alist))', so we
>>    don't have to keep looking for them.
>
> I'm not sure what you refer to -- there's a bunch of code that allows
> you to refer to servers based on the name as well as the actual backend
> definition (that has grown for historical reasons)...

Okay, one theoretical example that combines all of the above (and will
probably illustrate why this whole project is a non-starter):

Right now, every time you hit "g" in the Group buffer, Gnus cycles over
all groups, collects those eligible for refresh, rebuilds the relevant
list of servers for those groups, and then asks each server to update
its particular subset of groups.

What I think could be much cleaner (and I'm not saying this is
necessarily a great idea, it's just illustrative) is that
`gnus-get-unread-articles' would look like:

(defun gnus-get-unread-articles (level)
  (dolist (server (gnus-all-servers))
    (gnus-server-update level)))

Where `gnus-all-servers' just returns a list of all the server objects.
`gnus-server-update' would be a generic function looking like:

(cl-defgeneric gnus-server-update ((server gnus-server)
                                   level)
  (let ((groups (seq-filter (lambda (g)
                              (>= level (gnus-info-level g)))
                            (gnus-server-groups server))))
    (when groups
      update groups...)))

This is what I mean by "move code into base methods" (and
`gnus-server-groups' is the "keeping track of their groups" part). This
base method applies to all servers, but different server classes would
have the opportunity to augment it using :before :after and :around
methods, or override it completely.

Again, this particular case is just for illustration of the principle.

Anyway, I'm guessing all this would simply be too intrusive. So if we
wanted to preserve compatibility with backends defined out-of-tree, we
could a) redefine nnoo-declare/defvoo/deffoo to create ad-hoc structs
(probably not), or b) adjust gnus-check-backend-function and
gnus-get-function to check if the server is a list or a struct and
dispatch to different kinds of functions. But doing it this way would
mean having to keep nnoo.el, getting none of the benefits of generic
functions, and adding complexity and confusion.

I can't think of any other way of preserving compatibility. Probably
this just isn't feasible without breaking support.

Eric




reply via email to

[Prev in Thread] Current Thread [Next in Thread]