unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Alexander Adolf <alexander.adolf@condition-alpha.com>
To: Filipp Gunbin <fgunbin@fastmail.fm>
Cc: emacs-devel@gnu.org
Subject: Re: [PATCH] EUDC email addresses via completion-at-point in message-mode
Date: Mon, 02 May 2022 23:38:43 +0200	[thread overview]
Message-ID: <15b3bbf610c12c046aff8cdea3f5e592@condition-alpha.com> (raw)
In-Reply-To: <m2h76b8pay.fsf@fastmail.fm>

[-- Attachment #1: Type: text/plain, Size: 1735 bytes --]

Hello Filipp,

Filipp Gunbin <fgunbin@fastmail.fm> writes:

>> [...]
>> This reads as if t ("do nothing") vs. 'move ("move to the limit of
>> search") should make a difference? A few quick experiments seem to
>> indicate that in practice both seem to behave the same though. In this
>> light, I'm fine with changing 'move to t.
>
> Well honestly I was fooled by save-excursion, and didn't notice the
> return value of (point), with which the value we're talking about _may_
> matter.  However, your regexp will always match, due to \\|^ branch
> which will find bol, so you can just do:
>
> (save-excursion
>   (re-search-backward "\\([:,]\\|^\\)[ \t]*")
>   (match-end 0))

I tried without the surrounding save-excursion, and even then I didn't
notice any difference in behaviour between t and 'move for NOERROR.

Your suggested simplification works just as well, of course. Thanks for
pointing out! Updated patch below.

>> [...]
>> That said, it would probably be desirable for message mode to have
>> different values for both, completion-at-point-functions and
>> completion-styles, depending on where point is (email header, newsgroup
>> header, message body, etc.). But this seems like a wider discussion
>> about the architecture of message.el rather than this patch.
>
> Yes, sounds like another use case for completion-category-overrides.

Hadn't come across that one yet; thanks for the pointer.

Message.el does this:

(add-to-list 'completion-category-defaults '(email (styles substring)))

It seems to me you suggest amending that line in message.el, rather than
having the setq-local in my capf function? I have included this in the
below patch, too.


Many thanks and looking forward to your thoughts,

  --alexander



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-EUDC-email-addresses-via-completion-at-point-in-mess.patch --]
[-- Type: text/x-patch, Size: 10692 bytes --]

From 7da38d56d7dddf4f60f4e8055634a64ef6709870 Mon Sep 17 00:00:00 2001
From: Alexander Adolf <alexander.adolf@condition-alpha.com>
Date: Mon, 2 May 2022 23:01:11 +0200
Subject: [PATCH] EUDC email addresses via completion-at-point in message-mode

* lisp/net/eudc-capf.el (new file): Add new 'eudc-capf-complete'
function.
* lisp/gnus/message.el (message-mode): Add 'eudc-capf-complete' to
'completion-at-point-functions' when a 'message-mode' buffer is
created, removing the FIXME.
* doc/misc/eudc.texi (Inline Query Expansion): Add a new subsection,
describing the new 'completion-at-point' mechanism in 'message-mode'.
* etc/NEWS (EUDC): Describe the new 'completion-at-point' method.
---
 doc/misc/eudc.texi    |  23 ++++++++
 etc/NEWS              |   6 ++
 lisp/gnus/message.el  |   7 ++-
 lisp/net/eudc-capf.el | 133 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 166 insertions(+), 3 deletions(-)
 create mode 100644 lisp/net/eudc-capf.el

diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index d2850282fe..d2a1efeed0 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -713,6 +713,7 @@ be passed to the program.
 
 @node Inline Query Expansion
 @section Inline Query Expansion
+@subsection Inline Query Expansion Using a Key Binding
 
 Inline query expansion is a powerful method to get completion from
 your directory servers.  The most common usage is for expanding names
@@ -885,6 +886,28 @@ An error is signaled.  The expansion aborts.
 Default is @code{select}
 @end defvar
 
