Subject: bug#59314: 29.0.50; EUDC and message-mode header completion

From: Alexander Adolf <[email-masked]>
Date: Thu, 01 Dec 2022 16:48:20 +0100

Hello Eric,

Eric Abrahamsen <[email-masked]> writes:

> [...]
> In fact this whole message-mode thing is an impossible tangle, burritos
> within burritos, and it would be great to get rid of it altogether.
> [...]
> So I need to clobber `message-expand-name' altogether.
>
> And EUDC having a function on `completion-at-point-functions' is
> wrapping yet another burrito outside the existing burritos, because now
> EUDC has a completion function both inside and outside message-mode's
> own completion machinery.
>
> In fact the docstring of `eudc-capf-message-expand-name' makes it sound
> like it thinks it's being called as part of `message-expand-name', but
> now it isn't -- it's being called as part of the capf machinery. Or
> rather, it could potentially be called in both places.
>
> I think a half-stick of dynamite is the only real solution.
> [...]

Perhaps we can be slightly more CONstructive that this. ;-)))

I am preparing a patch to message.el which refactors
`message-completion-alist` along the lines of this:

---------------------------- Begin Quote -----------------------------
(defcustom message-completion-alist
  `((,message-newgroups-header-regexp . (:category newsgroup
                                         :fieldsep-re "\\([:,]\\|^\\)[ \t]*"
                                         :completions ,#'message-expand-group))
    (,message-email-recipient-header-regexp . (:category email
                                               :fieldsep-re "\\([:,]\\|^\\)[ \t]*"
                                               :completions ,#'eudc-capf-message-expand-name)))
  "Alist of (RE . RECIPE), defining completion contexts.
This variable controls how `message-completion-function' performs
in-buffer completion.  RECIPE is either a function (deprecated),
or a plist.

When `message-completion-function' is invoked, and point is on a
line matching one of the REs in the alist, the settings in the
corresponding RECIPE are applied.

When RECIPE is a function, it is called for completion.  RECIPE
should be a function that obeys the same rules as those of
`completion-at-point-functions'.

When RECIPE is a plist, the properties control how in-buffer
completion is performed.  The following properties are currently
defined:

:category

    The symbol defining the category in
    `completion-category-defaults' to use for completion.  Also
    see `completion-category-overrides', and `completion-styles'.

:fieldsep-re

    The regular expression to use when scanning backwards in the
    buffer.  All text between point, and any preceding text
    matching this regular expression, will be used as the prefix
    for finding completion candidates.

:completions

    The function that provides completions, and that obeys the
    same rules as those of `completion-at-point-functions'.
    In-buffer completion will be performed as if
    `completion-at-point-functions' had been set to this value."
  :version "29.1"
  :group 'message
  :type '(alist :key-type regexp
                :value-type (choice (plist)
                                    (function
                                     :tag "Completion function (deprecated)"))))
----------------------------- End Quote ------------------------------

As you can see, `eudc-capf-message-expand-name` effectively replaces
`message-expand-name` altogether:

---------------------------- Begin Quote -----------------------------
(make-obsolete 'message-expand-name 'eudc-capf-message-expand-name
               "29.1")
----------------------------- End Quote ------------------------------

The patch goes on to remove everything relating to ecomplete,
mailabbrev, bbdb, and the likes from message.el, too. Get rid of all the
burritos, except one. The one and only source for email addresses in
message.el IMHO should be EUDC, and the one and only completion UI
should be whatever CAPF uses. Any and all sources for email addresses
should implement back-ends for EUDC, so they can be queried via EUDC,
which does the aggregation of results from the different sources, and
delivers it back to message.el as one lump.

EUDC backends:   ldap   ecomplete   mailabbrev   bbdb    you-name-it
               \________________________ ____________________________/
                                        V
                                        |
                                        V
eudc-capf.el:            eudc-capf-message-expand-name
                                        |
                                        V
message.el:               message-completion-function
                                        |
                                        V
minibuffer.el                completion-at-point
                                        |
                                        V
                   [ optional completion UI (for example corfu) ]

As you may imagine, this is a bigger patch, and I am discussing it on
emacs-devel with Stefan Monnier. So it'll still be a little while until
it might hopefully get merged, and the burritos unwrapped.

Many thanks and looking forward to your thoughts,

  --alexander