From 29e91a6ff6cdfec4e0a895a1f0fe9e72ca68df15 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 2 May 2020 00:13:05 -0400 Subject: [PATCH] Replace doom-cache library with doom-store And remove persistent-store dependency. --- core/autoload/cache.el | 95 --------------------------------- core/autoload/store.el | 116 +++++++++++++++++++++++++++++++++++++++++ core/packages.el | 3 -- docs/api.org | 4 +- 4 files changed, 118 insertions(+), 100 deletions(-) delete mode 100644 core/autoload/cache.el create mode 100644 core/autoload/store.el diff --git a/core/autoload/cache.el b/core/autoload/cache.el deleted file mode 100644 index 79db071dd..000000000 --- a/core/autoload/cache.el +++ /dev/null @@ -1,95 +0,0 @@ -;;; core/autoload/cache.el -*- lexical-binding: t; -*- - -;; This little library thinly wraps around persistent-soft (which is a pcache -;; wrapper, how about that). It has three purposes: -;; -;; + To encapsulate the cache backend (persistent-soft/pcache in this case), in -;; case it needs to change. -;; + To provide `doom-cache-persist': a mechanism for easily persisting -;; variables across Emacs sessions. -;; + To lazy-load persistent-soft until it is really needed. -;; -;; Like persistent-soft, caches assume a 2-tier structure, where all caches are -;; namespaced by location. - -(defvar doom-cache-alists '(t) - "An alist of alists, containing lists of variables for the doom cache library -to persist across Emacs sessions.") - -(defvar doom-cache-location 'doom - "The default location for cache files. This symbol is translated into a file -name under `pcache-directory' (by default a subdirectory under -`doom-cache-dir'). One file may contain multiple cache entries.") - -(defun doom-save-persistent-cache-h () - "Hook to run when an Emacs session is killed. Saves all persisted variables -listed in `doom-cache-alists' to files." - (dolist (alist (butlast doom-cache-alists 1)) - (cl-loop with key = (car alist) - for var in (cdr alist) - if (symbol-value var) - do (doom-cache-set var it nil key)))) -(add-hook 'kill-emacs-hook #'doom-save-persistent-cache-h) - - -;; -;; Library - -;;;###autoload -(defmacro with-cache! (location &rest body) - "Runs BODY with a different default `doom-cache-location'." - (declare (indent defun)) - `(let ((doom-cache-location ',location)) - ,@body)) - -;;;###autoload -(defun doom-cache-persist (location variables) - "Persist VARIABLES (list of symbols) in LOCATION (symbol). - -This populates these variables with cached values, if one exists, and saves them -to file when Emacs quits. - -Warning: this is incompatible with buffer-local variables." - (dolist (var variables) - (when (doom-cache-exists var location) - (set var (doom-cache-get var location)))) - (setf (alist-get location doom-cache-alists) - (append variables (cdr (assq location doom-cache-alists))))) - -;;;###autoload -(defun doom-cache-desist (location &optional variables) - "Unregisters VARIABLES (list of symbols) in LOCATION (symbol) from -`doom-cache-alists', thus preventing them from being saved between sessions. -Does not affect the actual variables themselves or their values." - (if variables - (setf (alist-get location doom-cache-alists) - (cl-set-difference (cdr (assq location doom-cache-alists)) - variables)) - (delq (assq location doom-cache-alists) - doom-cache-alists))) - -;;;###autoload -(defun doom-cache-get (key &optional location) - "Retrieve KEY from LOCATION (defaults to `doom-cache-location'), if it exists -and hasn't expired." - (persistent-soft-fetch - key (symbol-name (or location doom-cache-location)))) - -;;;###autoload -(defun doom-cache-set (key value &optional ttl location) - "Set KEY to VALUE in the cache. TTL is the time (in seconds) until this cache -entry expires. LOCATION is the super-key to store this cache item under; the -default is `doom-cache-location'. " - (persistent-soft-store - key value - (symbol-name (or location doom-cache-location)) ttl)) - -;;;###autoload -(defun doom-cache-exists (key &optional location) - "Returns t if KEY exists at LOCATION (defaults to `doom-cache-location')." - (persistent-soft-exists-p key (or location doom-cache-location))) - -;;;###autoload -(defun doom-cache-clear (&optional location) - "Clear a cache LOCATION (defaults to `doom-cache-location')." - (persistent-soft-flush (or location doom-cache-location))) diff --git a/core/autoload/store.el b/core/autoload/store.el new file mode 100644 index 000000000..205ac44a1 --- /dev/null +++ b/core/autoload/store.el @@ -0,0 +1,116 @@ +;;; core/autoload/cache.el -*- lexical-binding: t; -*- + +;; This little library abstracts the process of writing arbitrary elisp values +;; to a 2-tiered file store (in `doom-store-dir'/`doom-store-location'). + +(defvar doom-store-dir (concat doom-cache-dir "store/") + "Directory to look for and store data accessed through this API.") + +(defvar doom-store-persist-alist '(t) + "An alist of alists, containing lists of variables for the doom cache library +to persist across Emacs sessions.") + +(defvar doom-store-location "default" + "The default location for cache files. This symbol is translated into a file +name under `pcache-directory' (by default a subdirectory under +`doom-store-dir'). One file may contain multiple cache entries.") + +(defun doom-save-persistent-store-h () + "Hook to run when an Emacs session is killed. Saves all persisted variables +listed in `doom-store-persist-alist' to files." + (dolist (alist (butlast doom-store-persist-alist 1)) + (cl-loop with key = (car alist) + for var in (cdr alist) + if (symbol-value var) + do (doom-store-set var it nil key)))) +(add-hook 'kill-emacs-hook #'doom-save-persistent-store-h) + + +;; +;; Library + +;;;###autoload +(defun doom-store-persist (location variables) + "Persist VARIABLES (list of symbols) in LOCATION (symbol). + +This populates these variables with cached values, if one exists, and saves them +to file when Emacs quits. + +Warning: this is incompatible with buffer-local variables." + (dolist (var variables) + (when (doom-store-exists var location) + (set var (doom-store-get var location)))) + (setf (alist-get location doom-store-persist-alist) + (append variables (cdr (assq location doom-store-persist-alist))))) + +;;;###autoload +(defun doom-store-desist (location &optional variables) + "Unregisters VARIABLES (list of symbols) in LOCATION (symbol) from +`doom-store-persist-alist', thus preventing them from being saved between sessions. +Does not affect the actual variables themselves or their values." + (if variables + (setf (alist-get location doom-store-persist-alist) + (cl-set-difference (cdr (assq location doom-store-persist-alist)) + variables)) + (delq (assq location doom-store-persist-alist) + doom-store-persist-alist))) + +(defun doom--store-init (location) + (or (gethash location doom--cache) + (not (file-exists-p doom-store-dir)) + (let* ((store (expand-file-name location doom-store-dir)) + (data (and (file-exists-p store) + (with-temp-buffer + (set-buffer-multibyte nil) + (setq buffer-file-coding-system 'binary) + (let (file-name-handler-alist) + (insert-file-contents-literally store)) + (setq data (read (current-buffer))))))) + (puthash location data doom--cache) + data))) + +(defun doom--store-get (key location &optional ttl) + (when-let* ((location-data (doom--store-init location)) + (data (gethash location location-data))) + (and (or (null (car data)) + (time-less-p (time-add (current-time) ttl) (car data))) + (cdr data)))) + +(defun doom--store-put (key value location &optional ttl) + (let ((data (doom--store-init location))) + (puthash location + (cons (time-add (current-time) ttl) + (doom--store-get key location)) + data) + (let ((coding-system-for-write 'binary) + (write-region-annotate-functions nil) + (write-region-post-annotation-function nil)) + (with-temp-file (expand-file-name location doom-store-dir) + (prin1 data (current-buffer)))) + data)) + + +(defvar doom--cache (make-hash-table :test 'equal)) +;;;###autoload +(defun doom-store-get (key &optional location) + "Retrieve KEY from LOCATION (defaults to `doom-store-location'), if it exists +and hasn't expired." + (doom--store-get key (or location doom-store-location))) + +;;;###autoload +(defun doom-store-set (key value &optional ttl location) + "Set KEY to VALUE in the cache. TTL is the time (in seconds) until this cache +entry expires. LOCATION is the super-key to store this cache item under; the +default is `doom-store-location'. " + (doom--store-put key value (or location doom-store-location) ttl)) + +;;;###autoload +(defalias 'doom-store-exists #'doom-store-get) + +;;;###autoload +(defun doom-store-clear (&optional location) + "Clear a cache LOCATION (defaults to `doom-store-location')." + (let ((path (expand-file-name (or location doom-store-location) doom-store-location))) + (when (file-exists-p path) + (delete-file path) + t))) diff --git a/core/packages.el b/core/packages.el index acbab0d28..4d6494314 100644 --- a/core/packages.el +++ b/core/packages.el @@ -43,6 +43,3 @@ ;; core-keybinds.el (package! general :pin "42e38034cd2305fa7432866323c923979d8f9b06") (package! which-key :pin "8b49ae978cceca65967f3544c236f32964ddbed0") - -;; autoload/cache.el -(package! persistent-soft :pin "a1e0ddf2a12a6f18cab565dee250f070384cbe02") diff --git a/docs/api.org b/docs/api.org index e4702ffc5..9c3f8e1c5 100644 --- a/docs/api.org +++ b/docs/api.org @@ -535,7 +535,7 @@ These are side-by-side comparisons, showing how to bind keys with and without ** Persist Emacs' initial frame position, dimensions and/or full-screen state across sessions #+BEGIN_SRC elisp ;; add to ~/.doom.d/config.el -(when-let (dims (doom-cache-get 'last-frame-size)) +(when-let (dims (doom-store-get 'last-frame-size)) (cl-destructuring-bind ((left . top) width height fullscreen) dims (setq initial-frame-alist (append initial-frame-alist @@ -546,7 +546,7 @@ These are side-by-side comparisons, showing how to bind keys with and without (fullscreen . ,fullscreen)))))) (defun save-frame-dimensions () - (doom-cache-set 'last-frame-size + (doom-store-set 'last-frame-size (list (frame-position) (frame-width) (frame-height)