emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ebdb 03594c7 3/3: Tweak completion support


From: Eric Abrahamsen
Subject: [elpa] externals/ebdb 03594c7 3/3: Tweak completion support
Date: Sun, 10 Mar 2019 12:14:26 -0400 (EDT)

branch: externals/ebdb
commit 03594c73081c1cd8f17b3e5c80791c2b8b6f60a8
Author: Eric Abrahamsen <address@hidden>
Commit: Eric Abrahamsen <address@hidden>

    Tweak completion support
    
    The gist of this is that it provides two kinds of completion support:
    the `ebdb-dwim-completion-cache' which is simply a list of "name
    <mail>" strings for use in mail composition buffers, and the
    `ebdb-record-completion-table', which is a general-purpose completion
    table for selecting a record.
    
    Squashed commit of the following:
    
    commit 5f55a397da48d58ff411c509cc0105e1f2b60ac0
    Author: Eric Abrahamsen <address@hidden>
    Date:   Thu Mar 7 18:13:55 2019 -0800
    
        Remove option ebdb-wl-use-ebdb-completion
    
        * ebdb-wl.el (ebdb-insinuate-wl): We've already got the option
          ebdb-complete-mail for this.
    
    commit 1776b0275e4c2d20713ba3a36ec849d3bb19a936
    Author: Eric Abrahamsen <address@hidden>
    Date:   Thu Mar 7 16:50:57 2019 -0800
    
        Arrange for post-completion stuff to be called even with capf
    
        * ebdb-message.el (ebdb-message-complete-mail-cleanup): New function
          that simply passes the correct arguments to
          `ebdb-complete-mail-cleanup'.
          (ebdb-insinuate-message): Add the above to a buffer-local value of
          `choose-completion-string-functions'.
    
    commit efaafa1cd438e41bbcab1fd6ed8a3c32922294d0
    Author: Eric Abrahamsen <address@hidden>
    Date:   Thu Mar 7 12:02:15 2019 -0800
    
        Docstring fixes
    
    commit d234439f97fea6a796f097e96b65da23fbfa867d
    Author: Eric Abrahamsen <address@hidden>
    Date:   Thu Mar 7 12:01:52 2019 -0800
    
        Update docs about completion options
    
    commit 84b8b3d707a02196e71ba447cf7df294a088e285
    Author: Eric Abrahamsen <address@hidden>
    Date:   Wed Mar 6 13:41:30 2019 -0800
    
        Make more interesting completion table, remove some functions
    
        * ebdb-com.el (ebdb-record-completion-table): This function now uses
          the string to complete as an actual search.
          (ebdb-completing-read-record): Simplify this record somewhat; assume
          that there's only one matching record.
          (ebdb-completing-read-records): Delete this function, there isn't
          really a use for it.
    
    commit 74e34625d6b9e0db4cd8ae5b00645364a1591f1c
    Author: Eric Abrahamsen <address@hidden>
    Date:   Thu Jan 17 10:41:51 2019 -0800
    
        WIP on manual updates
    
    commit 9892a4401d9c16f50c3f52fdb4dc86550ca4ff9d
    Author: Eric Abrahamsen <address@hidden>
    Date:   Wed Jan 16 12:21:44 2019 -0800
    
        Turns out the completion functions could be simpler
    
        * ebdb-com.el (ebdb-record-completion-table): So *that's* what
          `complete-with-action' is for.
        * ebdb.el (ebdb-mail-dwim-collection-function): Here, too.
    
    commit 52cbe9e94aa0f4acb4480ec75b87632c85c30ce9
    Author: Eric Abrahamsen <address@hidden>
    Date:   Mon Jan 14 13:57:50 2019 -0800
    
        New completion mechanisms, next bit
    
    commit 9b2087e494636333c1e66da17eef55cc69b7f121
    Author: Eric Abrahamsen <address@hidden>
    Date:   Fri Dec 28 13:44:21 2018 -0800
    
        WIP on new completion mechanisms
---
 ebdb-com.el      |  86 ++++++++++---------
 ebdb-complete.el |  75 ++++-------------
 ebdb-message.el  |  40 +++++++--
 ebdb-wl.el       |  13 +--
 ebdb.el          |  76 +++++++++++++++--
 ebdb.info        | 253 +++++++++++++++++++++++++++++++++++++------------------
 ebdb.org         |  93 ++++++++++++++++----
 ebdb.texi        | 117 ++++++++++++++++++++-----
 8 files changed, 504 insertions(+), 249 deletions(-)

diff --git a/ebdb-com.el b/ebdb-com.el
index efd0798..8277a77 100644
--- a/ebdb-com.el
+++ b/ebdb-com.el
@@ -2313,9 +2313,9 @@ The search results are displayed in the EBDB buffer using 
formatter FMT."
 ;;;###autoload
 (defun ebdb-search-single-record (record &optional fmt)
   "Prompt for a single RECORD, and display it."
-  (interactive (list (ebdb-completing-read-records "Display records: ")
+  (interactive (list (ebdb-completing-read-record "Display record: ")
                      (ebdb-formatter-prefix)))
-  (ebdb-display-records record fmt))
+  (ebdb-display-records (list record) fmt))
 
 (defun ebdb-search-prog (function &optional fmt)
   "Search records using FUNCTION.
@@ -2424,7 +2424,39 @@ otherwise inline."
       (ebdb-cite-records records arg))
     (pop-to-buffer buf)))
 
-;;; completion
+;;; Completion
+
+(defun ebdb-record-completion-table (str pred action)
+  "Function used as a completion table for EBDB records.
+STR is used to search the database.  The return value is the
+completed name string."
+  (let* ((completion-ignore-case ebdb-case-fold-search)
+        (newstring (concat "^" str))
+        ;; Completion searches the database, but we only use "fast
+        ;; lookup" search clauses which use the hashtable, instead of
+        ;; cycling over all records one by one.  Still pretty slow,
+        ;; though.  Also unfortunate is that EBDB has a broader
+        ;; concept of "matching string" than the completion
+        ;; framework, which will later filter out strings that we
+        ;; consider matching (e.g. according to character folding, or
+        ;; romanization of non-English scripts).  Perhaps we could
+        ;; make our own completion style to take care of that.
+        (strings
+         (mapcar #'ebdb-string
+                 (if (string-empty-p str)
+                     (ebdb-records)
+                   (ebdb-search
+                    (ebdb-records)
+                    (append
+                     (list `(ebdb-field-name ,newstring)
+                           `(ebdb-field-mail ,newstring)
+                           `(ebdb-field-tags ,newstring))
+                     (mapcar (lambda (f)
+                               (list f newstring))
+                             ebdb-hash-extra-predicates)))))))
+    (if (eq action 'metadata)
+       '(metadata . ((category . ebdb-contact)))
+      (complete-with-action action strings str pred))))
 
 ;;;###autoload
 (defun ebdb-completion-predicate (key records)
@@ -2441,44 +2473,16 @@ Obey `ebdb-completion-list'."
             (ebdb-hash-p key record ebdb-completion-list))
           nil))))
 
-(defun ebdb-completing-read-records (prompt &optional omit-records)
-  "Read and return list of records from the ebdb.
-Completion is done according to `ebdb-completion-list', with
-prompt PROMPT.  If the user just hits return, nil is returned.
-Otherwise, a valid response is forced.  Optional argument
-OMIT-RECORDS is a list of records that should never be returned."
-  (unless ebdb-record-tracker
-    (ebdb-load))
-  (let* ((completion-ignore-case t)
-         (string (completing-read prompt ebdb-hashtable
-                                  'ebdb-completion-predicate t)))
-    (unless (string= "" string)
-      (let (records)
-       (dolist (record (gethash string ebdb-hashtable))
-         (when (and (not (memq record omit-records))
-                    (not (memq record records)))
-           (push record records)))
-       records))))
-
-
-(defun ebdb-completing-read-record (prompt &optional omit-records)
-  "Prompt for and return a single record from the ebdb.
-Completion is done according to `ebdb-completion-list', with
-prompt PROMPT.  If the user just hits return, nil is
-returned.  Otherwise, a valid response is forced.  If OMIT-RECORDS
-is non-nil it should be a list of records to dis-allow completion
-with."
-  (let ((records (ebdb-completing-read-records prompt omit-records)))
-    (cond ((eq (length records) 1)
-           (car records))
-          ((> (length records) 1)
-           (ebdb-display-records records ebdb-default-oneline-formatter)
-           (let* ((count (length records))
-                  (result (completing-read
-                           (format "Which record (1-%s): " count)
-                           (mapcar 'number-to-string (number-sequence 1 count))
-                           nil t)))
-             (nth (1- (string-to-number result)) records))))))
+(defun ebdb-completing-read-record (prompt)
+  "Read and return a record from the EBDB.
+PROMPT is used in `completing-read'.  Actual completion is done
+using the function `ebdb-record-completion-table'."
+  (let ((string (completing-read
+                prompt #'ebdb-record-completion-table nil t))
+       records)
+    (unless (string-empty-p string)
+      (or (car-safe (ebdb-gethash string '(fl-name aka mail)))
+         (message "No matching records for \"%s\"" string)))))
 
 ;;;###autoload
 (defun ebdb-completing-read-mails (prompt &optional init)
diff --git a/ebdb-complete.el b/ebdb-complete.el
index e293199..85aee73 100644
--- a/ebdb-complete.el
+++ b/ebdb-complete.el
@@ -1,8 +1,9 @@
-;;; ebdb-complete.el --- EBDB window as an email-chooser      -*- 
lexical-binding: t; -*-
+;;; ebdb-complete.el --- Completion functionality for EBDB      -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2017  Free Software Foundation, Inc.
 
 ;; Author: Feng Shu <address@hidden>
+;; Maintainer: Eric Abrahamsen <address@hidden>
 ;; Keywords: mail, convenience
 
 ;; This program is free software; you can redistribute it and/or modify
@@ -20,80 +21,35 @@
 
 ;;; Commentary:
 
-;; ## Introduce ##
-;;
-;; ebdb-complete is a EBDB tool, when in headers (TO: and CC:) of message-mode
-;; buffer, Type TAB key will pop up a EBDB window as email-chooser.
+;; This file contains the function `ebdb-complete' which pops
+;; up a full EBDB window as email-chooser, typically in mail
+;; composition buffers.
+
+;; The simplest installation method is to call:
 
-;; ## Usage ##
-;;
-;; ### The easiest way ###
-;;
-;; Add the below line to your emacs config file.
-;;
-;; ```
-;; (require 'ebdb-complete)
 ;; (ebdb-complete-enable)
-;; ```
-;;
-;; ### The manual way ###
+
+;; This will bind TAB in message-mode and mail-mode to
+;; `ebdb-complete', which will pop up a full EBDB buffer as a contact
+;; chooser.
 ;;
-;; The function `ebdb-complete-enable' only rebind some key in `ebdb-mode-map',
-;; `message-mode-map' and `mail-mode-map', user can do this job by hand,
-;; for example:
+;; This can also be done manually, e.g.:
 ;;
-;; ```
-;; ;; ebdb-mode
 ;; (define-key ebdb-mode-map "q" 'ebdb-complete-quit-window)
 ;; (define-key ebdb-mode-map "\C-c\C-c" 'ebdb-complete-push-mail)
 ;; (define-key ebdb-mode-map (kbd "RET") 
'ebdb-complete-push-mail-and-quit-window)
 ;; (define-key message-mode-map "\t" 'ebdb-complete-message-tab)
 ;; (define-key mail-mode-map "\t" 'ebdb-complete-message-tab)
-;; ```
 
 ;;; Code:
 (require 'ebdb-com)
 (require 'message)
 (require 'sendmail)
 
-;; Experimental completion-at-point function.  I'm not sure this is a
-;; good idea yet -- with a large enough EBDB database, nearly any
-;; string is completable, meaning the other completion-at-point
-;; functions will rarely get a chance.
-(defun ebdb-completion-at-point-function ()
-  "Try to find an EBDB completion for the text at point.
-For use in `completion-at-point-functions'."
-  ;; Might consider restricting this to text-mode buffers -- would you
-  ;; ever want to complete contact names in prog-mode?
-  (let* ((start (point))
-        (chunk (buffer-substring
-                (save-excursion
-                  ;; First try going back two words.
-                  (forward-word -2)
-                  (setq start (point)))
-                (point)))
-        (completions (all-completions (downcase chunk) ebdb-hashtable)))
-    (unless completions
-      ;; If that didn't work, try just one word.
-      (setq chunk (buffer-substring
-                  (save-excursion
-                    (forward-word -1)
-                    (setq start (point)))
-                  (point))
-           completions (all-completions (downcase chunk) ebdb-hashtable)))
-    (when completions
-      (list start (point)
-           (mapcar
-            (lambda (str)
-              ;; Gross.
-              (if (string-match-p "@" str)
-                  str
-                (capitalize str)))
-            completions)
-           '(:exclusive no)))))
+;;;###autoload
 
 (defvar ebdb-complete-info (make-hash-table)
-  "A hashtable, record buffer, buffer-window and window-point")
+  "A hashtable recording buffer, buffer-window and window-point")
 
 (defun ebdb-complete-push-mail (records &optional _ arg)
   "Push email-address(es) of `records' to buffer in `ebdb-complete-info'."
@@ -154,6 +110,7 @@ Before quit, this command will do some clean jobs."
      (skip-syntax-backward "w_")
      (point))))
 
+;;;###autoload
 (defun ebdb-complete ()
   "Open EBDB window as an email-address selector,
 if Word at point is found, EBDB will search this word
@@ -233,6 +190,7 @@ when in message body, this command will indent regular 
text."
   (define-key ebdb-mode-map "\C-c\C-c" 'ebdb-complete-push-mail)
   (define-key ebdb-mode-map (kbd "RET") 
'ebdb-complete-push-mail-and-quit-window))
 
+;;;###autoload
 (defun ebdb-complete-enable ()
   "Enable ebdb-complete, it will rebind TAB key in `message-mode-map'."
   (interactive)
@@ -242,7 +200,6 @@ when in message body, this command will indent regular 
text."
   (define-key mail-mode-map "\t" 'ebdb-complete-message-tab)
   (message "ebdb-complete: Override EBDB keybindings: `q', `C-c C-c' and 
`RET'"))
 
-
 (provide 'ebdb-complete)
 
 ;; Local Variables:
diff --git a/ebdb-message.el b/ebdb-message.el
index 1cbecd5..ada381f 100644
--- a/ebdb-message.el
+++ b/ebdb-message.el
@@ -90,12 +90,30 @@ See Gnus' manual for details."
 (cl-defmethod ebdb-popup-window (&context (major-mode mail-mode))
   (list (get-buffer-window) 0.4))
 
+(defun ebdb-message-complete-mail-cleanup (str _buffer pos &optional _)
+  "Call `ebdb-complete-mail-cleanup' after capf completion."
+  (ebdb-complete-mail-cleanup str pos))
+
 (defun ebdb-insinuate-message ()
   ;; We don't currently bind the `ebdb-mua-keymap'.
-  (when ebdb-complete-mail
-    (cl-pushnew 
'("^\\(Resent-\\)?\\(To\\|B?Cc\\|Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):"
 . ebdb-complete-mail)
-               message-completion-alist
-               :test #'equal))
+  (pcase ebdb-complete-mail
+    ('capf (progn (add-hook
+                  'completion-at-point-functions
+                  #'ebdb-mail-dwim-completion-at-point-function nil t)
+                 ;; Kind of hacky way of mimicking
+                 ;; `ebdb-complete-mail' behavior, but for capf.  The
+                 ;; completion-string-functions are supposed to be
+                 ;; buffer local, but don't appear to be.
+                 (set
+                  (make-local-variable
+                   'choose-completion-string-functions)
+                  (push #'ebdb-message-complete-mail-cleanup
+                        choose-completion-string-functions))))
+    ('nil nil)
+    (_
+     (cl-pushnew 
'("^\\(Resent-\\)?\\(To\\|B?Cc\\|Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):"
 . ebdb-complete-mail)
+                message-completion-alist
+                :test #'equal)))
   ;; Other MUAs clear the EBDB buffer before displaying (in
   ;; `ebdb-mua-auto-update', the call to `ebdb-display-records' does
   ;; not pass the "append" flag).  Displaying in message-mode does
@@ -106,8 +124,18 @@ See Gnus' manual for details."
 (defun ebdb-insinuate-mail ()
   "Hook EBDB into Mail Mode."
   ;; We don't currently bind the `ebdb-mua-keymap'.
-  (if ebdb-complete-mail
-      (define-key mail-mode-map "\M-\t" 'ebdb-complete-mail))
+  (pcase ebdb-complete-mail
+    ('capf (progn (add-hook
+                  'completion-at-point-functions
+                  #'ebdb-mail-dwim-completion-at-point-function nil t)
+                 ;; See above.
+                 (set
+                  (make-local-variable
+                   'choose-completion-string-functions)
+                  (push #'ebdb-message-complete-mail-cleanup
+                        choose-completion-string-functions))))
+    ('nil nil)
+    (_ (define-key mail-mode-map "\M-\t" 'ebdb-complete-mail)))
   (ebdb-undisplay-records))
 
 (add-hook 'message-mode-hook 'ebdb-insinuate-message)
diff --git a/ebdb-wl.el b/ebdb-wl.el
index 5c47256..6440f87 100644
--- a/ebdb-wl.el
+++ b/ebdb-wl.el
@@ -42,17 +42,6 @@
   "Options for EBDB's interaction with Wanderlust."
   :group 'ebdb-mua)
 
-;; This rebinds <TAB> in `wl-draft-mode-map' to `ebdb-complete-mail'.
-;; WL has its own completion mechanism that we could hook into, by
-;; setting `wl-address-init-function' to our own function that
-;; populates `wl-address-completion-list', but that would mean that
-;; we're basically duplicating most of the information in the EBDB,
-;; and `ebdb-complete-mail' works fine in `wl-draft-mode'.
-(defcustom ebdb-wl-use-ebdb-completion nil
-  "If non-nil, use EBDB mail completion in WL draft mode."
-  :group 'ebdb-wl
-  :type 'bool)
-
 (cl-defmethod ebdb-mua-message-header ((header string)
                                       &context (major-mode mime-view-mode))
   "Extract a message header in Wanderlust."
@@ -122,7 +111,7 @@ beginning) of the signature separator."
 (defun ebdb-insinuate-wl ()
   "Hook EBDB into Wanderlust."
   (define-key wl-summary-mode-map ";" ebdb-mua-keymap)
-  (when ebdb-wl-use-ebdb-completion
+  (when ebdb-complete-mail
     (define-key wl-draft-mode-map (kbd "TAB") #'ebdb-complete-mail))
   (add-hook 'wl-summary-exit-hook #'ebdb-wl-quit-window))
 
diff --git a/ebdb.el b/ebdb.el
index 1408b4a..465340c 100644
--- a/ebdb.el
+++ b/ebdb.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2016-2018  Free Software Foundation, Inc.
 
-;; Version: 0.6.5
+;; Version: 0.6.6
 ;; Package-Requires: ((emacs "25.1") (cl-lib "0.5") (seq "2.15"))
 
 ;; Maintainer: Eric Abrahamsen <address@hidden>
@@ -96,6 +96,11 @@ You really should not disable debugging.  But it will speed 
things up."))
   "Bind this to t to quiet things down - do not set it.
 See also `ebdb-silent'.")
 
+(defvar ebdb-dwim-completion-cache nil
+  "A list of strings as returned by `ebdb-dwim-mail'.
+As mail field instances are created, a \"dwim\"-style string is
+added here, for use in `completion-at-point' in mail buffers.")
+
 ;; Custom groups
 
 (defgroup ebdb-eieio nil
@@ -646,9 +651,15 @@ name in mail address when same as mail."
                  (const :tag "Avoid redundancy" t)))
 
 (defcustom ebdb-complete-mail t
-  "If t MUA insinuation provides key binding for command `ebdb-complete-mail'."
+  "If non-nil composition MUAs will complete EBDB contacts.
+Completion takes place within mail headers that specify one or
+more message recipients.  A value of `capf' will add an EBDB
+collection to `completion-at-point-functions'.  Any other non-nil
+value will override \"TAB\" to call `ebdb-complete-mail'."
   :group 'ebdb-sendmail
-  :type 'boolean)
+  :type '(choice (const :tag "Use `ebdb-complete-mail'" t)
+                (const :tag "Do not complete mail addresses" nil)
+                (const :tag "Use completion at point" capf)))
 
 (defcustom ebdb-completion-list t
   "Controls the behaviour of function `ebdb-complete-mail'.
@@ -672,21 +683,28 @@ If nil, no completion is offered."
                                  (const primary)
                                  (const mail)))))
 
-(defcustom ebdb-complete-mail-allow-cycling nil
-  "If non-nil cycle mail addresses when calling function `ebdb-complete-mail'."
+(defcustom ebdb-complete-mail-allow-cycling 5
+  "If non-nil, cycle mail addresses when completing mails.
+If `ebdb-complete-mail' is set to `capf', this option can be set
+to an integer number, specifying that completion should take
+place when there are that many completion candidates or fewer.
+Otherwise, cycling will take place among all a single contact's
+email addresses."
   :group 'ebdb-sendmail
-  :type 'boolean)
+  :type '(choice (const :tag "Never cycle" nil)
+                (const :tag "Always cycle" t)
+                (number :tag "Cycle for this many candidates or fewer")))
 
 (defcustom ebdb-complete-mail-hook nil
-  "List of functions called after a sucessful completion."
+  "List of functions called after a successful completion."
   :group 'ebdb-sendmail
   :type 'hook)
 
 (defcustom ebdb-mail-abbrev-expand-hook nil
   ;; Replacement for function `mail-abbrev-expand-hook'.
   "Function (not hook) run each time an alias is expanded.
-The function is called with two args the alias and the list
-of corresponding mail addresses."
+The function is called with two args: the alias and the list of
+corresponding mail addresses."
   :group 'ebdb-sendmail
   :type 'function)
 
@@ -1483,6 +1501,8 @@ first one."
   (with-slots (aka mail) field
     (ebdb-puthash mail record)
     (object-add-to-list (ebdb-record-cache record) 'mail-canon mail)
+    (cl-pushnew (ebdb-dwim-mail record field) ebdb-dwim-completion-cache
+               :test #'equal)
     (when aka
       (ebdb-puthash aka record)
       (object-add-to-list (ebdb-record-cache record) 'mail-aka aka))))
@@ -1492,6 +1512,8 @@ first one."
     (when aka
       (ebdb-remhash aka record)
       (object-remove-from-list (ebdb-record-cache record) 'mail-aka aka))
+    (setq ebdb-dwim-completion-cache (delete (ebdb-dwim-mail record field)
+                                            ebdb-dwim-completion-cache))
     (ebdb-remhash mail record)
     (object-remove-from-list (ebdb-record-cache record) 'mail-canon mail))
   (cl-call-next-method))
@@ -4297,6 +4319,8 @@ addresses."
 
 
 
+;;; Mail and completion stuff.
+
 (defun ebdb-dwim-mail (record &optional mail)
   ;; Do What I Mean!
   "Return a string to use as the mail address of RECORD.
@@ -4341,6 +4365,40 @@ to use."
                  name mail))
       mail)))
 
+(defun ebdb-mail-dwim-completion-at-point-function ()
+  "Complete text at point as a mail \"dwim\" string.
+The completed strings are of the form \"Firstname Lastname
+<address@hidden>\".  For use in `completion-at-point-functions'
+in `message-mode' or `mail-mode'.
+
+Also see the variable `ebdb-ignore-redundant-mails'."
+  (when (let ((mail-abbrev-mode-regexp
+              
"^\\(Resent-\\)?\\(To\\|B?Cc\\|Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):"))
+          (mail-abbrev-in-expansion-header-p))
+    (let* ((start
+           (save-excursion
+             ;; Headers can be multi-line, but if we've wrapped there
+             ;; should always be something on the current line.
+             (re-search-backward ",[[:blank:]]?\\|:[[:blank:]]?"
+                                 (line-beginning-position) t)
+             (match-end 0)))
+          (end (save-excursion
+                 (goto-char (line-end-position))
+                 (max start (point)))))
+      (list start end #'ebdb-mail-dwim-collection-function
+           (list :exclusive 'no)))))
+
+(defun ebdb-mail-dwim-collection-function (str pred action)
+  "Function that pretends to be a completion table."
+  (let ((completion-ignore-case t))
+    (if (eq action 'metadata)
+       '(metadata . ((category . ebdb-contact)))
+      (complete-with-action action ebdb-dwim-completion-cache str pred))))
+
+(add-to-list 'completion-category-defaults
+            `(ebdb-contact (styles substring basic)
+                           (cycle . ,ebdb-complete-mail-allow-cycling)))
+
 
 ;;; Dialing and texting.
 
diff --git a/ebdb.info b/ebdb.info
index 59cc362..f34506e 100644
--- a/ebdb.info
+++ b/ebdb.info
@@ -12,6 +12,7 @@ Copyright © 2016 Free Software Foundation, Inc.
 
      (a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
      modify this GNU manual.”
+
 INFO-DIR-SECTION Emacs
 START-INFO-DIR-ENTRY
 * EBDB: (ebdb).         Contact management package.
@@ -80,6 +81,7 @@ MUA Interaction
 * Loading MUA Code::
 * Display and Updating::
 * EBDB and MUA summary buffers::
+* Mail Address Completion::
 
 Display and Updating
 
@@ -95,6 +97,11 @@ EBDB and MUA summary buffers
 * Summary buffer marks::
 
 
+Mail Address Completion
+
+* A Note on Completion::
+
+
 Specific MUAs
 
 * Gnus::
@@ -181,8 +188,8 @@ variable should point to your current BBDB file; 
alternately EBDB will
 look in the default location, found using ‘(locate-user-emacs-file
 "bbdb" ".bbdb)’.  Then set ‘ebdb-sources’ to a non-existent file name,
 and then run ‘ebdb-load’ (or any of the other EBDB entry commands).
-You’ll be prompted to create the new database, and upgrade from BBDB. If
-any records could not be upgraded, they will be displayed in an *EBDB
+You’ll be prompted to create the new database, and upgrade from BBDB.
+If any records could not be upgraded, they will be displayed in an *EBDB
 Migration Errors* buffer.  Migration bug reports are very welcome.
 
    You can also call the command ‘ebdb-migrate-from-bbdb’ at any time.
@@ -194,7 +201,7 @@ File: ebdb.info,  Node: Variables and Options,  Prev: 
Record Migration,  Up: Mig
 ---------------------------
 
 Many of the old BBDB customization options have been changed or removed
-entirely in EBDB. It’s probably best to put your BBDB customizations
+entirely in EBDB.  It’s probably best to put your BBDB customizations
 aside, and set new EBDB options as you come across them.  The most
 important options are detailed in this manual, you can also customize
 the “EBDB” group to see what’s available.
@@ -432,10 +439,10 @@ File: ebdb.info,  Node: Field Types,  Prev: Deleting 
Records and Fields,  Up: Re
 Fields can be classed in a few different categories.  Some are
 “plumbing” fields, that are present for all records, but not generally
 visible or user-editable: these include the creation date, timestamp,
-and UUID. You can view these fields by hitting ‘T’ on the record.  Other
-fields are “built-in”: basic fields that get special treatment.  These
-include the name, mail, phone, address, and notes fields.  EBDB comes
-with default classes for these fields: if you would like to use
+and UUID.  You can view these fields by hitting ‘T’ on the record.
+Other fields are “built-in”: basic fields that get special treatment.
+These include the name, mail, phone, address, and notes fields.  EBDB
+comes with default classes for these fields: if you would like to use
 different defaults, you can create new classes (inheriting from the
 existing ones) and use those instead.  See *note Hacking EBDB:: for more
 information.
@@ -553,6 +560,7 @@ emails.
 * Loading MUA Code::
 * Display and Updating::
 * EBDB and MUA summary buffers::
+* Mail Address Completion::
 
 
 File: ebdb.info,  Node: Loading MUA Code,  Next: Display and Updating,  Up: 
MUA Interaction
@@ -781,7 +789,7 @@ binding, and only specifies the further binding.  Ie, press 
“;:” to call
      Only display recipients, using all mail addresses from the message.
 
 
-File: ebdb.info,  Node: EBDB and MUA summary buffers,  Prev: Display and 
Updating,  Up: MUA Interaction
+File: ebdb.info,  Node: EBDB and MUA summary buffers,  Next: Mail Address 
Completion,  Prev: Display and Updating,  Up: MUA Interaction
 
 5.3 EBDB and MUA summary buffers
 ================================
@@ -856,6 +864,76 @@ string provided by Gnus, and adding the EBDB-specific 
format code:
      record.  Defaults to “e”.
 
 
+File: ebdb.info,  Node: Mail Address Completion,  Prev: EBDB and MUA summary 
buffers,  Up: MUA Interaction
+
+5.4 Mail Address Completion
+===========================
+
+Emacs’ two message-composition modes are ‘message-mode’ and ‘mail-mode’,
+the former having somewhat obsoleted the latter – EBDB supports both.
+
+   The main use of EBDB in message composition is to complete email
+addresses of contacts, obviously.  The following options govern this
+behavior:
+
+ -- User Option: ebdb-complete-mail
+     If non-nil, EBDB will provide mail completion in mail composition
+     buffers.  If it is the symbol ‘capf’, EBDB will add it’s own
+     completion function to the local value of
+     ‘completion-at-point-functions’.  Otherwise, it will clobber the
+     existing binding of ‘<TAB>’ and replace it with the function
+     ‘ebdb-complete-mail’.  (Technically, in ‘message-mode’, it will
+     ensure this function is called instead of ‘message-expand-name’.)
+
+ -- User Option: ebdb-mail-avoid-redundancy
+     If nil, mail completion will always insert a full “First Last
+     <address@hidden>” string, even when the contact’s name is
+     deemed to be redundant with the email address itself.  If set to
+     the symbol ‘mail-only’, the name will never be inserted.  If any
+     other non-nil value, the name will be elided if it appears to be
+     redundant.
+
+ -- User Option: ebdb-complete-mail-allow-cycling
+     If non-nil, cycle mail addresses when completing mails.  The exact
+     behavior of this setting depends a bit on the value of
+     ‘ebdb-complete-mail’.  If completion at point is being used, this
+     can be set to an integer N, specifying that cycling may take place
+     if there are N or fewer candidate completion strings.  If the
+     function ‘ebdb-complete-mail’ is being used, a non-nil value will
+     allow cycling among all of a single contact’s mail addresses, once
+     the contact itself has been selected.
+
+ -- User Option: ebdb-completion-display-record
+     If non-nil, display each newly-completed record in a pop-up *EBDB*
+     buffer.
+
+ -- User Option: ebdb-complete-mail-hook
+     A hook run after a successful completion.
+
+ -- User Option: ebdb-mail-abbrev-expand-hook
+     A single function called each time an alias is expanded in a
+     composition buffer.  The function is called with two arguments: the
+     alias name, and the list of corresponding mail addresses.
+
+* Menu:
+
+* A Note on Completion::
+
+
+File: ebdb.info,  Node: A Note on Completion,  Up: Mail Address Completion
+
+5.4.1 A Note on Completion
+--------------------------
+
+As mentioned above, EBDB completion can be done either using the
+completion at point framework, or its own ‘ebdb-complete-mail’ function.
+The two don’t behave exactly the same, however: completion at point
+works from a pre-constructed list of strings, while ‘ebdb-complete-mail’
+conducts an actual search of the database.  This means that the former
+is faster, but the latter will find more records, particularly if search
+options like ‘ebdb-case-fold-search’ are in effect.
+
+
 File: ebdb.info,  Node: Specific MUAs,  Next: EBDB Buffers,  Prev: MUA 
Interaction,  Up: Top
 
 6 Specific MUAs
@@ -1308,25 +1386,18 @@ File: ebdb.info,  Node: Completion,  Next: Snarfing,  
Prev: EBDB Buffers,  Up: T
 8 Completion
 ************
 
-There are many Emacs completion frameworks out there, and libraries
-exist providing EBDB support for helm, counsel, and company.  These
-libraries must be loaded from the package repositories, and provide the
-commands ‘helm-ebdb’, ‘counsel-ebdb’, and ‘company-ebdb’, respectively.
-Counsel and company are made to be hooked into Emacs’ existing
-completion frameworks; the helm command must be called explicitly.
+There are many Emacs completion frameworks out there, and EBDB provides
+custom commands for a few of them: ‘ebdb-helm’, ‘ebdb-counsel’, and
+‘ebdb-company’.  Counsel and company are made to be hooked into Emacs’
+existing completion frameworks; the helm command must be called
+explicitly.  For information about completion in mail composition
+buffers, see *note Mail Address Completion::.
 
    Another built-in library, ‘ebdb-complete’, uses an ephemeral pop-up
 *EBDB* buffer for record completion.  The command ‘ebdb-complete’
 provides an interactive entry point, or you can enable it for ‘<TAB>’ in
 ‘message-mode’ by calling ‘ebdb-complete-enable’.
 
-   Several native EBDB commands involve choosing a record, or multiple
-records.  At present, the completion interface for these commands is a
-bit random: several of the commands simply use ‘completing-read’
-directly, which isn’t right.  At some point, all EBDB commands that ask
-the user to select a record will become aware of the currently-loaded
-completion frameworks.
-
 
 File: ebdb.info,  Node: Snarfing,  Next: Internationalization,  Prev: 
Completion,  Up: Top
 
@@ -1604,7 +1675,7 @@ File: ebdb.info,  Node: Field Classes,  Next: Writing 
Internationalization Libra
 16.1 Field Classes
 ==================
 
-It’s fairly easy to create your own custom field classes in EBDB. All
+It’s fairly easy to create your own custom field classes in EBDB.  All
 such fields should subclass the ‘ebdb-field-user’ class, which sets up
 basic behavior.  That base class provides for no slots at all, so your
 class must define the slots where the field data will be held.  It
@@ -2047,7 +2118,7 @@ separate functions:
  -- Method: ebdb-make-buffer-name
      Called with no arguments but the mode specializer, this function
      should return the string name of the *EBDB* buffer to be associated
-     with this MUA. Usually the function body will look like: ‘(format
+     with this MUA.  Usually the function body will look like: ‘(format
      "*%s-<mua>" ebdb-buffer-name)’.
 
  -- Method: ebdb-popup-window
@@ -2087,8 +2158,8 @@ any).  This is done with two generic functions:
 
 File: ebdb.info,  Node: Index,  Prev: Hacking EBDB,  Up: Top
 
-Index
-*****
+17 Index
+********
 
 [index]
 * Menu:
@@ -2173,6 +2244,14 @@ Index
 * ebdb-cite-records-ebdb:                The Basics of ebdb-mode.
                                                               (line  89)
 * ebdb-clone-buffer:                     EBDB Buffers.        (line  19)
+* ebdb-complete-mail:                    Mail Address Completion.
+                                                              (line  13)
+* ebdb-complete-mail-allow-cycling:      Mail Address Completion.
+                                                              (line  30)
+* ebdb-complete-mail-hook:               Mail Address Completion.
+                                                              (line  44)
+* ebdb-completion-display-record:        Mail Address Completion.
+                                                              (line  40)
 * ebdb-copy-fields-as-kill:              The Basics of ebdb-mode.
                                                               (line  96)
 * ebdb-copy-mail-as-kill:                The Basics of ebdb-mode.
@@ -2258,6 +2337,10 @@ Index
                                                               (line  24)
 * ebdb-mail:                             The Basics of ebdb-mode.
                                                               (line  56)
+* ebdb-mail-abbrev-expand-hook:          Mail Address Completion.
+                                                              (line  47)
+* ebdb-mail-avoid-redundancy:            Mail Address Completion.
+                                                              (line  22)
 * ebdb-mail-each:                        The Basics of ebdb-mode.
                                                               (line  61)
 * ebdb-make-buffer-name:                 Writing Integration For New MUAs.
@@ -2432,65 +2515,67 @@ Index
 
 
 Tag Table:
-Node: Top806
-Node: Getting Started2526
-Node: Migration from BBDB3181
-Node: Record Migration3392
-Node: Variables and Options4195
-Node: Migration from Org Contacts4681
-Node: The EBDB Database5441
-Node: Creating Records9429
-Node: Record classes10510
-Node: Record names10855
-Node: Record Fields11530
-Node: Inserting New Fields11774
-Node: Editing Existing Fields12570
-Node: Deleting Records and Fields13170
-Node: Field Types13566
-Node: Role fields15853
-Node: Tag field17541
-Node: Mail folder field18185
-Node: MUA Interaction18513
-Node: Loading MUA Code19038
-Node: Display and Updating19751
-Node: Pop-up Buffers20517
-Node: Auto-Updating Records22100
-Node: Noticing and Automatic Rules24500
-Node: Interactive Commands25833
-Node: EBDB and MUA summary buffers28308
-Node: Sender name display28794
-Node: Summary buffer marks30021
-Node: Specific MUAs31200
-Node: Gnus31348
-Node: Posting Styles31570
-Node: EBDB Buffers33145
-Node: Searching34356
-Node: Changing Search Behavior36018
-Node: The Basics of ebdb-mode37265
-Node: Customizing Record Display41574
-Node: Marking45894
-Node: Exporting/Formatting46321
-Node: Completion47270
-Node: Snarfing48468
-Node: Internationalization50485
-Node: Diary Integration53186
-Node: Mail Aliases54051
-Node: vCard Support54765
-Node: Org Integration55264
-Node: Citing Records57162
-Node: Hacking EBDB57920
-Node: Field Classes60237
-Node: Init and Delete Methods63372
-Node: The Labeled Field Class64879
-Node: The Singleton Field Class65733
-Node: Actions66171
-Node: Custom Field Searching66843
-Node: Fast Lookups69710
-Node: Formatting in the EBDB Buffer71520
-Node: Writing Internationalization Libraries73596
-Node: Writing Integration For New MUAs78010
-Node: Article snarfing81457
-Node: Index82175
+Node: Top807
+Node: Getting Started2607
+Node: Migration from BBDB3262
+Node: Record Migration3473
+Node: Variables and Options4276
+Node: Migration from Org Contacts4763
+Node: The EBDB Database5523
+Node: Creating Records9511
+Node: Record classes10592
+Node: Record names10937
+Node: Record Fields11612
+Node: Inserting New Fields11856
+Node: Editing Existing Fields12652
+Node: Deleting Records and Fields13252
+Node: Field Types13648
+Node: Role fields15934
+Node: Tag field17622
+Node: Mail folder field18266
+Node: MUA Interaction18594
+Node: Loading MUA Code19147
+Node: Display and Updating19860
+Node: Pop-up Buffers20626
+Node: Auto-Updating Records22209
+Node: Noticing and Automatic Rules24609
+Node: Interactive Commands25942
+Node: EBDB and MUA summary buffers28417
+Node: Sender name display28935
+Node: Summary buffer marks30162
+Node: Mail Address Completion31341
+Node: A Note on Completion33850
+Node: Specific MUAs34473
+Node: Gnus34621
+Node: Posting Styles34843
+Node: EBDB Buffers36418
+Node: Searching37629
+Node: Changing Search Behavior39291
+Node: The Basics of ebdb-mode40538
+Node: Customizing Record Display44847
+Node: Marking49167
+Node: Exporting/Formatting49594
+Node: Completion50543
+Node: Snarfing51339
+Node: Internationalization53356
+Node: Diary Integration56057
+Node: Mail Aliases56922
+Node: vCard Support57636
+Node: Org Integration58135
+Node: Citing Records60033
+Node: Hacking EBDB60791
+Node: Field Classes63108
+Node: Init and Delete Methods66244
+Node: The Labeled Field Class67751
+Node: The Singleton Field Class68605
+Node: Actions69043
+Node: Custom Field Searching69715
+Node: Fast Lookups72582
+Node: Formatting in the EBDB Buffer74392
+Node: Writing Internationalization Libraries76468
+Node: Writing Integration For New MUAs80882
+Node: Article snarfing84330
+Node: Index85048
 
 End Tag Table
 
diff --git a/ebdb.org b/ebdb.org
index 3212a7a..ec0ff9f 100644
--- a/ebdb.org
+++ b/ebdb.org
@@ -634,7 +634,6 @@ Only display the recipients.
 #+begin_deffn
 Only display recipients, using all mail addresses from the message.
 #+end_deffn
-
 ** EBDB and MUA summary buffers
 
 EBDB can affect the way message senders are displayed in your MUA's
@@ -703,6 +702,78 @@ string provided by Gnus, and adding the EBDB-specific 
format code:
 Format letter to use in the summary buffer format string to mark a
 record.  Defaults to "e".
 #+END_defopt
+** Mail Address Completion
+:PROPERTIES:
+:ID:       f035aefc-53b1-4d05-b980-8ae0ac851275
+:END:
+Emacs' two message-composition modes are ~message-mode~ and
+~mail-mode~, the former having somewhat obsoleted the latter -- EBDB
+supports both.
+
+The main use of EBDB in message composition is to complete email
+addresses of contacts, obviously.  The following options govern this
+behavior:
+
+#+ATTR_TEXINFO: :options ebdb-complete-mail
+#+BEGIN_defopt
+If non-nil, EBDB will provide mail completion in mail composition
+buffers.  If it is the symbol ~capf~, EBDB will add it's own
+completion function to the local value of
+~completion-at-point-functions~.  Otherwise, it will clobber the
+existing binding of {{{kbd(@key{TAB})}}} and replace it with the
+function ~ebdb-complete-mail~.  (Technically, in ~message-mode~, it
+will ensure this function is called instead of ~message-expand-name~.)
+#+END_defopt
+
+#+ATTR_TEXINFO: :options ebdb-mail-avoid-redundancy
+#+BEGIN_defopt
+If nil, mail completion will always insert a full "First Last
+<address@hidden>" string, even when the contact's name is
+deemed to be redundant with the email address itself.  If set to the
+symbol ~mail-only~, the name will never be inserted.  If any other
+non-nil value, the name will be elided if it appears to be redundant.
+#+END_defopt
+
+#+ATTR_TEXINFO: :options ebdb-complete-mail-allow-cycling
+#+BEGIN_defopt
+If non-nil, cycle mail addresses when completing mails.  The exact
+behavior of this setting depends a bit on the value of
+~ebdb-complete-mail~.  If completion at point is being used, this can
+be set to an integer N, specifying that cycling may take place if
+there are N or fewer candidate completion strings.  If the function
+~ebdb-complete-mail~ is being used, a non-nil value will allow cycling
+among all of a single contact's mail addresses, once the contact
+itself has been selected.
+#+END_defopt
+
+#+ATTR_TEXINFO: :options ebdb-completion-display-record
+#+BEGIN_defopt
+If non-nil, display each newly-completed record in a pop-up
+{{{buf(EBDB)}}} buffer.
+#+END_defopt
+
+#+ATTR_TEXINFO: :options ebdb-complete-mail-hook
+#+BEGIN_defopt
+A hook run after a successful completion.
+#+END_defopt
+
+#+ATTR_TEXINFO: :options ebdb-mail-abbrev-expand-hook
+#+BEGIN_defopt
+A single function called each time an alias is expanded in a
+composition buffer.  The function is called with two arguments: the
+alias name, and the list of corresponding mail addresses.
+#+END_defopt
+
+*** A Note on Completion
+As mentioned above, EBDB completion can be done either using the
+completion at point framework, or its own ~ebdb-complete-mail~
+function.  The two don't behave exactly the same, however: completion
+at point works from a pre-constructed list of strings, while
+~ebdb-complete-mail~ conducts an actual search of the database.  This
+means that the former is faster, but the latter will find more
+records, particularly if search options like ~ebdb-case-fold-search~
+are in effect.
+
 * Specific MUAs
 ** Gnus
 EBDB has a little more support for Gnus than the other MUAs, for no
@@ -741,7 +812,6 @@ A current limitation of this functionality is that it only 
works when
 composing a mail to a single recipient.  If you mark several records
 in a {{{buf(EBDB)}}} buffer and compose a mail to them collectively,
 the mechanism will be bypassed.
-
 * EBDB Buffers
 :PROPERTIES:
 :ID:       877ca77a-06d6-4fbf-87ec-614d03c37e30
@@ -1220,13 +1290,12 @@ imperfect: not all fields can be exported correctly.  
VCard version
 
 It's possible to write new formatters, documentation is forthcoming.
 * Completion
-There are many Emacs completion frameworks out there, and libraries
-exist providing EBDB support for helm, counsel, and company.  These
-libraries must be loaded from the package repositories, and provide
-the commands ~helm-ebdb~, ~counsel-ebdb~, and ~company-ebdb~,
-respectively.  Counsel and company are made to be hooked into Emacs'
-existing completion frameworks; the helm command must be called
-explicitly.
+There are many Emacs completion frameworks out there, and EBDB
+provides custom commands for a few of them: ~ebdb-helm~,
+~ebdb-counsel~, and ~ebdb-company~.  Counsel and company are made to
+be hooked into Emacs' existing completion frameworks; the helm command
+must be called explicitly.  For information about completion in mail
+composition buffers, see [[id:f035aefc-53b1-4d05-b980-8ae0ac851275][Mail 
Address Completion]].
 
 Another built-in library,
 @@texinfo:@file{@@ebdb-complete@@texinfo:}@@, uses an ephemeral pop-up
@@ -1235,12 +1304,6 @@ Another built-in library,
 it for {{{kbd(@key{TAB})}}} in ~message-mode~ by calling
 ~ebdb-complete-enable~.
 
-Several native EBDB commands involve choosing a record, or multiple
-records.  At present, the completion interface for these commands is a
-bit random: several of the commands simply use ~completing-read~
-directly, which isn't right.  At some point, all EBDB commands that
-ask the user to select a record will become aware of the
-currently-loaded completion frameworks.
 * Snarfing
 #+CINDEX: Snarfing text
 "Snarfing" refers to scanning free-form text and extracting
diff --git a/ebdb.texi b/ebdb.texi
index 7f08154..8104981 100644
--- a/ebdb.texi
+++ b/ebdb.texi
@@ -22,6 +22,7 @@ is included in the section entitled “GNU Free Documentation 
License.”
 
 (a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
 modify this GNU manual.”
+
 @end quotation
 @end copying
 
@@ -103,6 +104,7 @@ MUA Interaction
 * Loading MUA Code::
 * Display and Updating::
 * EBDB and MUA summary buffers::
+* Mail Address Completion::
 
 Display and Updating
 
@@ -118,6 +120,11 @@ EBDB and MUA summary buffers
 * Summary buffer marks::
 
 
+Mail Address Completion
+
+* A Note on Completion::
+
+
 Specific MUAs
 
 * Gnus::
@@ -200,7 +207,7 @@ alternately EBDB will look in the default location, found 
using
 @code{(locate-user-emacs-file "bbdb" ".bbdb)}.  Then set @code{ebdb-sources} to
 a non-existent file name, and then run @code{ebdb-load} (or any of the
 other EBDB entry commands).  You'll be prompted to create the new
-database, and upgrade from BBDB.  If any records could not be
+database, and upgrade from address@hidden  If any records could not be
 upgraded, they will be displayed in an *EBDB Migration Errors*
 buffer.  Migration bug reports are very welcome.
 
@@ -211,7 +218,7 @@ You can also call the command @code{ebdb-migrate-from-bbdb} 
at any time.
 @subsection Variables and Options
 
 Many of the old BBDB customization options have been changed or
-removed entirely in EBDB.  It's probably best to put your BBDB
+removed entirely in address@hidden  It's probably best to put your BBDB
 customizations aside, and set new EBDB options as you come across
 them.  The most important options are detailed in this manual, you can
 also customize the ``EBDB'' group to see what's available.
@@ -469,7 +476,7 @@ a record's main name will instead prompt to delete the 
whole record.
 Fields can be classed in a few different categories.  Some are
 ``plumbing'' fields, that are present for all records, but not generally
 visible or user-editable: these include the creation date, timestamp,
-and UUID.  You can view these fields by hitting @kbd{T} on the
+and address@hidden  You can view these fields by hitting @kbd{T} on the
 record.  Other fields are ``built-in'': basic fields that get special
 treatment.  These include the name, mail, phone, address, and notes
 fields.  EBDB comes with default classes for these fields: if you
@@ -578,6 +585,7 @@ and receiving emails.
 * Loading MUA Code::
 * Display and Updating::
 * EBDB and MUA summary buffers::
+* Mail Address Completion::
 @end menu
 
 @node Loading MUA Code
@@ -611,7 +619,7 @@ the records referenced in that message. It can:
 Pop up a buffer displaying the records.
 @item
 Create new records, or alter existing records, based on information
-provided by the MUA.
+provided by the address@hidden
 @item
 Run automatic rules to edit the records.
 @item
@@ -903,6 +911,77 @@ Format letter to use in the summary buffer format string 
to mark a
 record.  Defaults to ``e''.
 @end defopt
 
address@hidden Mail Address Completion
address@hidden Mail Address Completion
+
+Emacs' two message-composition modes are @code{message-mode} and
address@hidden, the former having somewhat obsoleted the latter -- EBDB
+supports both.
+
+The main use of EBDB in message composition is to complete email
+addresses of contacts, obviously.  The following options govern this
+behavior:
+
address@hidden ebdb-complete-mail
+If non-nil, EBDB will provide mail completion in mail composition
+buffers.  If it is the symbol @code{capf}, EBDB will add it's own
+completion function to the local value of
address@hidden  Otherwise, it will clobber the
+existing binding of @address@hidden and replace it with the
+function @code{ebdb-complete-mail}.  (Technically, in @code{message-mode}, it
+will ensure this function is called instead of @code{message-expand-name}.)
address@hidden defopt
+
address@hidden ebdb-mail-avoid-redundancy
+If nil, mail completion will always insert a full ``First Last
+<first.last@@example.com>'' string, even when the contact's name is
+deemed to be redundant with the email address itself.  If set to the
+symbol @code{mail-only}, the name will never be inserted.  If any other
+non-nil value, the name will be elided if it appears to be redundant.
address@hidden defopt
+
address@hidden ebdb-complete-mail-allow-cycling
+If non-nil, cycle mail addresses when completing mails.  The exact
+behavior of this setting depends a bit on the value of
address@hidden  If completion at point is being used, this can
+be set to an integer N, specifying that cycling may take place if
+there are N or fewer candidate completion strings.  If the function
address@hidden is being used, a non-nil value will allow cycling
+among all of a single contact's mail addresses, once the contact
+itself has been selected.
address@hidden defopt
+
address@hidden ebdb-completion-display-record
+If non-nil, display each newly-completed record in a pop-up
+*EBDB* buffer.
address@hidden defopt
+
address@hidden ebdb-complete-mail-hook
+A hook run after a successful completion.
address@hidden defopt
+
address@hidden ebdb-mail-abbrev-expand-hook
+A single function called each time an alias is expanded in a
+composition buffer.  The function is called with two arguments: the
+alias name, and the list of corresponding mail addresses.
address@hidden defopt
+
address@hidden
+* A Note on Completion::
address@hidden menu
+
address@hidden A Note on Completion
address@hidden A Note on Completion
+
+As mentioned above, EBDB completion can be done either using the
+completion at point framework, or its own @code{ebdb-complete-mail}
+function.  The two don't behave exactly the same, however: completion
+at point works from a pre-constructed list of strings, while
address@hidden conducts an actual search of the database.  This
+means that the former is faster, but the latter will find more
+records, particularly if search options like @code{ebdb-case-fold-search}
+are in effect.
+
 @node Specific MUAs
 @chapter Specific MUAs
 
@@ -1444,13 +1523,12 @@ It's possible to write new formatters, documentation is 
forthcoming.
 @node Completion
 @chapter Completion
 
-There are many Emacs completion frameworks out there, and libraries
-exist providing EBDB support for helm, counsel, and company.  These
-libraries must be loaded from the package repositories, and provide
-the commands @code{helm-ebdb}, @code{counsel-ebdb}, and @code{company-ebdb},
-respectively.  Counsel and company are made to be hooked into Emacs'
-existing completion frameworks; the helm command must be called
-explicitly.
+There are many Emacs completion frameworks out there, and EBDB
+provides custom commands for a few of them: @code{ebdb-helm},
address@hidden, and @code{ebdb-company}.  Counsel and company are made to
+be hooked into Emacs' existing completion frameworks; the helm command
+must be called explicitly.  For information about completion in mail
+composition buffers, see @ref{Mail Address Completion}.
 
 Another built-in library,
 @file{ebdb-complete}, uses an ephemeral pop-up
@@ -1459,13 +1537,6 @@ Another built-in library,
 it for @address@hidden in @code{message-mode} by calling
 @code{ebdb-complete-enable}.
 
-Several native EBDB commands involve choosing a record, or multiple
-records.  At present, the completion interface for these commands is a
-bit random: several of the commands simply use @code{completing-read}
-directly, which isn't right.  At some point, all EBDB commands that
-ask the user to select a record will become aware of the
-currently-loaded completion frameworks.
-
 @node Snarfing
 @chapter Snarfing
 
@@ -1487,7 +1558,7 @@ the region is active, this command snarfs the current 
region,
 otherwise it snarfs the entire current buffer.  Called as a function,
 it can accept a string as the first argument and snarfs that.  The
 RECS argument, which cannot be passed interactively, is a list of
-records that are assumed to be related to snarfable data in STRING.
+records that are assumed to be related to snarfable data in address@hidden
 @end deffn
 
 @defopt ebdb-snarf-routines
@@ -1536,7 +1607,7 @@ There is currently only one country library written for 
EBDB,
 fields.  It parses and displays phone numbers and names correctly, and
 also allows users to search on Chinese names using pinyin.  It can be
 installed from ELPA, and requires the @code{pyim} package, available on
-MELPA.
address@hidden
 
 The present dearth of libraries is a result of the author scratching
 his own itch.  Contributions of new libraries are very welcome (see
@@ -1745,7 +1816,7 @@ existing objects.  This may be addressed in the future.
 @node Field Classes
 @section Field Classes
 
-It's fairly easy to create your own custom field classes in EBDB.  All
+It's fairly easy to create your own custom field classes in address@hidden  All
 such fields should subclass the @code{ebdb-field-user} class, which sets up
 basic behavior.  That base class provides for no slots at all, so your
 class must define the slots where the field data will be held.  It
@@ -2217,7 +2288,7 @@ two separate functions:
 @deffn Method ebdb-make-buffer-name
 Called with no arguments but the mode specializer, this function
 should return the string name of the *EBDB* buffer to be
-associated with this MUA.  Usually the function body will look like:
+associated with this address@hidden  Usually the function body will look like:
 @code{(format "*%s-<mua>" ebdb-buffer-name)}.
 @end deffn
 
@@ -2259,7 +2330,7 @@ Return the text of the article signature, or nil.
 @end deffn
 
 @node Index
address@hidden Index
address@hidden Index
 
 @printindex cp
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]