+@subsection Inline Query Expansion Using completion-at-point
+
+In addition to providing a dedicated EUDC function for binding to a
+key shortcut (@pxref{Inline Query Expansion Using a Key Binding}),
+EUDC also provides a function to contribute search results to the
+Emacs in-buffer completion system available via the function
+@code{completion-at-point} (@pxref{Identifier
+Inquiries,,,maintaining}) in @code{message-mode} buffers
+(@pxref{Message}).  When using this mechanism, queries are made in the
+multi-server query mode of operation (@pxref{Multi-server Queries}).
+
+When a buffer in @code{message-mode} is created, EUDC's inline
+expansion function is automatically added to the variable
+@code{completion-at-point-functions}.  As a result, whenever
+@code{completion-at-point} is invoked in a @code{message-mode} buffer,
+EUDC will be queried for email addresses matching the words before
+point.  Since this will be useful only when editing specific message
+header fields that require specifying one or more email addresses, an
+additional check is performed whether point is actually in one of
+those header fields.  Thus, any matching email addresses will be
+offered for completion in suitable message header fields only, and not
+in other places, like for example the body of the message.
 
 
 @node The Server Hotlist
diff --git a/etc/NEWS b/etc/NEWS
index f897158afd..9df23ee326 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -951,6 +951,12 @@ is called, and the returned values are used to populate the phrase and
 comment parts (see RFC 5322 for definitions).  In both cases, the
 phrase part will be automatically quoted if necessary.
 
