unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Alexander Adolf <alexander.adolf@condition-alpha.com>
To: emacs-devel@gnu.org
Subject: [PATCH] EUDC email addresses via completion-at-point in message-mode
Date: Sat, 09 Apr 2022 18:24:02 +0200	[thread overview]
Message-ID: <ea2bb7e91bee666649cc152abbe9312a@condition-alpha.com> (raw)

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

Hello,

when switching to a new in-buffer completion user interface package
which is solely based on completion-at-point, I observed that email
address completion in message-mode happens in the minibuffer, regardless
of what UI on top of completion-at-point I use. Also, EUDC's ability to
aggregate search results from several servers, which was recently added
with commit 0470a4a939772c4bd25123b15f5eadab41f8bee5, was not kicking
in, i.e. I was presented results from a single EUDC server only.

Browsing through message.el quickly brought me to the sixth of the 21
FIXMEs in that file, which reads on line 3183:

  ;; 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 #'message-completion-function nil t)

Thus, the most straightforward solution to my problem seemed to make a
new EUDC function that can be added to completion-at-point-functions,
and to update message-mode to actually add that function to
completion-at-point-functions. This is what the below attached patch
does.

As a result, both of my issues are fixed: the new completion-at-point
user interface presents the email addresses, and I get results from all
configured EUDC servers.

For EUDC, the added value is that it gains a function for
completion-at-point-functions, which it didn't have before. The new
function also makes use of EUDC's new "try all servers" feature,
merging the search results from several sources.

For message-mode, the added value is that the FIXME regarding the
merging of email address completion tables is addressed, as this is now
done by EUDC. Further sources for email addresses can be added to EUDC
by writing EUDC back-ends for them, which is not difficult in my
experience. Any new email address sources will thus become available in
message-mode without any further changes in message-mode itself (neither
code nor config).


Hoping to have helped, 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: 10197 bytes --]

From 0fe373c62f0a5186f9609bb33b0890cce2fb8dcc Mon Sep 17 00:00:00 2001
From: Alexander Adolf <alexander.adolf@condition-alpha.com>
Date: Fri, 8 Apr 2022 22:28:45 +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  |   4 +-
 lisp/net/eudc-capf.el | 130 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 161 insertions(+), 2 deletions(-)
 create mode 100644 lisp/net/eudc-capf.el

diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index 71e3e6b9ed..cc98b0606c 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -711,6 +711,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
@@ -883,6 +884,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 2fac893cc5..d6790424a7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -773,6 +773,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 30734b8f1a..9800167147 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))
diff --git a/lisp/net/eudc-capf.el b/lisp/net/eudc-capf.el
new file mode 100644
index 0000000000..673fbb440f
--- /dev/null
+++ b/lisp/net/eudc-capf.el
@@ -0,0 +1,130 @@
+;;; 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:
+
+;;    (require 'eudc-capf)
+;;    (add-hook 'completion-at-point-functions #'eudc-capf-complete -1 t)
+
+;;; 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'.  When a completion table is
+returned, it is marked as non-exclusive."
+  (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)
+    nil))
+
+;;;###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 (and (boundp 'eudc-server) eudc-server)
+          (and (boundp 'eudc-server-hotlist) eudc-server-hotlist))
+      (progn
+        (setq-local completion-styles '(substring partial-completion)
+                    completion-ignore-case t)
+        (let* ((beg (save-excursion
+                      (if (re-search-backward "\\([:,]\\|^\\)[ \t]*"
+                                              (point-at-bol) 'move)
+                          (goto-char (match-end 0)))
+                      (point)))
+               (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)
+                :exclusive 'no)))
+    nil))
+
+(provide 'eudc-capf)
+;;; eudc-capf.el ends here
-- 
2.35.1


             reply	other threads:[~2022-04-09 16:24 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-09 16:24 Alexander Adolf [this message]
2022-04-12 21:12 ` [PATCH] EUDC email addresses via completion-at-point in message-mode 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
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=ea2bb7e91bee666649cc152abbe9312a@condition-alpha.com \
    --to=alexander.adolf@condition-alpha.com \
    --cc=emacs-devel@gnu.org \
    /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).