]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch-address.el
emacs: Add new option notmuch-search-hide-excluded
[notmuch] / emacs / notmuch-address.el
index 71985ed79dfcce86985002abf2c97e7d9ddb0a65..f756254cb8513ec062ca692299fbb39e4f683fe1 100644 (file)
@@ -1,4 +1,4 @@
-;;; notmuch-address.el --- address completion with notmuch
+;;; notmuch-address.el --- address completion with notmuch  -*- lexical-binding: t -*-
 ;;
 ;; Copyright © David Edmondson
 ;;
 (require 'notmuch-parser)
 (require 'notmuch-lib)
 (require 'notmuch-company)
-;;
+
 (declare-function company-manual-begin "company")
 
+;;; Cache internals
+
 (defvar notmuch-address-last-harvest 0
   "Time of last address harvest.")
 
@@ -47,24 +49,33 @@ If the hash is not present it attempts to load a saved hash."
   (or notmuch-address-full-harvest-finished
       (notmuch-address--load-address-hash)))
 
+;;; Options
+
 (defcustom notmuch-address-command 'internal
   "Determines how address completion candidates are generated.
 
-If it is a string then that string should be an external program
-which must take a single argument (searched string) and output a
-list of completion candidates, one per line.
+If this is a string, then that string should be an external
+program, which must take a single argument (searched string)
+and output a list of completion candidates, one per line.
+
+If this is the symbol `internal', then an implementation is used
+that relies on the \"notmuch address\" command, but does not use
+any third-party (i.e. \"external\") programs.
 
-Alternatively, it can be the symbol `internal', in which case
-internal completion is used; the variable
-`notmuch-address-internal-completion' can be used to customize
-this case.
+If this is the symbol `as-is', then Notmuch does not modify the
+value of `message-completion-alist'. This option has to be set to
+this value before `notmuch' is loaded, otherwise the modification
+to `message-completion-alist' may already have taken place. This
+setting obviously does not prevent `message-completion-alist'
+from being modified at all; the user or some third-party package
+may still modify it.
 
-Finally, if this variable is nil then address completion is
-disabled."
+Finally, if this is nil, then address completion is disabled."
   :type '(radio
-         (const :tag "Use internal address completion" internal)
-         (const :tag "Disable address completion" nil)
-         (string :tag "Use external completion command"))
+         (const  :tag "Use internal address completion" internal)
+         (string :tag "Use external completion command")
+         (const  :tag "Disable address completion" nil)
+         (const  :tag "Use default or third-party mechanism" as-is))
   :group 'notmuch-send
   :group 'notmuch-address
   :group 'notmuch-external)
@@ -133,9 +144,16 @@ matching `notmuch-address-completion-headers-regexp'."
   :group 'notmuch-address
   :group 'notmuch-hooks)
 
+(defcustom notmuch-address-use-company t
+  "If available, use company mode for address completion."
+  :type 'boolean
+  :group 'notmuch-send
+  :group 'notmuch-address)
+
+;;; Setup
+
 (defun notmuch-address-selection-function (prompt collection initial-input)
-  "Call (`completing-read'
-      PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)"
+  "Default address selection function: delegate to completing read."
   (completing-read
    prompt collection nil nil initial-input 'notmuch-address-history))
 
@@ -147,22 +165,14 @@ matching `notmuch-address-completion-headers-regexp'."
 (defun notmuch-address-message-insinuate ()
   (message "calling notmuch-address-message-insinuate is no longer needed"))
 
-(defcustom notmuch-address-use-company t
-  "If available, use company mode for address completion."
-  :type 'boolean
-  :group 'notmuch-send
-  :group 'notmuch-address)
-
 (defun notmuch-address-setup ()
-  (let* ((setup-company (and notmuch-address-use-company
-                            (require 'company nil t)))
-        (pair (cons notmuch-address-completion-headers-regexp
-                    #'notmuch-address-expand-name)))
-    (when setup-company
+  (unless (eq notmuch-address-command 'as-is)
+    (when (and notmuch-address-use-company
+              (require 'company nil t))
       (notmuch-company-setup))
-    (unless (member pair message-completion-alist)
-      (setq message-completion-alist
-           (push pair message-completion-alist)))))
+    (cl-pushnew (cons notmuch-address-completion-headers-regexp
+                     #'notmuch-address-expand-name)
+               message-completion-alist :test #'equal)))
 
 (defun notmuch-address-toggle-internal-completion ()
   "Toggle use of internal completion for current buffer.
@@ -178,12 +188,14 @@ toggles the setting in this buffer."
        (kill-local-variable 'company-idle-delay)
       (setq-local company-idle-delay nil))))
 
+;;; Completion
+
 (defun notmuch-address-matching (substring)
   "Returns a list of completion candidates matching SUBSTRING.
 The candidates are taken from `notmuch-address-completions'."
   (let ((candidates)
        (re (regexp-quote substring)))
-    (maphash (lambda (key val)
+    (maphash (lambda (key _val)
               (when (string-match re key)
                 (push key candidates)))
             notmuch-address-completions)
@@ -204,7 +216,7 @@ requiring external commands."
       ;; harvest if necessary.
       (notmuch-address-harvest-trigger)))
    (t
-    (process-lines notmuch-address-command original))))
+    (notmuch--process-lines notmuch-address-command original))))
 
 (defun notmuch-address-expand-name ()
   (cond
@@ -231,14 +243,8 @@ requiring external commands."
                    (t
                     (funcall notmuch-address-selection-function
                              (format "Address (%s matches): " num-options)
-                             ;; We put the first match as the initial
-                             ;; input; we put all the matches as
-                             ;; possible completions, moving the
-                             ;; first match to the end of the list
-                             ;; makes cursor up/down in the list work
-                             ;; better.
-                             (append (cdr options) (list (car options)))
-                             (car options))))))
+                             options
+                             orig)))))
       (if chosen
          (progn
            (push chosen notmuch-address-history)
@@ -250,12 +256,11 @@ requiring external commands."
        (ding))))
    (t nil)))
 
