BSD 4_4_Lite1 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Aug 1988 07:02:50 +0000 (23:02 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Aug 1988 07:02:50 +0000 (23:02 -0800)
Work on file usr/src/contrib/emacs-18.57/lisp/saveconf.el

Synthesized-from: CSRG/cd2/4.4BSD-Lite1

usr/src/contrib/emacs-18.57/lisp/saveconf.el [new file with mode: 0644]

diff --git a/usr/src/contrib/emacs-18.57/lisp/saveconf.el b/usr/src/contrib/emacs-18.57/lisp/saveconf.el
new file mode 100644 (file)
index 0000000..68d34fc
--- /dev/null
@@ -0,0 +1,240 @@
+;;; Save Emacs buffer and window configuration between editing sessions.
+;;; Copyright (C) 1987, 1988 Kyle E. Jones
+;;;
+;;; Verbatim copies of this file may be freely redistributed.
+;;;
+;;; Modified versions of this file may be redistributed provided that this
+;;; notice remains unchanged, the file contains prominent notice of
+;;; author and time of modifications, and redistribution of the file
+;;; is not further restricted in any way.
+;;;
+;;; This file is distributed `as is', without warranties of any kind.
+
+(provide 'saveconf)
+
+(defconst save-context-version "Norma Jean"
+  "A unique string which is placed at the beginning of every saved context
+file.  If the string at the beginning of the context file doesn't match the
+value of this variable the `recover-context' command will ignore the file's
+contents.")
+
+(defvar auto-save-and-recover-context nil
+  "*If non-nil the `save-context' command will always be run before Emacs is
+exited.  Also upon Emacs startup, if this variable is non-nil and Emacs is
+passed no command line arguments, `recover-context' will be run.")
+
+(defvar save-buffer-context nil
+  "*If non-nil the `save-context' command will save the context
+of buffers that are visiting files, as well as the contexts of buffers
+that have windows.")
+
+(defvar save-context-predicate
+  (function (lambda (w)
+             (and (buffer-file-name (window-buffer w))
+                  (not (string-match "^\\(/usr\\)?/tmp/"
+                                     (buffer-file-name (window-buffer w)))))))
+  "*Value is a predicate function which determines which windows' contexts
+are saved.  When the `save-context' command is invoked, this function will
+be called once for each existing Emacs window.  The function should accept
+one argument which will be a window object, and should return non-nil if
+the window's context should be saved.")
+
+
+;; kill-emacs' function definition must be saved
+(if (not (fboundp 'just-kill-emacs))
+    (fset 'just-kill-emacs (symbol-function 'kill-emacs)))
+
+;; Make Emacs call recover-context at startup if appropriate.
+(setq top-level
+      (list 'let '((starting-up (not command-line-processed)))
+           (list 'prog1
+                 top-level
+                 '(and starting-up auto-save-and-recover-context
+                       (null (cdr command-line-args)) (recover-context)))))
+
+(defun kill-emacs (&optional query)
+  "End this Emacs session.
+Prefix ARG or optional first ARG non-nil means exit with no questions asked,
+even if there are unsaved buffers.  If Emacs is running non-interactively
+and ARG is an integer, then Emacs exits with ARG as its exit code.
+
+If the variable `auto-save-and-restore-context' is non-nil,
+the function save-context will be called first."
+  (interactive "P")
+  ;; check the purify flag.  try to save only if this is a dumped Emacs.
+  ;; saving context from a undumped Emacs caused a NULL pointer to be
+  ;; referenced through.  I'm not sure why.
+  (if (and auto-save-and-recover-context (null purify-flag))
+      (save-context))
+  (just-kill-emacs query))
+
+(defun save-context ()
+  "Save context of all Emacs windows (files visited and position of point).
+The information goes into a file called .emacs_<username> in the directory
+where the Emacs session was started.  The context can be recovered with the
+`recover-context' command, provided you are in the same directory where
+the context was saved.
+
+If the variable `save-buffer-context' is non-nil, the context of all buffers
+visiting files will be saved as well.
+
+Window sizes and shapes are not saved, since these may not be recoverable
+on terminals with a different number of rows and columns."
+  (interactive)
+  (condition-case error-data
+      (let (context-buffer mark save-file-name)
+       (setq save-file-name (concat (original-working-directory)
+                                    ".emacs_" (user-login-name)))
+       (if (not (file-writable-p save-file-name))
+           (if (file-writable-p (original-working-directory))
+               (error "context is write-protected, %s" save-file-name)
+             (error "can't access directory, %s"
+                    (original-working-directory))))
+       ;;
+       ;; set up a buffer for the saved context information
+       ;; Note that we can't set the visited file yet, because by
+       ;; giving the buffer a file to visit we are making it
+       ;; eligible to have it's context saved.
+       ;;
+       (setq context-buffer (get-buffer-create " *Context Info*"))
+       (set-buffer context-buffer)
+       (erase-buffer)
+       (set-buffer-modified-p nil)
+       ;;
+       ;; record the context information
+       ;;
+       (mapcar
+        (function
+         (lambda (w)
+           (cond ((funcall save-context-predicate w)
+                  (prin1 (buffer-file-name (window-buffer w)) context-buffer)
+                  (princ " " context-buffer)
+                  (prin1 (window-point w) context-buffer)
+                  (princ "\n" context-buffer)))))
+        (window-list))
+       
+       ;;
+       ;; nil is the data sentinel.  We will insert it later if we
+       ;; need it but for now just remember where the last line of
+       ;; window context ended.
+       ;;
+       (setq mark (point))
+
+       ;;
+       ;; If `save-buffer-context' is non-nil we save buffer contexts.
+       ;;
+       (if save-buffer-context
+           (mapcar
+            (function
+             (lambda (b)
+               (set-buffer b)
+               (cond (buffer-file-name
+                      (prin1 buffer-file-name context-buffer)
+                      (princ " " context-buffer)
+                      (prin1 (point) context-buffer)
+                      (princ "\n" context-buffer)))))
+            (buffer-list)))
+
+       ;;
+       ;; If the context-buffer contains information, we add the version
+       ;;   string and sentinels, and write out the saved context.
+       ;; If the context-buffer is empty, we don't create a file at all.
+       ;; If there's an old saved context in this directory we attempt
+       ;;   to delete it.
+       ;;
+       (cond ((buffer-modified-p context-buffer)
+              (set-buffer context-buffer)
+              (setq buffer-offer-save nil)
+              ;; sentinel for EOF
+              (insert "nil\n")
+              ;; sentinel for end of window contexts
+              (goto-char mark)
+              (insert "nil\n")
+              ;; version string
+              (goto-char (point-min))
+              (prin1 save-context-version context-buffer)
+              (insert "\n\n")
+              ;; so kill-buffer won't need confirmation later
+              (set-buffer-modified-p nil)
+              ;; save it
+              (write-region (point-min) (point-max) save-file-name
+                            nil 'quiet))
+             (t (condition-case data
+                    (delete-file save-file-name) (error nil))))
+
+       (kill-buffer context-buffer))
+    (error nil)))
+
+(defun recover-context ()
+  "Recover an Emacs context saved by `save-context' command.
+Files that were visible in windows when the context was saved are visited and
+point is set in each window to what is was when the context was saved."
+  (interactive)
+  ;;
+  ;; Set up some local variables.
+  ;;
+  (condition-case error-data
+      (let (sexpr context-buffer recover-file-name)
+       (setq recover-file-name (concat (original-working-directory)
+                                       ".emacs_" (user-login-name)))
+       (if (not (file-readable-p recover-file-name))
+           (error "can't access context, %s" recover-file-name))
+       ;;
+       ;; create a temp buffer and copy the saved context into it.
+       ;;
+       (setq context-buffer (get-buffer-create " *Recovered Context*"))
+       (set-buffer context-buffer)
+       (erase-buffer)
+       (insert-file-contents recover-file-name nil)
+       ;; so kill-buffer won't need confirmation later
+       (set-buffer-modified-p nil)
+       ;;
+       ;; If it's empty forget it.
+       ;;
+       (if (zerop (buffer-size))
+           (error "context file is empty, %s" recover-file-name))
+       ;;
+       ;; check the version and make sure it matches ours
+       ;;
+       (setq sexpr (read context-buffer))
+       (if (not (equal sexpr save-context-version))
+           (error "version string incorrect, %s" sexpr))
+       ;;
+       ;; Recover the window contexts
+       ;;
+       (while (setq sexpr (read context-buffer))
+         (select-window (get-largest-window))
+         (if (buffer-file-name)
+             (split-window))
+         (other-window 1)
+         (find-file sexpr)
+         (goto-char (read context-buffer)))
+       ;;
+       ;; Recover buffer contexts, if any.
+       ;;
+       (while (setq sexpr (read context-buffer))
+         (set-buffer (find-file-noselect sexpr))
+         (goto-char (read context-buffer)))
+       (bury-buffer "*scratch*")
+       (kill-buffer context-buffer))
+    (error nil)))
+        
+(defun original-working-directory ()
+  (save-excursion
+    (set-buffer (get-buffer-create "*scratch*"))
+    default-directory))
+
+(defun window-list (&optional mini)
+  "Returns a list of Lisp window objects for all Emacs windows.
+Optional first arg MINIBUF t means include the minibuffer window
+in the list, even if it is not active.  If MINIBUF is neither t
+nor nil it means to not count the minibuffer window even if it is active."
+  (let* ((first-window (next-window (previous-window (selected-window)) mini))
+        (windows (cons first-window nil))
+        (current-cons windows)
+        (w (next-window first-window mini)))
+    (while (not (eq w first-window))
+      (setq current-cons (setcdr current-cons (cons w nil)))
+      (setq w (next-window w mini)))
+    windows))
+