unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Alexander Adolf <alexander.adolf@condition-alpha.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Thomas Fitzsimmons <fitzsim@fitzsim.org>, emacs-devel@gnu.org
Subject: Re: [PATCH] EUDC email addresses via completion-at-point in message-mode
Date: Fri, 15 Apr 2022 23:58:40 +0200	[thread overview]
Message-ID: <dc51ed8dcb5b1d44bf51859758d120ba@condition-alpha.com> (raw)
In-Reply-To: <jwvtuav93hc.fsf-monnier+emacs@gnu.org>

Hello Stefan,

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> [...]
> Maybe EUDC shouldn't be in charge of providing a CAPF function.

I'd tend to disagree.

> The CAPF function needs to understand the current document's syntax to
> know where an email address is expected, but that part is completely
> unrelated to EUDC itself (and related to the major mode instead).
> [...]

Fully agree.

I think there may be a middle ground. I appreciate you seem to share the
idea of following "separation of concerns", some also call it
"one-thing-well mantra" (doe one thing only, do it well), as it
typically helps keeping code simpler.

A couple of thoughts on completion in message mode:

---------------------------- Begin Quote -----------------------------
Variable: completion-at-point-functions

     The value of this abnormal hook should be a list of functions,
     which are used to compute a completion table (see Basic Completion)
     for completing the text at point. It can be used by major modes to
     provide mode-specific completion tables (see Major Mode
     Conventions).
----------------------------- End Quote ------------------------------

But I think there may be a "catch 22" here, though. If the major mode
provides the completion table(s) itself, fine. But what about completion
tables contributed by 3rd party packages? I don't think a major mode
could, or should have an, inevitably incomplete, list of 3rd party
packages to query for completion tables. IMO it would seem much more
sensible to reverse responsibilities: any package that is capable of
providing additional completion tables for certain major modes, should
register itself with those modes (e.g. by adding itself to
completion-at-point-functions).

In message-mode (there may be others, too), the in-buffer completion
will additionally need to figure out the context where completion is
attempted, i.e. some function will need to be called to determine the
semantic context of the stuff around point in order to choose one or
more suitable functions for delivering completion candidates. For
instance in a programming language buffer, do I need candidates for a
function, or for a variable? For instance in a message buffer, do I need
candidates for an email address, or text snippets for the message body?

In the current architecture for completion-at-point, such checks for
context have to be performed by the functions registered in
completion-at-point-functions. This seems wasteful, as it means a lot of
very similar code all over (possibly with subtly different bugs in each
copy), and an unnecessary runtime burden as completion-at-point may be
called often (for every keystroke in some situations).

mail-mode and message-mode are sort of half way there by providing
mail-complete-alist and message-completion-alist, respectively. Both
variables allow for registering a _single_ function to be called for
buffer lines matching a regex. This already takes the burden of figuring
out the completion context away from the function being called, and
together with the try-all-servers feature recently added to EUDC it
would already suffice to aggregate email address candidates from more
than one source in message-mode.

A more generic mechanism could look like this:

1) Each 3rd party package that wants to provide general purpose
   completion tables for a given major mode, adds a function to the
   respective *-mode-hook that adds that package's completion function
   to completion-at-point-functions (this is current good practice).

2) Each major mode that wants to allow users to have different
   completion tables based on the context where the completion happens,
   offers a *-mode-context-completion-functions-alist variable. The keys
   in this alist should be symbols describing the completion context or
   purpose (for example 'email, 'newsgroup, etc.). The values are
   symbols representing abnormal hook variables. (This is where
   mail-mode and message-mode are half way there.)

3) Users (or init code of 3rd party packages) call add-hook to add
   completion functions to the values of entries in
   *-mode-context-completion-functions-alist variable(s) as they deem
   fit. These functions must be "cooperative" in the sense that they
   should add ":exclusive 'no" to the completion table they return,
   unless there is a particular reason for claiming exclusive completion
   "rights".

4) Each major mode that wants to allow users to have different
   completion tables based on the context where the completion happens,
   does the following:

    4.1) After all mode hooks have been run, sample the current value of
	 completion-at-point-functions, and store it in a variable.

    4.2) Next, set completion-at-point-functions to a single function,
	 which is the mode's completion function.

    4.3) When completion-at-point is called, and hence in the mode's
	 completion function:

	4.3.1) Check whether point is in any of specific completion
	       context.

	4.3.2) If point is in a specific context, consult the
	       *-mode-context-completion-functions-alist variable to
	       determine the list of functions to call. If that is not
	       the case, use the previously sampled value of
	       completion-at-point-functions.

	4.3.3) Do a let-binding setting completion-at-point-functions to
	       the value determined in the previous step, and then call
	       completion-at-point (recursive) within the let context,
	       and return whatever completion-at-point returned. (Can
	       completion-at-point be called recursively? I haven't
	       tried.)

5) Job done.


Apologies for the lengthy explanation...


  --alexander





  reply	other threads:[~2022-04-15 21:58 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-09 16:24 [PATCH] EUDC email addresses via completion-at-point in message-mode Alexander Adolf
2022-04-12 21:12 ` Thomas Fitzsimmons
2022-04-13 14:44   ` Alexander Adolf
2022-04-14  0:26     ` Thomas Fitzsimmons
2022-04-15 21:23       ` Alexander Adolf
2022-04-14 13:02     ` Eric S Fraga
2022-04-14 13:27       ` Thomas Fitzsimmons
2022-04-14 13:52         ` Eric S Fraga
2022-04-15 21:39           ` Alexander Adolf
2022-04-17 12:12             ` Eric S Fraga
2022-04-15 21:35       ` Alexander Adolf
2022-04-17 12:20         ` Eric S Fraga
2022-04-17 13:58           ` Thomas Fitzsimmons
2022-04-17 17:21             ` Eric S Fraga
2022-04-14 14:02     ` Stefan Monnier
2022-04-15 21:58       ` Alexander Adolf [this message]
2022-04-15 22:57         ` Eric Abrahamsen
2022-04-14  1:44 ` Eric Abrahamsen
2022-04-14 13:04   ` Eric S Fraga
2022-04-14 15:17     ` Eric Abrahamsen
2022-04-14 15:26       ` Stefan Monnier
2022-04-15 16:31         ` Eric Abrahamsen
2022-04-15 17:17           ` Stefan Monnier
2022-04-15 22:30           ` Alexander Adolf
2022-04-15 22:16   ` Alexander Adolf
2022-04-15 22:58     ` Stefan Monnier
2022-04-26 14:39 ` Alexander Adolf
2022-04-26 18:58   ` Filipp Gunbin
2022-04-28 17:15     ` Alexander Adolf
2022-04-29 14:43       ` Thomas Fitzsimmons
2022-05-02 17:10         ` Alexander Adolf
2022-05-03 18:03           ` Thomas Fitzsimmons
2022-05-05 16:32             ` Alexander Adolf
2022-05-05 16:57               ` Thomas Fitzsimmons
2022-05-10 21:16                 ` Thomas Fitzsimmons
2022-05-16 12:35                   ` Alexander Adolf
2022-04-29 23:04       ` Filipp Gunbin
2022-05-02 21:38         ` Alexander Adolf
2022-05-02 22:32           ` Filipp Gunbin
2022-05-03 16:18             ` Alexander Adolf
2022-05-03 16:22   ` Alexander Adolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dc51ed8dcb5b1d44bf51859758d120ba@condition-alpha.com \
    --to=alexander.adolf@condition-alpha.com \
    --cc=emacs-devel@gnu.org \
    --cc=fitzsim@fitzsim.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).