++++
+*** New function 'eudc-capf-complete' with message-mode integration
+EUDC can now contribute email addresses to 'completion-at-point' by
+adding the new function 'eudc-capf-complete' to
+'completion-at-point-functions' in message-mode.
+
 ** eww/shr
 
 +++
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index e7dc089a3c..3cef247522 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -51,6 +51,7 @@
 (require 'yank-media)
 (require 'mailcap)
 (require 'sendmail)
+(require 'eudc-capf)
 
 (autoload 'mailclient-send-it "mailclient")
 
@@ -3180,8 +3181,7 @@ Like `text-mode', but with these additional commands:
     (mail-abbrevs-setup))
    ((message-mail-alias-type-p 'ecomplete)
     (ecomplete-setup)))
-  ;; FIXME: merge the completion tables from ecomplete/bbdb/...?
-  ;;(add-hook 'completion-at-point-functions #'message-ecomplete-capf nil t)
+  (add-hook 'completion-at-point-functions #'eudc-capf-complete -1 t)
   (add-hook 'completion-at-point-functions #'message-completion-function nil t)
   (unless buffer-file-name
     (message-set-auto-save-file-name))
@@ -8364,7 +8364,8 @@ set to nil."
 	(t
 	 (expand-abbrev))))
 
-(add-to-list 'completion-category-defaults '(email (styles substring)))
+(add-to-list 'completion-category-defaults '(email (styles substring
+                                                           partial-completion)))
 
 (defun message--bbdb-query-with-words (words)
   ;; FIXME: This (or something like this) should live on the BBDB side.
diff --git a/lisp/net/eudc-capf.el b/lisp/net/eudc-capf.el
new file mode 100644
index 0000000000..68cbfd93ff
--- /dev/null
+++ b/lisp/net/eudc-capf.el
@@ -0,0 +1,133 @@
+;;; eudc-capf.el --- EUDC - completion-at-point bindings  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; Author: Alexander Adolf
+;;
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;    This library provides functions to deliver email addresses from
+;;    EUDC search results to `completion-at-point'.
+;;
+;;    Email address completion will likely be desirable only in
+;;    situations where designating email recipients plays a role, such
+;;    as when composing or replying to email messages, or when posting
+;;    to newsgroups, possibly with copies of the post being emailed.
+;;    Hence, modes relevant in such contexts, such as for example
+;;    `message-mode' and `mail-mode', often at least to some extent
+;;    provide infrastructure for different functions to be called when
+;;    completing in certain message header fields, or in the body of
+;;    the message.  In other modes for editing email messages or
+;;    newsgroup posts, which do not provide such infrastructure, any
+;;    completion function providing email addresses will need to check
+;;    whether the completion attempt occurs in an appropriate context
+;;    (that is, in a relevant message header field) before providing
+;;    completion candidates.  Two mechanisms are thus provided by this
+;;    library.
+;;
+;;    The first mechanism is intended for use by the modes listed in
+;;    `eudc-capf-modes', and relies on these modes adding
+;;    `eudc-capf-complete' to `completion-at-point-functions', as
+;;    would be usually done for any general-purpose completion
+;;    function.  In this mode of operation, and in order to offer
+;;    email addresses only in contexts where the user would expect
+;;    them, a check is performed whether point is on a line that is a
+;;    message header field suitable for email addresses, such as for
+;;    example "To:", "Cc:", etc.
+;;
+;;    The second mechanism is intended for when the user modifies
+;;    `message-completion-alist' to replace `message-expand-name' with
+;;    the function `eudc-capf-message-expand-name'.  As a result,
+;;    minibuffer completion (`completing-read') for email addresses
+;;    would no longer enabled in `message-mode', but
+;;    `completion-at-point' (in-buffer completion) only.
+
+;;; Usage:
+
+;;    In a major mode, or context where you want email address
+;;    completion, you would do something along the lines of:
+;;
+;;    (require 'eudc-capf)
+;;    (add-hook 'completion-at-point-functions #'eudc-capf-complete -1 t)
+;;
+;;    The minus one argument puts it at the front of the list so it is
+;;    called first, and the t value for the LOCAL parameter causes the
+;;    setting to be buffer local, so as to avoid modifying any global
+;;    setting.
+;;
+;;    The value of the variable `eudc-capf-modes' indicates which
+;;    major modes do such a setup as part of their initialisation
+;;    code.
+
+;;; Code:
+
+(require 'eudc)
+
+(defvar message-email-recipient-header-regexp)
+(defvar mail-abbrev-mode-regexp)
+(declare-function mail-abbrev-in-expansion-header-p "mailabbrev" ())
+
+(defconst eudc-capf-modes '(message-mode)
+  "List of modes in which email address completion is to be attempted.")
+
+;; completion functions
+
+;;;###autoload
+(defun eudc-capf-complete ()
+  "Email address completion function for `completion-at-point-functions'.
+
+This function checks whether the current major mode is one of the
+modes listed in `eudc-capf-modes', and whether point is on a line
+with a message header listing email recipients, that is, a line
+whose beginning matches `message-email-recipient-header-regexp',
+and, if the check succeeds, searches for records matching the
+words before point.
+
+The return value is either nil when no match is found, or a
+completion table as required for functions listed in
+`completion-at-point-functions'."
+  (if (and (seq-some #'derived-mode-p eudc-capf-modes)
+           (let ((mail-abbrev-mode-regexp message-email-recipient-header-regexp))
+             (mail-abbrev-in-expansion-header-p)))
+      (eudc-capf-message-expand-name)))
+
+;;;###autoload
+(defun eudc-capf-message-expand-name ()
+  "Email address completion function for `message-completion-alist'.
+
+When this function is added to `message-completion-alist',
+replacing any existing entry for `message-expand-name' there,
+with an appropriate regular expression such as for example
+`message-email-recipient-header-regexp', then EUDC will be
+queried for email addresses, and the results delivered to
+`completion-at-point'."
+  (if (or eudc-server eudc-server-hotlist)
+      (progn
+        (let* ((beg (save-excursion
+                      (re-search-backward "\\([:,]\\|^\\)[ \t]*")
+                      (match-end 0)))
+               (end (point))
+               (prefix (save-excursion (buffer-substring-no-properties beg end))))
+          (list beg end
+                (completion-table-with-cache
+                 (lambda (_)
+                   (eudc-query-with-words (split-string prefix "[ \t]+") t))
+                 t))))))
+
+(provide 'eudc-capf)
+;;; eudc-capf.el ends here
-- 
2.36.0


  reply	other threads:[~2022-05-02 21:38 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
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 [this message]
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=15b3bbf610c12c046aff8cdea3f5e592@condition-alpha.com \
    --to=alexander.adolf@condition-alpha.com \
    --cc=emacs-devel@gnu.org \
    --cc=fgunbin@fastmail.fm \
    /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).