emacs-devel
[Top][All Lists]
Advanced

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

Turning Gnus groups into real objects


From: Eric Abrahamsen
Subject: Turning Gnus groups into real objects
Date: Wed, 17 Jul 2019 12:29:34 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

[The following is some musings on changing the implementation of
mail/news groups in Gnus, and can be ignored if that doesn't interest
you. I'll send in actual code as bug reports, later.]

I've started thinking about the best way to go about turning Gnus groups
into real objects, and wanted to put some ideas down here.

Currently, Gnus groups are represented using lists -- these lists are
referred to as "infos". There's also the concept of an "entry", which is
basically an unread-message count (an integer) appended to the front of
an info. The term "group" usually just means the string name of the
group.

I'd like to turn groups into real objects using EIEIO. Advantages
include making the code more legible -- removing the distinction between
group/info/entry, and dropping a lot of boilerplate code. It would also
allow very easy adjustments to different kinds of groups: ie a "draft
group" class, an "archive group" class, with their own different
behaviors. The nnimap and nnmaildir backends already extend groups with
extra information, and having actual classes would make that less
awkward.

Thinking about the least-disruptive way of getting there, it seemed like
a good first step to fix up the accessor functions used to make changes
to group data.

Group infos are manipulated using a series of `gnus-info-*' getter
macros (starting line 2797 in gnus.el), with a corresponding series of
`gnus-info-set-*' setter macros, though the setters are used less often.
In fact, quite a bit of the Gnus code ignores the getters/setters
altogether, and manipulates the info lists directly (with code like
"(setcar (nthcdr 3 info)...)", etc).

So I thought a good first step would be to regularize the code so that
it only uses the accessors to touch group data, making it easier to
later change the underlying implementation. But this is going to involve
a fair amount of personal preference.

First of all, I'd love to get rid of the group/info/entry distinction,
and only have "groups" (plus "group-name", if we have to refer to the
string name). So the accessors would be named "gnus-group-*" instead of
"gnus-info-*".

A further personal preference is using a getter function, and then
pairing that with `setf' to set the value (as opposed to having a
distinct setter function). I don't have a very strong argument for this,
I just find it conceptually cleaner.

When defining classes, a slot can have a :reader tag and a :writer tag,
or an :accessor tag that does both. So for example the current code
would look like:

(defclass gnus-group ()
  ((marks
    :type list
    :initform nil
    :writer gnus-info-set-marks
    :reader gnus-info-marks)
   ...))

Whereas my mild preference would be for:

(defclass gnus-group ()
  ((marks
    :type list
    :initform nil
    :accessor gnus-info-marks)
   ...))

And using `setf' with that, to set. The existing `gnus-info-set-*'
macros aren't used all that much, and it wouldn't be too much work to
switch them out for `setf's.

But it would also be great to drop the info nomenclature altogether, in
which case (adding backwards compatibility) all the mark handling code
would look like:

(defclass gnus-group ()
  ((marks
    :type list
    :initform nil
    :accessor gnus-group-marks)
   ...))

(define-obsolete-function-alias 'gnus-info-marks 'gnus-group-marks "27.1")

(defmacro gnus-info-set-marks (group marks &optional _extend)
  (setf (gnus-group-marks info) marks))

(make-obsolete 'gnus-info-set-marks
               "use `setf' with `gnus-group-marks' instead" "27.1")

This is already fairly long, I'll leave it at that. I'm curious if
anyone's got any opinions about this.

Thanks,
Eric




reply via email to

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