add lisp packages
This commit is contained in:
3
lisp/persist/.elpaignore
Normal file
3
lisp/persist/.elpaignore
Normal file
@@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
Cask
|
||||
.gitignore
|
||||
4
lisp/persist/.gitignore
vendored
Normal file
4
lisp/persist/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/.cask
|
||||
/makefile-local
|
||||
/persist.html
|
||||
/dist/
|
||||
6
lisp/persist/Cask
Normal file
6
lisp/persist/Cask
Normal file
@@ -0,0 +1,6 @@
|
||||
(source melpa-stable)
|
||||
|
||||
(package-file "persist.el")
|
||||
|
||||
(development
|
||||
(depends-on "assess"))
|
||||
29
lisp/persist/Makefile
Normal file
29
lisp/persist/Makefile
Normal file
@@ -0,0 +1,29 @@
|
||||
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
|
||||
|
||||
html:
|
||||
texi2html persist.texi
|
||||
|
||||
push-elpa:
|
||||
git push elpa HEAD:externals/persist
|
||||
|
||||
pull-elpa:
|
||||
git pull elpa externals/persist
|
||||
2
lisp/persist/persist-pkg.el
Normal file
2
lisp/persist/persist-pkg.el
Normal file
@@ -0,0 +1,2 @@
|
||||
;; Generated package description from persist.el -*- no-byte-compile: t -*-
|
||||
(define-package "persist" "0.4" "Persist Variables between Emacs Sessions" 'nil :url "http://elpa.gnu.org/packages/persist.html" :authors '(("Phillip Lord" . "phillip.lord@russet.org.uk")) :maintainer '("Phillip Lord" . "phillip.lord@russet.org.uk"))
|
||||
183
lisp/persist/persist.el
Normal file
183
lisp/persist/persist.el
Normal file
@@ -0,0 +1,183 @@
|
||||
;;; persist.el --- Persist Variables between Emacs Sessions -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phillip Lord <phillip.lord@russet.org.uk>
|
||||
;; Maintainer: Phillip Lord <phillip.lord@russet.org.uk>
|
||||
;; Package-Type: multi
|
||||
;; Version: 0.4
|
||||
|
||||
;; The contents of this file are subject to the GPL License, Version 3.0.
|
||||
|
||||
;; This file is not part of Emacs
|
||||
|
||||
;; 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
|
||||
(locate-user-emacs-file "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)
|
||||
"Return the file name at which SYMBOL does or will persist."
|
||||
(expand-file-name
|
||||
(symbol-name symbol)
|
||||
(or (get symbol 'persist-location)
|
||||
persist--directory-location)))
|
||||
|
||||
(defun persist--defvar-1 (symbol location)
|
||||
"Set symbol up for persistance."
|
||||
(when location
|
||||
(persist-location symbol location))
|
||||
(persist-symbol symbol (symbol-value symbol))
|
||||
(persist-load symbol))
|
||||
|
||||
(defmacro persist-defvar (symbol initvalue docstring &optional location)
|
||||
"Define SYMBOL as a persistant variable and return SYMBOL.
|
||||
|
||||
This form is nearly equivalent to `defvar', except that the
|
||||
variable persists between Emacs sessions.
|
||||
|
||||
It does not support the optional parameters. Both INITVALUE and
|
||||
DOCSTRING need to be given."
|
||||
;; We cannot distinguish between calls with initvalue of nil and a
|
||||
;; single parameter call. Unfortunately, these two calls have
|
||||
;; different semantics -- the single arity shuts up the byte
|
||||
;; compiler, but does not define the symbol. So, don't support a
|
||||
;; single arity persist-defvar.
|
||||
|
||||
;; Don't support 2-arity calls either because we are lazy and
|
||||
;; because if you want to persist it, you want to doc it.
|
||||
(declare (debug (symbolp form stringp &optional form)) (doc-string 3))
|
||||
;; Define inside progn so the byte compiler sees defvar
|
||||
`(progn
|
||||
(defvar ,symbol ,initvalue ,docstring)
|
||||
;; Access initvalue through its symbol because the defvar form
|
||||
;; has to stay at first level within a progn
|
||||
(persist--defvar-1 ',symbol ,location)
|
||||
',symbol))
|
||||
|
||||
(defun persist-location (symbol directory)
|
||||
"Set the directory for persisting the value of symbol.
|
||||
|
||||
This does not force the loading of value from this directory, so
|
||||
to persist a variable, you will normally need to call
|
||||
`persist-load' to load a previously saved location."
|
||||
(put symbol 'persist-location (expand-file-name directory)))
|
||||
|
||||
(defun persist-symbol (symbol &optional initvalue)
|
||||
"Make SYMBOL a persistant variable.
|
||||
|
||||
If non-nil, INITVALUE is the value to which SYMBOL will be set if
|
||||
`persist-reset' is called. Otherwise, the INITVALUE will be the
|
||||
current `symbol-value' of SYMBOL.
|
||||
|
||||
INITVALUE is set for the session and will itself not persist
|
||||
across sessions.
|
||||
|
||||
This does force the loading of value from this directory, so to
|
||||
persist a variable, you will normally need to call `persist-load'
|
||||
to load a previously saved location."
|
||||
(let ((initvalue (or initvalue (symbol-value symbol))))
|
||||
(add-to-list 'persist--symbols symbol)
|
||||
(put symbol 'persist t)
|
||||
(put symbol 'persist-default initvalue)))
|
||||
|
||||
(defun persist--persistant-p (symbol)
|
||||
"Return non-nil if SYMBOL is a persistant variable."
|
||||
(get symbol 'persist))
|
||||
|
||||
(defun persist-save (symbol)
|
||||
"Save SYMBOL now.
|
||||
|
||||
Normally, it should not be necessary to call this explicitly, as
|
||||
variables persist automatically when Emacs exits."
|
||||
(unless (persist--persistant-p symbol)
|
||||
(error (format
|
||||
"Symbol %s is not persistant" symbol)))
|
||||
(unless (equal (symbol-value symbol)
|
||||
(persist-default symbol))
|
||||
(let ((dir-loc
|
||||
(file-name-directory
|
||||
(persist--file-location symbol))))
|
||||
(unless (file-exists-p dir-loc)
|
||||
(mkdir dir-loc)))
|
||||
(with-temp-buffer
|
||||
(print (symbol-value symbol) (current-buffer))
|
||||
(write-region (point-min) (point-max)
|
||||
(persist--file-location symbol)
|
||||
nil 'quiet))))
|
||||
|
||||
(defun persist-default (symbol)
|
||||
"Return the default value for SYMBOL."
|
||||
(get symbol 'persist-default))
|
||||
|
||||
(defun persist-reset (symbol)
|
||||
"Reset the value of SYMBOL to the default."
|
||||
(set symbol (persist-default symbol)))
|
||||
|
||||
(defun persist-load (symbol)
|
||||
"Load the saved value of 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)
|
||||
"Stop the value in SYMBOL from persisting.
|
||||
|
||||
This does not remove any saved value of SYMBOL."
|
||||
(put symbol 'persist nil)
|
||||
(setq persist--symbols
|
||||
(remove symbol persist--symbols)))
|
||||
|
||||
(defun persist--save-all ()
|
||||
"Save all persistant symbols."
|
||||
(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
|
||||
153
lisp/persist/persist.texi
Normal file
153
lisp/persist/persist.texi
Normal file
@@ -0,0 +1,153 @@
|
||||
\input texinfo
|
||||
@setfilename persist.info
|
||||
@settitle persist persistant variables
|
||||
|
||||
@dircategory Emacs
|
||||
@direntry
|
||||
* Persist: (persist). Persistant variables for Emacs.
|
||||
@end direntry
|
||||
|
||||
@copying
|
||||
Copyright @copyright{} 2019 Phillip Lord
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover, or Back-Cover Texts. A copy of
|
||||
the license is included in the section entitled ``GNU Free Documentation
|
||||
License'' in the Emacs manual.
|
||||
|
||||
This document is part of a collection distributed under the GNU Free
|
||||
Documentation License. If you want to distribute this document
|
||||
separately from the collection, you can do so by adding a copy of the
|
||||
license to the document, as described in section 6 of the license.
|
||||
|
||||
All Emacs Lisp code contained in this document may be used, distributed,
|
||||
and modified without restriction.
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@titlepage
|
||||
@title Persist -- Persistant Variables for Emacs
|
||||
@author by Phillip Lord
|
||||
@page
|
||||
@insertcopying
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@node Top
|
||||
@top Persist -- Persistant Variables for Emacs
|
||||
|
||||
Perist is a library for making variables persistant; that it, their
|
||||
state can be changed from the default and the new value will remain even
|
||||
after Emacs has been closed and restarted.
|
||||
|
||||
@menu
|
||||
* Persist:: Simple Usage
|
||||
* The details:: All functions for interacting with Persist
|
||||
* Comparison:: How this relates to other, similar techniques
|
||||
* Implementation:: How variables are saved
|
||||
@end menu
|
||||
|
||||
@node Persist
|
||||
@section Persist
|
||||
|
||||
This section describes simple usage of persist.
|
||||
|
||||
@defmac persist-defvar (var initvalue docstring) body@dots{}
|
||||
This macro is equivalent in form to @code{defvar}, except any changes to
|
||||
the value of @code{var} will persist between sessions. This macro does
|
||||
not support the lower arity versions of @code{defvar}. Both an
|
||||
@code{initvalue} and @code{docstring} needs to be provided.
|
||||
@end defmac
|
||||
|
||||
@example
|
||||
@group
|
||||
(persist-defvar my-persistant-variable 10
|
||||
"A variable of no purpose.
|
||||
|
||||
This variable is persistant between sessions")
|
||||
@end group
|
||||
@end example
|
||||
|
||||
|
||||
@node The details
|
||||
@section The details
|
||||
|
||||
|
||||
@defmac persist-defvar (var initvalue docstring) body@dots{}
|
||||
This macro is equivalent to @code{defvar} and can be used to make a
|
||||
variable persistant.
|
||||
@end defmac
|
||||
|
||||
@defun persist-symbol (symbol &optional initvalue)
|
||||
This function takes @code{symbol} for an existing, non-persistant variable
|
||||
and makes it persistant. If @code{initvalue} is not given, then the
|
||||
current value is used. For package developers, @code{persist-defvar}
|
||||
would generally be prefered; this function might be useful for making
|
||||
third-party variables persistant.
|
||||
@end defun
|
||||
|
||||
@example
|
||||
@group
|
||||
(defvar my-persistant-variable 10
|
||||
"A variable of no purpose")
|
||||
|
||||
(persist-symbol 'my-persistant-variable 10)
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@defun persist-save (symbol)
|
||||
This function saves @code{symbol} immediately rather than waiting till
|
||||
the normal time
|
||||
@end defun
|
||||
|
||||
@defun persist-default (symbol)
|
||||
Return the default value for @code{symbol}. The default value is
|
||||
actually set for each session and does not persist from session to
|
||||
session, although if the value is set by either @code{persist-defvar} or
|
||||
@code{persist-symbol} saved it in a file, it will be set to the same
|
||||
value across sessions.
|
||||
@end defun
|
||||
|
||||
@defun persist-reset (symbol)
|
||||
Change the value of @code{symbol} to the last saved value if it exists.
|
||||
@end defun
|
||||
|
||||
@defun persist-location (symbol directory)
|
||||
Values are usually persisted to a standard location; it is possible to
|
||||
change this for individual symbol using this function. Be aware that
|
||||
this does not call @code{persist-load}, so this will not restore a
|
||||
previously saved value.
|
||||
@end defun
|
||||
|
||||
@node Comparison
|
||||
@section Comparison
|
||||
|
||||
There are several other packages which also persist aspects of Emacs
|
||||
across sessions, however, these fulfil a different purpose.
|
||||
|
||||
Custom persists values of variables across sessions. However, it does
|
||||
this for user options, and is associated with a user interface for
|
||||
editing the value.
|
||||
|
||||
desktop.el is also user-centric and is aimed at persisting the session
|
||||
in terms of buffers, modes and minor modes. It can be used to persist
|
||||
individual variables, but this will also save the session which the user
|
||||
may or may not want.
|
||||
|
||||
savehist.el can save individual variables but, as with desktop.el, is a
|
||||
a global setting and has other implications such as saving mini-buffer
|
||||
history.
|
||||
|
||||
@node Implementation
|
||||
@section Implementation
|
||||
|
||||
persist is implemented by saving values for each symbol into an
|
||||
different. This makes it relatively easy to update or delete the stored
|
||||
value for a variable by hand if necessary. It should scale to 10 or 100
|
||||
variables, but may get a bit slow after this.
|
||||
|
||||
@bye
|
||||
6
lisp/persist/test/Makefile
Normal file
6
lisp/persist/test/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
## what ever we called, don't do it here
|
||||
default:
|
||||
$(MAKE) -C ..
|
||||
|
||||
$(MAKECMDGOALS):
|
||||
$(MAKE) -C .. $(MAKECMDGOALS)
|
||||
127
lisp/persist/test/persist-tests.el
Normal file
127
lisp/persist/test/persist-tests.el
Normal file
@@ -0,0 +1,127 @@
|
||||
(require 'persist)
|
||||
(require 'seq)
|
||||
|
||||
|
||||
(defmacro with-local-temp-persist (&rest body)
|
||||
(declare (debug 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)))
|
||||
:type 'error
|
||||
:exclude-subtypes t))
|
||||
|
||||
(ert-deftest test-persist-save ()
|
||||
(with-local-temp-persist
|
||||
(let ((sym (cl-gensym)))
|
||||
;; precondition
|
||||
(should-not (file-exists-p (persist--file-location sym)))
|
||||
(set sym 10)
|
||||
(persist-symbol sym 10)
|
||||
(persist-save sym)
|
||||
(should t)
|
||||
(should-not (file-exists-p (persist--file-location sym)))
|
||||
(set sym 20)
|
||||
(persist-save sym)
|
||||
(should (file-exists-p (persist--file-location sym)))
|
||||
(should
|
||||
(string-match-p
|
||||
"20"
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (persist--file-location sym))
|
||||
(buffer-string))))
|
||||
(should-error
|
||||
(persist-save 'fred)))))
|
||||
|
||||
(ert-deftest test-persist-save-non-number ()
|
||||
"Test saving something that is not a number.
|
||||
|
||||
`test-persist-save' missed "
|
||||
(with-local-temp-persist
|
||||
(let ((sym (cl-gensym)))
|
||||
(set sym "fred")
|
||||
(persist-symbol sym "fred")
|
||||
(persist-save sym)
|
||||
(should t)
|
||||
(should-not (file-exists-p (persist--file-location sym)))
|
||||
(set sym "george")
|
||||
(persist-save sym)
|
||||
(should (file-exists-p (persist--file-location sym)))
|
||||
(should
|
||||
(string-match-p
|
||||
"george"
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (persist--file-location sym))
|
||||
(buffer-string)))))))
|
||||
|
||||
(ert-deftest test-persist-load ()
|
||||
(with-local-temp-persist
|
||||
(let ((sym (cl-gensym)))
|
||||
(set sym 10)
|
||||
;; set this different to force save
|
||||
(persist-symbol sym 1)
|
||||
(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)))))
|
||||
|
||||
(ert-deftest test-persist-location ()
|
||||
(unwind-protect
|
||||
(let ((sym (cl-gensym)))
|
||||
(delete-directory "./persist-defined-location" t)
|
||||
(set sym 10)
|
||||
(persist-symbol sym 10)
|
||||
(persist-location sym "./persist-defined-location")
|
||||
(should
|
||||
(equal (expand-file-name
|
||||
(symbol-name sym)
|
||||
"./persist-defined-location/")
|
||||
(persist--file-location sym)))
|
||||
(persist-save sym)
|
||||
(should-not (file-exists-p (persist--file-location sym)))
|
||||
(set sym 20)
|
||||
(persist-save sym)
|
||||
(should (file-exists-p (persist--file-location sym)))
|
||||
(should
|
||||
(string-match-p
|
||||
"20"
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (persist--file-location sym))
|
||||
(buffer-string))))
|
||||
(should-error
|
||||
(persist-save 'fred)))
|
||||
(delete-directory "./persist-defined-location" t)))
|
||||
Reference in New Issue
Block a user