unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Thoughts on Refactoring In-Buffer Completion In message.el
@ 2022-06-23 15:26 Alexander Adolf
  2022-06-25  4:35 ` Thomas Fitzsimmons
  2022-06-25  8:22 ` Stefan Monnier
  0 siblings, 2 replies; 16+ messages in thread
From: Alexander Adolf @ 2022-06-23 15:26 UTC (permalink / raw)
  To: emacs-devel

Hello,

<disclaimer>
  message.el is a massive file (some 8600 lines), and I can't claim
  having read or understood any substantial portion of it. All
  statements solely rely on the (small) portions of the code around
  completion in message.el, which I have looked at. Thus, as always in
  life, I shall be looking froward to standing corrected and
  enlightened wherever I deserve it. ;-)
</disclaimer>

Regarding in-buffer completion, message-mode is probably a rather
specific case as it has succinctly distinct in-buffer completion
contexts. Think for instance of a body or subject line, vs. a To header
line, vs. a References header line, vs. a Newsgroups header line.

Currently, message-mode employs two mechanisms for handling these
contextss:

• Its completion function message-completion-function is registered in
  completion-at-point-functions, and marshals the in-buffer completion
  contexts via the variable message-completion-alist.
  message-completion-alist in turn configures the (one and only)
  function to be called for completion candidates in a given context.

• The completion style to use for email addresses is added to the
  variable completion-category-defaults.

What made me start scratching my head about this, was the wish to
combine email address candidates from more than one source, and have
them be presented in a single list by completion-at-point. Since EUDC
had recently gained the ability to return combined search results from
several of its back-ends [1], I put together a new EUDC function that
can be added to completion-at-point-functions. My new function gets
added to the front of completion-at-point-functions in message-mode, and
email address completion candidates from the EUDC back-ends I have
configured show up when completion-at-point is triggered [2].

[1] commit 0470a4a939772c4bd25123b15f5eadab41f8bee5
[2] commit 620ac6735520aea97ce49059b0df38ed41930b6b


So far so good; this satisfies my immediate use-case.


Job done? Looking at [2], you'll notice that I need to check in my new
EUDC completion function whether point is actually on a To, Cc, etc.
line. Otherwise email addresses would happily be offered as completion
candidates in the middle of the subject, or in the body. Having this
extra check for an email message header line in EUDC code didn't feel
quite right, however. Think "separation of concerns".

Further looking at message.el, and how in-buffer completion is handled
there, you'll find that there is (more or less) close integration with
ecomplete, mailabbrev, EUDC, and bbdb in message.el. Consider, for
instance the defun starting at line 8378 of message.el:

