;; restore.el -- automatically save emacs "desktop" ;; ;; Time-stamp: ;; ;; Taken from saveplace.el by Karl Fogel ;; ;; When you exit, the list of files open, as well as where in each file you are, ;; is saved. When you startup emacs (without a filename argument), assuming you ;; have set up your .emacs file correctly (see below), then all the files you ;; had open when you last exited emacs will be opened, and the point will be ;; placed where it was in each buffer when you last exited emacs. ;; ;; Version 1.0: 23 Aug 1996 by AWColley ;; (defvar restore-env-alist nil "Alist of last emacs desktop. Each element looks like (FILENAME . POSITION).") (defvar in-restore-env nil "*Non-nil means include this file in restore-env-alist when you exit emacs. If you wish to automatically include any open file everytime you exit emacs, then add the following to your ~/.emacs file: \(load \"restore\"\) \(setq-default in-restore-env t\)") (make-variable-buffer-local 'in-restore-env) (defvar restore-env-file "~/.emacs-env" "*Name of the file that saves the restore-env-alist.") (defvar restore-env-version-control 'nospecial "*Controls how to backup restore-env-file. See version-control.") (defvar restore-env-loaded nil "Non-nil means that the restore-env-file has already been loaded.") (defun toggle-in-restore-env (&optional parg) "Toggle whether to save your place in this file at the end of this session. If called with a prefix arg, the mode is enabled if the argument is positive and disabled otherwise." (interactive "P") (if (not buffer-file-name) (message (format "Buffer \"%s\" not visiting a file." (buffer-name))) (if (and in-restore-env (or (not parg) (<= parg 0))) (progn (message "This file will NOT be included in restore environment.") (setq in-restore-env nil) ) (message "This file will be included in restore environment.") (setq in-restore-env t) ) ) ) (defun restore-env-to-alist () ;; Put filename and point for current-buffer in a cons box and then cons that ;; onto the front of the restore-env-alist, if in-restore-env is non-nil. ;; Otherwise, just delete that file from the alist. (if buffer-file-name (progn (let ((cell (assoc buffer-file-name restore-env-alist))) (if cell (setq restore-env-alist (delq cell restore-env-alist)) ) ) (if in-restore-env (setq restore-env-alist (cons (cons buffer-file-name (point)) restore-env-alist) ) ) ) ) ) (defun restore-env-alist-to-file () ;; save the current desktop to the restore-env-file (let ((file (expand-file-name restore-env-file))) (save-excursion (message (format "Saving desktop to %s..." file)) (set-buffer (get-buffer-create " *Restore Desktop*")) (delete-region (point-min) (point-max)) (goto-char (point-min)) (print restore-env-alist (current-buffer)) (let ((version-control (cond ((null restore-env-version-control) nil) ((eq 'never restore-env-version-control) 'never) ((eq 'nospecial restore-env-version-control) version-control) (t t)))) (write-file file) (kill-buffer (current-buffer)) (message (format "Saving desktop to %s...done." file)) ) ) ) ) (defun load-restore-env-alist-from-file () ;; restore the desktop saved in the restore-env-file (if (not restore-env-loaded) (progn (setq restore-env-loaded t) (let ((file (expand-file-name restore-env-file))) ;; make sure that the alist does not get overwritten, and then ;; load it if it exists (if (file-readable-p file) (save-excursion (message (format "Restoring desktop from %s..." restore-env-file)) ;; don't want to use find-file because we have been adding hooks to it. (set-buffer (get-buffer-create " *Restore Desktop*")) (delete-region (point-min) (point-max)) (insert-file-contents file) (goto-char (point-min)) (setq restore-env-alist (car (read-from-string (buffer-substring (point-min) (point-max))) ) ) (kill-buffer (current-buffer)) (message (format "Restoring desktop from %s...done." file)) t) t) nil) ) ) ) (defun restore-envs-to-alist () ;; Go through buffer-list, saving places to alist if in-restore-env is non-nil. (setq restore-env-alist nil) (let ((buf-list (buffer-list))) (while buf-list ;; put this into a save-excursion in case someone is counting on ;; another function in kill-emacs-hook to act on the last buffer ;; they were in: (save-excursion (set-buffer (car buf-list)) ;; in-restore-env checks buffer-file-name too, but we can avoid overhead ;; of function call by checking here too. (and buffer-file-name (restore-env-to-alist)) (setq buf-list (cdr buf-list)) ) ) ) ) (defun restore-env-disable-all () "Go through buffer-list, turning in-restore-env to nil in each of them." (interactive) (let ((buf-list (buffer-list))) (while buf-list (save-excursion (set-buffer (car buf-list)) (if buffer-file-name (setq in-restore-env nil) ) (setq buf-list (cdr buf-list)) ) ) ) (setq restore-env-alist nil) (message "No currently open files will be included in saved desktop.") ) (defun restore-env-load-all () "Restore environment saved in restore-env-file." (interactive) (or restore-env-loaded (load-restore-env-alist-from-file)) (let ((file-list restore-env-alist)) (while file-list (find-file (car (car file-list))) (setq file-list (cdr file-list)) ) ) ) (defun restore-env-startup-hook () ;; If there are no command line arguments, restore last desktop (if (< (length command-line-args) 2) (restore-env-load-all) ) ) (defun restore-env-find-file-hook () ;; When a file is opened, if it is in the saved desktop, place point at the ;; last location saved. (or restore-env-loaded (load-restore-env-alist-from-file)) (let ((cell (assoc buffer-file-name restore-env-alist))) (if cell (progn (or after-find-file-from-revert-buffer (goto-char (cdr cell))) ;; and make sure it will be saved again... (setq in-restore-env t) ) ) ) ) (defun restore-env-kill-emacs-hook () ;; When emacs exits, save the desktop (restore-envs-to-alist) (restore-env-alist-to-file) ) (add-hook 'find-file-hooks 'restore-env-find-file-hook t) (add-hook 'kill-emacs-hook 'restore-env-kill-emacs-hook) (add-hook 'after-init-hook 'restore-env-startup-hook) (provide 'restore) ; why not... ;;; restore.el ehdn here