From: CSRG Date: Mon, 15 Aug 1988 07:02:50 +0000 (-0800) Subject: BSD 4_4_Lite1 development X-Git-Tag: BSD-4_4_Lite2^2~3162 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/ff5cf2d0cb3778ba6e7acde13b976b85c2bf0ef0 BSD 4_4_Lite1 development Work on file usr/src/contrib/emacs-18.57/lisp/saveconf.el Synthesized-from: CSRG/cd2/4.4BSD-Lite1 --- 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 index 0000000000..68d34fca8d --- /dev/null +++ b/usr/src/contrib/emacs-18.57/lisp/saveconf.el @@ -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_ 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)) +