-(defun notmuch-address-harvest-addr (result)
-  (let ((name-addr (plist-get result :name-addr)))
-    (puthash name-addr t notmuch-address-completions)))
+;;; Harvest
 
-(defun notmuch-address-harvest-handle-result (obj)
-  (notmuch-address-harvest-addr obj))
+(defun notmuch-address-harvest-addr (result)
+  (puthash (plist-get result :name-addr)
+          t notmuch-address-completions))
 
 (defun notmuch-address-harvest-filter (proc string)
   (when (buffer-live-p (process-buffer proc))
@@ -264,7 +269,7 @@ requiring external commands."
        (goto-char (point-max))
        (insert string))
       (notmuch-sexp-parse-partial-list
-       'notmuch-address-harvest-handle-result (process-buffer proc)))))
+       'notmuch-address-harvest-addr (process-buffer proc)))))
 
 (defvar notmuch-address-harvest-procs '(nil . nil)
   "The currently running harvests.
@@ -302,7 +307,7 @@ execution, CALLBACK is called when harvesting finishes."
                            (and config-query
                                 (format " and (%s)" config-query)))
                  from-or-to-me-query))
-        (args `("address" "--format=sexp" "--format-version=4"
+        (args `("address" "--format=sexp" "--format-version=5"
                 ,(if sent "--output=recipients" "--output=sender")
                 "--deduplicate=address"
                 ,query)))
@@ -375,7 +380,7 @@ to be a saved address hash."
 (defun notmuch-address--save-address-hash ()
   (when notmuch-address-save-filename
     (if (or (not (file-exists-p notmuch-address-save-filename))
-           ;; The file exists, check it is a file we saved
+           ;; The file exists, check it is a file we saved.
            (notmuch-address--get-address-hash))
        (with-temp-file notmuch-address-save-filename
          (let ((save-plist
@@ -396,17 +401,16 @@ appear to be an address savefile.  Not overwriting."
       (setq notmuch-address-last-harvest now)
       (notmuch-address-harvest
        nil nil
-       (lambda (proc event)
+       (lambda (_proc event)
         ;; If harvest fails, we want to try
-        ;; again when the trigger is next
-        ;; called
+        ;; again when the trigger is next called.
         (if (string= event "finished\n")
             (progn
               (notmuch-address--save-address-hash)
               (setq notmuch-address-full-harvest-finished t))
           (setq notmuch-address-last-harvest 0)))))))
 
-;;
+;;; Standalone completion
 
 (defun notmuch-address-from-minibuffer (prompt)
   (if (not notmuch-address-command)
@@ -425,7 +429,7 @@ appear to be an address savefile.  Not overwriting."
       (let ((minibuffer-local-map rmap))
        (read-string prompt)))))
 
-;;
+;;; _
 
 (provide 'notmuch-address)