1 ;; notmuch-address.el --- address completion with notmuch
3 ;; Copyright © David Edmondson
5 ;; This file is part of Notmuch.
7 ;; Notmuch is free software: you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; Notmuch is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with Notmuch. If not, see <http://www.gnu.org/licenses/>.
20 ;; Authors: David Edmondson <dme@dme.org>
26 (defcustom notmuch-address-command "notmuch-addresses"
27 "The command which generates possible addresses. It must take a
28 single argument and output a list of possible matches, one per
32 :group 'notmuch-external)
34 (defcustom notmuch-address-selection-function 'notmuch-address-selection-function
35 "The function to select address from given list. The function is
36 called with PROMPT, COLLECTION, and INITIAL-INPUT as arguments
37 (subset of what `completing-read' can be called with).
38 While executed the value of `completion-ignore-case' is t.
39 See documentation of function `notmuch-address-selection-function'
40 to know how address selection is made by default."
43 :group 'notmuch-external)
45 (defun notmuch-address-selection-function (prompt collection initial-input)
46 "Call (`completing-read'
47 PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)"
49 prompt collection nil nil initial-input 'notmuch-address-history))
51 (defvar notmuch-address-message-alist-member
52 '("^\\(Resent-\\)?\\(To\\|B?Cc\\|Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):"
53 . notmuch-address-expand-name))
55 (defvar notmuch-address-history nil)
57 (defun notmuch-address-message-insinuate ()
58 (unless (memq notmuch-address-message-alist-member message-completion-alist)
59 (setq message-completion-alist
60 (push notmuch-address-message-alist-member message-completion-alist))))
62 (defun notmuch-address-options (original)
63 (process-lines notmuch-address-command original))
65 (defun notmuch-address-expand-name ()
68 (re-search-backward "\\(\\`\\|[\n:,]\\)[ \t]*")
69 (goto-char (match-end 0))
71 (orig (buffer-substring-no-properties beg end))
72 (completion-ignore-case t)
73 (options (with-temp-message "Looking for completion candidates..."
74 (notmuch-address-options orig)))
75 (num-options (length options))
82 (funcall notmuch-address-selection-function
83 (format "Address (%s matches): " num-options)
84 (cdr options) (car options))))))
87 (push chosen notmuch-address-history)
88 (delete-region beg end)
90 (message "No matches.")
93 ;; Copied from `w3m-which-command'.
94 (defun notmuch-address-locate-command (command)
95 "Return non-nil if `command' is an executable either on
96 `exec-path' or an absolute pathname."
97 (when (stringp command)
98 (if (and (file-name-absolute-p command)
99 (file-executable-p command))
101 (setq command (file-name-nondirectory command))
102 (catch 'found-command
104 (dolist (dir exec-path)
105 (setq bin (expand-file-name command dir))
106 (when (or (and (file-executable-p bin)
107 (not (file-directory-p bin)))
108 (and (file-executable-p (setq bin (concat bin ".exe")))
109 (not (file-directory-p bin))))
110 (throw 'found-command bin))))))))
112 ;; If we can find the program specified by `notmuch-address-command',
113 ;; insinuate ourselves into `message-mode'.
114 (when (notmuch-address-locate-command notmuch-address-command)
115 (notmuch-address-message-insinuate))
119 (provide 'notmuch-address)