unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Mark Walters <markwalters1009@gmail.com>
To: notmuch@notmuchmail.org
Subject: [PATCH 2/2] emacs: address: save hash
Date: Sun, 20 Nov 2016 16:50:34 +0000	[thread overview]
Message-ID: <1479660634-17956-3-git-send-email-markwalters1009@gmail.com> (raw)
In-Reply-To: <1479660634-17956-1-git-send-email-markwalters1009@gmail.com>

This allows the user to save the address hash so that it is much
faster for the first completion after a restart. This defaults to off
as there are privacy implications to saving this information.

The code tries hard to avoid overwriting the wrong file. It also notes
if changes have been made to any of the relevant user settings, so
that the user does not get surprising results (i.e., outdated options
being used). Finally it stores some version information so that is
easy for us to update the format of the save file.
---
 emacs/notmuch-address.el | 83 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el
index 2eaca79..15c709d 100644
--- a/emacs/notmuch-address.el
+++ b/emacs/notmuch-address.el
@@ -37,11 +37,15 @@
 
 (defvar notmuch-address-full-harvest-finished nil
   "t indicates that full completion address harvesting has been
-finished. Use notmuch-address--harvest-ready to access.")
+finished. Use notmuch-address--harvest-ready to access as that
+will load a saved hash if necessary (and available).")
 
 (defun notmuch-address--harvest-ready ()
-  "Return t if there is a full address hash available."
-  notmuch-address-full-harvest-finished)
+  "Return t if there is a full address hash available.
+
+If the hash is not present it attempts to load a saved hash."
+  (or notmuch-address-full-harvest-finished
+      (notmuch-address--load-address-hash)))
 
 (defcustom notmuch-address-command 'internal
   "Determines how address completion candidates are generated.
@@ -91,6 +95,17 @@ This should be a list of the form '(DIRECTION FILTER), where
   :group 'notmuch-send
   :group 'notmuch-external)
 
+(defcustom notmuch-address-save-filename nil
+  "Filename to save the cached completion addresses.
+
+All the addresses notmuch uses for address completion will be
+cached in this file. This has obvious privacy implications so you
+should make sure it is not somewhere publicly readable."
+  :type '(choice (const :tag "Off" nil)
+		 (file :tag "Filename"))
+  :group 'notmuch-send
+  :group 'notmuch-external)
+
 (defcustom notmuch-address-selection-function 'notmuch-address-selection-function
   "The function to select address from given list. The function is
 called with PROMPT, COLLECTION, and INITIAL-INPUT as arguments
@@ -327,6 +342,64 @@ execution, CALLBACK is called when harvesting finishes."
   ;; return value
   nil)
 
+(defvar notmuch-address--save-hash-version 1
+  "Version format of the save hash.")
+
+(defun notmuch-address--get-address-hash ()
+  "Returns the saved address hash as a plist.
+
+Returns nil if the save file does not exist, or it does not seem
+to be a saved address hash."
+  (when notmuch-address-save-filename
+    (condition-case nil
+	(with-temp-buffer
+	  (insert-file-contents notmuch-address-save-filename)
+	  (let ((name (read (current-buffer)))
+		(plist (read (current-buffer))))
+	    ;; We do two simple sanity checks on the loaded file. We just
+	    ;; check a version is specified, not that it is the current
+	    ;; version, as we are allowed to over-write and a save-file with
+	    ;; an older version.
+	    (when (and (string= name "notmuch-address-hash")
+		       (plist-get plist :version))
+	      plist)))
+      ;; The error case catches any of the reads failing.
+      (error nil))))
+
+(defun notmuch-address--load-address-hash ()
+  "Read the saved address hash and set the corresponding variables."
+  (let ((load-plist (notmuch-address--get-address-hash)))
+    (when (and load-plist
+	       ;; If the user's setting have changed, or the version
+	       ;; has changed, return nil to make sure the new settings
+	       ;; take effect.
+	       (equal (plist-get load-plist :completion-settings)
+		      notmuch-address-internal-completion)
+	       (equal (plist-get load-plist :version)
+		      notmuch-address--save-hash-version))
+      (setq notmuch-address-last-harvest (plist-get load-plist :last-harvest)
+	    notmuch-address-completions (plist-get load-plist :completions)
+	    notmuch-address-full-harvest-finished t)
+      ;; Return t to say load was successful.
+      t)))
+
+(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
+	    (notmuch-address--get-address-hash))
+	(with-temp-file notmuch-address-save-filename
+	  (let ((save-plist (list :version notmuch-address--save-hash-version
+				  :completion-settings notmuch-address-internal-completion
+				  :last-harvest notmuch-address-last-harvest
+				  :completions notmuch-address-completions)))
+	    (print "notmuch-address-hash" (current-buffer))
+	    (print save-plist (current-buffer))))
+      (message "\
+Warning: notmuch-address-save-filename %s exists but doesn't
+appear to be an address savefile.  Not overwriting."
+	       notmuch-address-save-filename))))
+
 (defun notmuch-address-harvest-trigger ()
   (let ((now (float-time)))
     (when (> (- now notmuch-address-last-harvest) 86400)
@@ -337,7 +410,9 @@ execution, CALLBACK is called when harvesting finishes."
 				 ;; again when the trigger is next
 				 ;; called
 				 (if (string= event "finished\n")
-				     (setq notmuch-address-full-harvest-finished t)
+				     (progn
+				       (notmuch-address--save-address-hash)
+				       (setq notmuch-address-full-harvest-finished t))
 				   (setq notmuch-address-last-harvest 0)))))))
 
 ;;
-- 
2.1.4

  parent reply	other threads:[~2016-11-20 16:50 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-20 16:50 [PATCH 0/2] emacs allow save and load of the address-completions Mark Walters
2016-11-20 16:50 ` [PATCH 1/2] emacs: address: move address-full-harvest-finished to a function Mark Walters
2016-11-20 16:50 ` Mark Walters [this message]
2017-01-28  2:32 ` [PATCH 0/2] emacs allow save and load of the address-completions David Bremner

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://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1479660634-17956-3-git-send-email-markwalters1009@gmail.com \
    --to=markwalters1009@gmail.com \
    --cc=notmuch@notmuchmail.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://yhetil.org/notmuch.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).