┌────
│ 8377  (defun message--bbdb-query-with-words (words)
│ 8378    ;; FIXME: This (or something like this) should live on the BBDB side.
│ 8379    (when (fboundp 'bbdb-records)
└────
Listing 1: lisp/gnus/message.el "separation of concerns" example

What more should I add? I fully agree with the comment in line 8378.
Again, think "separation of concerns".


On this backdrop, where would I see room for improvement?


Overall, there are a couple of bits an pieces for in-buffer completion
in place in message.el already. But it seems they were developed/added
independently of each other, and a little more orchestration could
perhaps help to make things more flexible, but without reinventing the
wheel.

1) In message.el, combine both completion control mechanisms into a
   single one.

   At first glance from the end user's point of view,
   message-completion-alist and completion-category-defaults can be
   perceived as two distinct mechanisms, and it is not immediately
   obvious which completion style category applies for which regex in
   message-completion-alist. Only by inspecting line 8404 in message.el,
   one can discover which category is used:

   ┌────
   │ 8398  (defun message--name-table (orig-string)
   │ 8399    (let ((orig-words (split-string orig-string "[ \t]+"))
   │ 8400          eudc-responses
   │ 8401          bbdb-responses)
   │ 8402      (lambda (string pred action)
   │ 8403        (pcase action
   │ 8404          ('metadata '(metadata (category . email)))
   └────
   Listing 2: lisp/gnus/message.el completion styles handling

   Thus, I would propose to change message-completion-alist from being
   alist of (RE . FUN), to become an alist of (RE . PLIST). Two
   properties for the inner plist would initially defined; one for
   specifying the completion style, and another one for specifying the
   completion-at-point-functions. With this, the new default value of
   message-completion-alist could for example be along the lines of:

   ┌────
   │ (defcustom message-completion-alist
   │   `((,message-newgroups-header-regexp
   │      . '(:capf-style 'newsgroup
   │          :capf-funs  '(gnus-capf-complete)))    ;; hypothetical
   │     (,message-email-recipient-header-regexp
   │       . '(:capf-style 'email
   │           :capf-funs  '(eudc-capf-complete))))  ;; exists
   │   "docstring"
   │   )
   └────

   As an aside: considering the FIXME comment in the function
   message-expand-group, newsgroup completion would seem to be able to
   benefit from this change, too.

   If none of the regular expressions matches, the settings in
   completion-at-point-functions, and
   completion-category-defaults/overrides will apply as before, or in
   other modes.

   With such an approach, the end user would get a positive assertion as
   to which completion style is used in each part of a message buffer.


2) Refactor ecomplete, mailabbrev, and bbdb stuff out of message.el as
   much as possible.

   As the FIXME comment in listing 1 above suggests, any "query with
   words" functions, or other ecomplete, mailabbrev, or bbdb specific
   functions should be in the respective packages themselves
   ("separation of concerns"). Also, as EUDC performs search result
   aggregation across sources, these packages should implement EUDC
   back-ends to provide their results via EUDC. Message.el should thus
   not interact with any email address database directly, but instead
   provide a default configuration where completion-at-point queries
   EUDC for email addresses.


In all cases, current default behaviour should be retained as much as
reasonably possible, of course.


Many thanks and looking forward to your thoughts,

  -–alexander



^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: Thoughts on Refactoring In-Buffer Completion In message.el
@ 2022-08-13 13:11 Alexander Adolf
  2022-08-17  1:54 ` Stefan Monnier
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Adolf @ 2022-08-13 13:11 UTC (permalink / raw)
  To: emacs-devel

Hello,

it's been a while since the last update on this subject. I have chatted
with Thomas, the maintainer of EUDC, and he stated a preference for
having the two new EUDC back-ends (one for ecomplete, and one for
mailabbrev) in a separate patch series.

I will thus separate these two things out into a separate proposal, and
will update the "message completion refactoring proposal" accordingly.

Above and beyond that, I still need to do the following things for the
present "message completion refactoring proposal":

- figure out, and implement how to add completion category metadata to
  completion tables;

- write a NEWS entry;

- update the texi manual for message.


Cheers,

  --alexander



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2022-08-17  2:45 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-23 15:26 Thoughts on Refactoring In-Buffer Completion In message.el Alexander Adolf
2022-06-25  4:35 ` Thomas Fitzsimmons
2022-06-27 15:48   ` Alexander Adolf
2022-06-25  8:22 ` Stefan Monnier
2022-06-27 16:37   ` Alexander Adolf
2022-06-28 15:49     ` Stefan Monnier
2022-07-19 21:41       ` Alexander Adolf
2022-07-19 22:13         ` Stefan Monnier
2022-07-20 20:59           ` Alexander Adolf
2022-07-20 23:59             ` Stefan Monnier
2022-07-22 13:20               ` Alexander Adolf
2022-07-22 13:58                 ` Alexander Adolf
2022-07-27 21:16               ` Alexander Adolf
2022-08-17  2:45                 ` Stefan Monnier
  -- strict thread matches above, loose matches on Subject: below --
2022-08-13 13:11 Alexander Adolf
2022-08-17  1:54 ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).