;;; tehom-3.el --- Routines to save & restore complex elisp objects
;; Copyright (C) 1999 by Tom Breton
;; Author: Tom Breton
;; Created: 11 June 1999
;; Version: 1.0
;; Keywords: extensions
;; This file 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 2, or (at your option)
;; any later version.
;; This file 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 GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; This package is intended to easily save and restore the state of
;; any moderately complex elisp application. To use it, represent all
;; the persisting state of your app as one elisp object, and call
;; tehom-save-object and tehom-restore-object when ending / restarting
;; it. That's all.
;; This package requires cust-print and cl-read. For best results,
;; they should be byte-compiled.
;; It does not require either cust-print or cl-read to be set up, in
;; the sense that you need to add any code to support them. They need
;; only be accessible. Then you simply call tehom-save-object and
;; tehom-restore-object without further attention to the mechanics.
;; This package can read and write circular references (thanks to
;; cl-read and cust-print) within a single complex object, but using
;; it more than once (with separate savefiles) to write/read some
;; interlinked objects will not (and couldn't even in theory) resolve
;; inter-references between them. So if you have to save and restore
;; interlinked objects, combine them into a single object.
;; A single save file can only contain one elisp object as one sexp.
;; If there is more than one sexp in a save file, only the first will
;; be read.
;; The entry points are tehom-save-object and tehom-restore-object
;;; Code:
(require 'cust-print)
(require 'cl-read)
(defconst tehom-save-transfer-buf-name " *Transfer buffer*" "" )
;;;; Utility functions
( defun tehom-comment-protect-string (string-0)
"Return the string, but in comment syntax.
This function handles only comment-start, not comment-end, and only
handles lisp comment syntax. Which is to say, it does no more than is
needed for the tehom-3 package. It could easily be generalized."
(let*
(
(comment-protector (concat "\n" ";;" ))
(string-1
(split-string string-0 "\n" ))
(string-2
(mapconcat
'identity
string-1
comment-protector))
(string-3 (concat comment-protector string-2)))
string-3))
;;;; Helper functions
(defun tehom-write-custprinted-object-to-buf ( object savebuf)
"Fill SAVEBUF with the printed representation of OBJECT. "
(custom-print-install)
(let
( (print-circle t)
(custom-print-vectors t))
(custom-prin1 object savebuf ))
(custom-print-uninstall))
;;;; Entry points
( defun tehom-save-object (object filename &optional comment-0)
"Save the elisp object OBJECT to the file FILENAME.
If COMMENT-0 is passed, the file will begin with that text as a
comment."
(let*
(
(buf (get-buffer-create tehom-save-transfer-buf-name))
(comment
(or comment-0
"Data saved by tehom-save-object, written by Tom Breton" )))
(with-current-buffer buf
;;The buffer is just for transfer, so we don't need undo.
(setq buffer-undo-list t)
(buffer-disable-undo)
;;Clear the buffer so nothing interferes.
(erase-buffer)
;;Insert an explanatory comment.
(insert "\n;;" (tehom-comment-protect-string comment) "\n" )
;;Write the data.
(tehom-write-custprinted-object-to-buf object buf)
;;Write to that file, not caring whether it already exists.
(write-file filename)
;;Erase what's in here. No need to keep it. We don't delete
;;our buffer because re-using later it is more efficient.
(erase-buffer)
(set-buffer-modified-p nil)
)))
( defun tehom-restore-object (filename)
"Return the object restored from the file FILENAME."
(let*
((buf (get-buffer-create tehom-save-transfer-buf-name))
object)
(with-current-buffer buf
(setq buffer-undo-list t)
(buffer-disable-undo)
;;Get the file contents into our buffer.
(insert-file-contents filename t nil nil t )
;;Go to the start of the buffer.
(goto-char (point-min))
;;Enable cl-reader. We enable it permanently, since this is the
;;only thing this buffer is used for
(setq cl-read-active t)
;;Read specially. We can just use reader::read-from-buffer since
;;we know we're looking at a buffer.
(setq object ( reader::read-from-buffer buf ))
;;Erase what's in here. No need to keep it. We don't delete
;;our buffer because re-using later it is more efficient.
(erase-buffer)
(set-buffer-modified-p nil)
;;Return the object
object)))
(provide 'tehom-3)
;;; tehom-3.el ends here