[PATCH v1 3/3] emacs: Add an address completer in elisp.

David Edmondson dme at dme.org
Fri Sep 5 05:59:29 PDT 2014


Rather than relying on an external comment to provide address
completion in composition mode, provide a solution purely in elisp.

Update `notmuch-address-command' to allow it to specify an external
command or a function, with the default remaining as an external
command called "notmuch-addresses".
---
 emacs/notmuch-address.el | 49 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el
index fa65cd5..449fa54 100644
--- a/emacs/notmuch-address.el
+++ b/emacs/notmuch-address.el
@@ -24,10 +24,17 @@
 ;;
 
 (defcustom notmuch-address-command "notmuch-addresses"
-  "The command which generates possible addresses. It must take a
-single argument and output a list of possible matches, one per
-line."
-  :type 'string
+  "Command or function which generates possible addresses.
+
+A command must take a single argument and output a list of
+possible matches, one per line.
+
+A function must take a single argument and return a list of
+possible matches."
+  :type '(choice (string :tag "External command")
+		 (function :tag "Standard function"
+			   :value notmuch-address-option-generator)
+		 (function :tag "Custom function"))
   :group 'notmuch-send
   :group 'notmuch-external)
 
@@ -42,6 +49,32 @@ to know how address selection is made by default."
   :group 'notmuch-send
   :group 'notmuch-external)
 
+(defun notmuch-address-extractor (message)
+  "Return a list of addresses mentioned in `message'."
+  (let* ((headers (plist-get message :headers))
+	 (from (plist-get headers :From)))
+    from))
+
+(defun notmuch-address-option-generator (initial)
+  "Generate a set of possible address completions for `initial'."
+  (let* ((my-addresses (notmuch-user-all-email))
+	 (query (list (format "(%s) AND from:%s*"
+			      (mapconcat (lambda (a) (concat "to:" a))
+					 my-addresses " OR ")
+			      initial)))
+	 bare-results
+	 results)
+    (dolist (address
+	     (notmuch-query-map-threads 'notmuch-address-extractor
+					(notmuch-query-get-threads query t t)))
+      (when address
+	(let ((bare-address (cadr (std11-extract-address-components address))))
+	  (unless (or (member bare-address my-addresses)
+		      (member bare-address bare-results))
+	    (push bare-address bare-results)
+	    (push address results)))))
+    results))
+
 (defun notmuch-address-selection-function (prompt collection initial-input)
   "Call (`completing-read'
       PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)"
@@ -60,7 +93,13 @@ to know how address selection is made by default."
 	  (push notmuch-address-message-alist-member message-completion-alist))))
 
 (defun notmuch-address-options (original)
-  (process-lines notmuch-address-command original))
+  (cond
+   ((stringp notmuch-address-command)
+    (process-lines notmuch-address-command original))
+   ((functionp notmuch-address-command)
+    (funcall notmuch-address-command original))
+   (t
+    (error "No address completion mechanism defined."))))
 
 (defun notmuch-address-expand-name ()
   (let* ((end (point))
-- 
1.8.5.2 (Apple Git-48)



More information about the notmuch mailing list