Rework & polish doom-store library
+ Add doom-store-rem + Add real doom-store-member-p (to replace doom-store-exists alias) + Fix doom-store-clear not clearing in-memory store + Add doom-store-flush + Add deferred flushing through doom--inhibit-flush lexical var + Update doom-store-persist & doom-store-desist for new API
This commit is contained in:
parent
5a54ef1f9f
commit
4b28e9ce86
1 changed files with 74 additions and 49 deletions
|
@ -3,7 +3,7 @@
|
||||||
;; This little library abstracts the process of writing arbitrary elisp values
|
;; This little library abstracts the process of writing arbitrary elisp values
|
||||||
;; to a 2-tiered file store (in `doom-store-dir'/`doom-store-location').
|
;; to a 2-tiered file store (in `doom-store-dir'/`doom-store-location').
|
||||||
|
|
||||||
(defvar doom-store-dir (concat doom-cache-dir "store/")
|
(defvar doom-store-dir (concat doom-etc-dir "store/")
|
||||||
"Directory to look for and store data accessed through this API.")
|
"Directory to look for and store data accessed through this API.")
|
||||||
|
|
||||||
(defvar doom-store-persist-alist '(t)
|
(defvar doom-store-persist-alist '(t)
|
||||||
|
@ -16,15 +16,19 @@ name under `pcache-directory' (by default a subdirectory under
|
||||||
`doom-store-dir'). One file may contain multiple cache entries.")
|
`doom-store-dir'). One file may contain multiple cache entries.")
|
||||||
|
|
||||||
(defvar doom--store-table (make-hash-table :test 'equal))
|
(defvar doom--store-table (make-hash-table :test 'equal))
|
||||||
|
(defvar doom--inhibit-flush nil)
|
||||||
|
|
||||||
(defun doom-save-persistent-store-h ()
|
(defun doom-save-persistent-store-h ()
|
||||||
"Hook to run when an Emacs session is killed. Saves all persisted variables
|
"Hook to run when an Emacs session is killed. Saves all persisted variables
|
||||||
listed in `doom-store-persist-alist' to files."
|
listed in `doom-store-persist-alist' to files."
|
||||||
(dolist (alist (butlast doom-store-persist-alist 1))
|
(let (locations)
|
||||||
(cl-loop with key = (car alist)
|
(let ((doom--inhibit-flush t))
|
||||||
for var in (cdr alist)
|
(dolist (alist (butlast doom-store-persist-alist 1))
|
||||||
if (symbol-value var)
|
(cl-loop with location = (car alist)
|
||||||
do (doom-store-put var it nil key))))
|
for var in (cdr alist)
|
||||||
|
do (doom-store-put var (symbol-value var) nil location)
|
||||||
|
and do (cl-pushnew location locations))))
|
||||||
|
(mapc #'doom--store-flush locations)))
|
||||||
(add-hook 'kill-emacs-hook #'doom-save-persistent-store-h)
|
(add-hook 'kill-emacs-hook #'doom-save-persistent-store-h)
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,84 +38,105 @@ listed in `doom-store-persist-alist' to files."
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun doom-store-persist (location variables)
|
(defun doom-store-persist (location variables)
|
||||||
"Persist VARIABLES (list of symbols) in LOCATION (symbol).
|
"Persist VARIABLES (list of symbols) in LOCATION (symbol).
|
||||||
|
|
||||||
This populates these variables with cached values, if one exists, and saves them
|
This populates these variables with cached values, if one exists, and saves them
|
||||||
to file when Emacs quits.
|
to file when Emacs quits. This cannot persist buffer-local variables."
|
||||||
|
|
||||||
Warning: this is incompatible with buffer-local variables."
|
|
||||||
(dolist (var variables)
|
(dolist (var variables)
|
||||||
(when (doom-store-exists var location)
|
(when (doom-store-member-p var location)
|
||||||
(set var (doom-store-get var location))))
|
(set var (doom-store-get var location))))
|
||||||
(setf (alist-get location doom-store-persist-alist)
|
(setf (alist-get location doom-store-persist-alist)
|
||||||
(append variables (cdr (assq location doom-store-persist-alist)))))
|
(append variables (alist-get location doom-store-persist-alist))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun doom-store-desist (location &optional variables)
|
(defun doom-store-desist (location &optional variables)
|
||||||
"Unregisters VARIABLES (list of symbols) in LOCATION (symbol) from
|
"Unregisters VARIABLES (list of symbols) in LOCATION (symbol).
|
||||||
`doom-store-persist-alist', thus preventing them from being saved between sessions.
|
Variables to persist are recorded in `doom-store-persist-alist'. Does not affect
|
||||||
Does not affect the actual variables themselves or their values."
|
the actual variables themselves or their values."
|
||||||
(if variables
|
(if variables
|
||||||
(setf (alist-get location doom-store-persist-alist)
|
(setf (alist-get location doom-store-persist-alist)
|
||||||
(cl-set-difference (cdr (assq location doom-store-persist-alist))
|
(cl-set-difference (cdr (assq location doom-store-persist-alist))
|
||||||
variables))
|
variables))
|
||||||
(delq (assq location doom-store-persist-alist)
|
(delq! location doom-store-persist-alist 'assoc)))
|
||||||
doom-store-persist-alist)))
|
|
||||||
|
|
||||||
(defun doom--store-init (location)
|
(defun doom--store-init (location)
|
||||||
(or (gethash location doom--store-table)
|
(or (gethash location doom--store-table)
|
||||||
(if (file-exists-p doom-store-dir)
|
(let* ((file-name-handler-alist nil)
|
||||||
(let* ((store (expand-file-name location doom-store-dir))
|
(location-path (expand-file-name location doom-store-dir)))
|
||||||
(data (and (file-exists-p store)
|
(if (file-exists-p location-path)
|
||||||
(with-temp-buffer
|
(puthash location
|
||||||
(set-buffer-multibyte nil)
|
(with-temp-buffer
|
||||||
(setq buffer-file-coding-system 'binary)
|
(set-buffer-multibyte nil)
|
||||||
(let (file-name-handler-alist)
|
(setq buffer-file-coding-system 'binary)
|
||||||
(insert-file-contents-literally store))
|
(insert-file-contents-literally location-path)
|
||||||
(read (current-buffer))))))
|
(read (current-buffer)))
|
||||||
(puthash location data doom--store-table)
|
doom--store-table)
|
||||||
data)
|
(puthash location (make-hash-table :test 'equal)
|
||||||
(make-hash-table :test #'equal))))
|
doom--store-table)))))
|
||||||
|
|
||||||
(defun doom--store-get (key location &optional default-value)
|
(defun doom--store-get (key location &optional default-value)
|
||||||
(if-let* ((location-data (doom--store-init location))
|
(let* ((location-data (doom--store-init location))
|
||||||
(data (gethash location location-data))
|
(data (gethash key location-data default-value)))
|
||||||
(_ (or (null (car data))
|
(if (and (not (eq data default-value))
|
||||||
(not (time-less-p (car data) (current-time))))))
|
(or (null (car data))
|
||||||
(cdr data)
|
(not (time-less-p (car data) (current-time)))))
|
||||||
default-value))
|
(cdr data)
|
||||||
|
default-value)))
|
||||||
|
|
||||||
(defun doom--store-put (key value location &optional ttl)
|
(defun doom--store-put (key value location &optional ttl)
|
||||||
(let ((data (doom--store-init location)))
|
(puthash key (cons (if ttl (time-add (current-time) ttl)) value)
|
||||||
(puthash location (cons (if ttl (time-add (current-time) ttl)) value) data)
|
(doom--store-init location))
|
||||||
(let ((coding-system-for-write 'binary)
|
(doom--store-flush location))
|
||||||
|
|
||||||
|
(defun doom--store-flush (location)
|
||||||
|
(unless doom--inhibit-flush
|
||||||
|
(let ((file-name-handler-alist nil)
|
||||||
|
(coding-system-for-write 'binary)
|
||||||
(write-region-annotate-functions nil)
|
(write-region-annotate-functions nil)
|
||||||
(write-region-post-annotation-function nil))
|
(write-region-post-annotation-function nil)
|
||||||
|
(data (doom--store-init location)))
|
||||||
(make-directory doom-store-dir 'parents)
|
(make-directory doom-store-dir 'parents)
|
||||||
(with-temp-file (expand-file-name location doom-store-dir)
|
(with-temp-file (expand-file-name location doom-store-dir)
|
||||||
(prin1 data (current-buffer))))
|
(prin1 data (current-buffer)))
|
||||||
data))
|
data)))
|
||||||
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun doom-store-get (key &optional location default-value)
|
(defun doom-store-get (key &optional location default-value)
|
||||||
"Retrieve KEY from LOCATION (defaults to `doom-store-location'), if it exists
|
"Retrieve KEY from LOCATION (defaults to `doom-store-location').
|
||||||
and hasn't expired."
|
If it doesn't exist or has expired, DEFAULT_VALUE is returned."
|
||||||
(doom--store-get key (or location doom-store-location) default-value))
|
(doom--store-get key (or location doom-store-location) default-value))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun doom-store-put (key value &optional ttl location)
|
(defun doom-store-put (key value &optional ttl location)
|
||||||
"Set KEY to VALUE in the cache. TTL is the time (in seconds) until this cache
|
"Set KEY to VALUE in the store at LOCATION.
|
||||||
entry expires. LOCATION is the super-key to store this cache item under; the
|
KEY can be any lisp object that is comparable with `equal'. TTL is the time (in
|
||||||
default is `doom-store-location'. "
|
seconds) until this cache entry expires. LOCATION is the super-key to store this
|
||||||
|
cache item under. It defaults to `doom-store-location'."
|
||||||
(doom--store-put key value (or location doom-store-location) ttl))
|
(doom--store-put key value (or location doom-store-location) ttl))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defalias 'doom-store-exists #'doom-store-get)
|
(defun doom-store-rem (key &optional location)
|
||||||
|
"Clear a cache LOCATION (defaults to `doom-store-location')."
|
||||||
|
(let ((location (or location doom-store-location)))
|
||||||
|
(remhash key (doom--store-init location))
|
||||||
|
(let ((table (doom--store-init "default")))
|
||||||
|
(remhash 'test table)
|
||||||
|
table)
|
||||||
|
(doom--store-flush location)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun doom-store-member-p (key &optional location)
|
||||||
|
"Return t if KEY in LOCATION exists.
|
||||||
|
LOCATION defaults to `doom-store-location'."
|
||||||
|
(let ((nil-value (format "--nilvalue%s--" (current-time))))
|
||||||
|
(not (equal (doom-store-get key location nil-value)
|
||||||
|
nil-value))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun doom-store-clear (&optional location)
|
(defun doom-store-clear (&optional location)
|
||||||
"Clear a cache LOCATION (defaults to `doom-store-location')."
|
"Clear the store at LOCATION (defaults to `doom-store-location')."
|
||||||
(let ((path (expand-file-name (or location doom-store-location) doom-store-location)))
|
(let* ((location (or location doom-store-location))
|
||||||
|
(path (expand-file-name location doom-store-dir)))
|
||||||
|
(remhash location doom--store-table)
|
||||||
(when (file-exists-p path)
|
(when (file-exists-p path)
|
||||||
(delete-file path)
|
(delete-file path)
|
||||||
t)))
|
t)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue