[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/persist 0c3b64f 1/3: Initial checkin
From: |
Phillip Lord |
Subject: |
[elpa] externals/persist 0c3b64f 1/3: Initial checkin |
Date: |
Fri, 28 Jun 2019 17:48:56 -0400 (EDT) |
branch: externals/persist
commit 0c3b64fca7e10caae329ea53800c8c913490bf62
Author: Phillip Lord <address@hidden>
Commit: Phillip Lord <address@hidden>
Initial checkin
---
.gitignore | 2 +
Cask | 6 +++
Makefile | 20 ++++++++
persist.el | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++
test/Makefile | 6 +++
test/persist-tests.el | 70 ++++++++++++++++++++++++++++
6 files changed, 229 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fac3642
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/.cask
+/makefile-local
diff --git a/Cask b/Cask
new file mode 100644
index 0000000..640078a
--- /dev/null
+++ b/Cask
@@ -0,0 +1,6 @@
+(source melpa-stable)
+
+(package-file "persist.el")
+
+(development
+ (depends-on "assess"))
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e0f1c02
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+EMACS ?= emacs
+CASK ?= cask
+
+-include makefile-local
+
+ifdef EMACS
+EMACS_ENV=EMACS=$(EMACS)
+endif
+
+
+test: install just-test
+
+just-test:
+ $(EMACS_ENV) $(CASK) emacs --batch -q \
+ --directory=. \
+ --load assess-discover.el \
+ --eval '(assess-discover-run-and-exit-batch t)'
+
+install:
+ $(EMACS_ENV) $(CASK) install
diff --git a/persist.el b/persist.el
new file mode 100644
index 0000000..00b0fc3
--- /dev/null
+++ b/persist.el
@@ -0,0 +1,125 @@
+;;; persist.el --- Persist Variables -*- lexical-binding: t -*-
+
+;;; Header:
+
+;; This file is not part of Emacs
+
+;; Author: Phillip Lord <address@hidden>
+;; Maintainer: Phillip Lord <address@hidden>
+;; Version: 0.1
+
+;; The contents of this file are subject to the GPL License, Version 3.0.
+
+;; Copyright (C) 2019, Phillip Lord
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides variables which persist across sessions.
+
+;; The main entry point is `persist-defvar' which behaves like
+;; `defvar' but which persists the variables between session. Variables
+;; are automatically saved when emacs exits.
+
+;; Other useful functions are `persist-save' which saves the variable
+;; immediately, `persist-load' which loads the saved value,
+;; `persist-reset' which resets to the default value.
+
+;; Values are stored in a directory in `user-emacs-directory', using
+;; one file per value. This makes it easy to delete or remove unused
+;; variables.
+
+;;; Code:
+
+(defvar persist--directory-location
+ (concat user-emacs-directory "persist/")
+ "The location of persist directory."
+ )
+
+(defvar persist--symbols nil
+ "List of symbols to persist.")
+
+(defvar persist-load-hook nil
+ "Special hook run on loading a variable.
+
+Hook functions are called with two values: the symbol and the
+value it will be set to. If any function returns nil, the
+variable is not set to the value.")
+
+(defun persist--file-location (symbol)
+ (concat persist--directory-location (symbol-name symbol)))
+
+(defmacro persist-defvar (symbol initvalue docstring)
+ (let ((form
+ `(defvar ,symbol ,initvalue ,docstring)
+ ))
+ (persist-symbol symbol initvalue)
+ (persist-load symbol)
+ form))
+
+(defun persist-symbol (symbol initvalue)
+ (add-to-list 'persist--symbols symbol)
+ (put symbol 'persist t)
+ (put symbol 'persist-default initvalue))
+
+;; Do we want a type checker or other assertion mechanism, that if it
+;; fails just resets to the default. Perhaps a single hook?
+
+(defun persist--persistant-p (symbol)
+ (get symbol 'persist))
+
+;; specifically save a variable NOW
+(defun persist-save (symbol)
+ (unless (persist--persistant-p symbol)
+ (error (format
+ "Symbol %s is not persistant" symbol)))
+ (unless (file-exists-p persist--directory-location)
+ (mkdir persist--directory-location))
+ (with-temp-buffer
+ (print (symbol-value symbol) (current-buffer))
+ (write-region (point-min) (point-max)
+ (persist--file-location symbol)
+ nil 'quiet)))
+
+;; Delete the saved persistent value and reset to default
+(defun persist-default (symbol)
+ (get symbol 'persist-default))
+
+(defun persist-reset (symbol)
+ (set symbol (persist-default symbol)))
+
+(defun persist-load (symbol)
+ (when (file-exists-p (persist--file-location symbol))
+ (with-temp-buffer
+ (insert-file-contents (persist--file-location symbol))
+ (let ((val (read (current-buffer))))
+ (when (run-hook-with-args-until-failure 'persist-load-hook
+ symbol val)
+ (set symbol val))))))
+
+(defun persist-unpersist (symbol)
+ (put symbol 'persist nil)
+ (setq persist--symbols
+ (remove symbol persist--symbols)))
+
+(defun persist--save-all ()
+ (mapc 'persist-save persist--symbols))
+
+;; Save on kill-emacs-hook anyway
+(add-hook 'kill-emacs-hook
+ 'persist--save-all)
+
+(provide 'persist)
+;;; persist.el ends here
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..8406646
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,6 @@
+## what ever we called, don't do it here
+default:
+ $(MAKE) -C ..
+
+$(MAKECMDGOALS):
+ $(MAKE) -C .. $(MAKECMDGOALS)
diff --git a/test/persist-tests.el b/test/persist-tests.el
new file mode 100644
index 0000000..411984a
--- /dev/null
+++ b/test/persist-tests.el
@@ -0,0 +1,70 @@
+(require 'persist)
+(require 'seq)
+
+
+(defmacro with-local-temp-persist (&rest body)
+ `(unwind-protect
+ (let ((persist--directory-location "./persist/")
+ (persist--symbols nil))
+ ,@body)
+ (delete-directory "./persist" t)))
+
+(ert-deftest test-persist-symbol ()
+ (should
+ (let ((persist--symbols nil)
+ (sym (cl-gensym)))
+ (persist-symbol sym 10)
+ (seq-contains persist--symbols sym))))
+
+(ert-deftest test-persist-save-only-persistant ()
+ ;; do not save not persist variables
+ (should-error
+ (with-local-temp-persist
+ (persist-save (cl-gensym)))))
+
+(ert-deftest test-persist-save ()
+ (with-local-temp-persist
+ (let ((sym (cl-gensym)))
+ (set sym 10)
+ (persist-symbol sym 10)
+ (persist-save sym)
+ (should t)
+ (should (file-exists-p (persist--file-location sym)))
+ (should
+ (string-match-p
+ "10"
+ (with-temp-buffer
+ (insert-file-contents (persist--file-location sym))
+ (buffer-string))))
+ (should-error
+ (persist-save 'fred)))))
+
+(ert-deftest test-persist-load ()
+ (with-local-temp-persist
+ (let ((sym (cl-gensym)))
+ (set sym 10)
+ (persist-symbol sym 10)
+ (persist-save sym)
+ (should (equal 10 (symbol-value sym)))
+ (set sym 30)
+ (should (equal 30 (symbol-value sym)))
+ (persist-load sym)
+ (should (equal 10 (symbol-value sym))))))
+
+(ert-deftest test-persist-remove ()
+ (with-local-temp-persist
+ (let ((sym (cl-gensym)))
+ (should-not (persist--persistant-p sym))
+ (persist-symbol sym 10)
+ (should (persist--persistant-p sym))
+ (persist-unpersist sym)
+ (should-not (persist--persistant-p sym)))))
+
+(ert-deftest test-persist-defvar ()
+ (with-local-temp-persist
+ (defvar test-no-persist-variable 10 "docstring")
+ (persist-defvar test-persist-variable 20 "docstring")
+ (should-not (persist--persistant-p 'test-no-persist-variable))
+ (should (persist--persistant-p 'test-persist-variable))
+ (should (= 20
+ (persist-default 'test-persist-variable)))))