Mercurial > hg > xemacs-beta
comparison lisp/packages/saveconf.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; Save Emacs buffer and window configuration between editing sessions. | |
2 ;;; Copyright (C) 1987, 1988, 1989 Kyle E. Jones | |
3 ;;; | |
4 ;;; This program is free software; you can redistribute it and/or modify | |
5 ;;; it under the terms of the GNU General Public License as published by | |
6 ;;; the Free Software Foundation; either version 1, or (at your option) | |
7 ;;; any later version. | |
8 ;;; | |
9 ;;; This program is distributed in the hope that it will be useful, | |
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 ;;; GNU General Public License for more details. | |
13 ;;; | |
14 ;;; A copy of the GNU General Public License can be obtained from the | |
15 ;;; program's author (send electronic mail to kyle@cs.odu.edu) or from | |
16 ;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA | |
17 ;;; 02139, USA. | |
18 ;;; | |
19 ;;; Send bug reports to kyle@cs.odu.edu. | |
20 | |
21 ;;; Synched up with: Not in FSF. | |
22 | |
23 ;; This package of functions gives Emacs the ability to remember which | |
24 ;; files were being visited, the windows that were on them, and the | |
25 ;; value of point in their buffers the last Emacs session in the same | |
26 ;; directory. This is an emulation of an old Gosling Emacs feature. | |
27 ;; | |
28 ;; The relevant commands are save-context and recover-context. | |
29 ;; | |
30 ;; Most of the time you'll want an Emacs session's context saved even if | |
31 ;; you choose not to recover it later. To avoid having to manually | |
32 ;; M-x save-context at each emacs exit, put the line: | |
33 ;; (setq auto-save-and-recover-context t) | |
34 ;; in your .emacs or in default.el in the lisp directory of the Emacs | |
35 ;; distribution. The context will then automatically be saved when | |
36 ;; Emacs exits. | |
37 ;; | |
38 ;; By default only the contexts of visible buffers (buffers with windows | |
39 ;; on them) are saved. Setting the variable save-buffer-context to t | |
40 ;; causes the contexts of all buffers to be saved. | |
41 ;; | |
42 ;; Put this file in the "lisp" directory of the emacs distribution in a | |
43 ;; file called saveconf.el. Byte-compile it. | |
44 ;; | |
45 ;; There are two ways to use this package. | |
46 ;; 1) Put the line | |
47 ;; (require 'saveconf) | |
48 ;; in the file site-init.el in the lisp directory of the Emacs | |
49 ;; directory and rebuild Emacs. If you get the "Pure Lisp storage | |
50 ;; exhausted" error message when rebuilding Emacs, increase PURESIZE | |
51 ;; in src/config.h by about 30000 bytes and try again. It's almost | |
52 ;; certain that this will happen to you so you might as well increase | |
53 ;; PURESIZE beforehand. | |
54 ;; | |
55 ;; This is the preferred mode of operation because it allows the | |
56 ;; package to become part of Emacs' startup sequence and automatically | |
57 ;; restore context in a directory if Emacs is invoked without any | |
58 ;; command line arguments. | |
59 ;; | |
60 ;; 2) Put these lines | |
61 ;; (require 'saveconf) | |
62 ;; (if (null (cdr command-line-args)) | |
63 ;; (setq inihibit-startup-message (recover-context))) | |
64 ;; at the end of your .emacs file or the default.el file in the | |
65 ;; lisp directory of the Emacs distribution. This causes the | |
66 ;; context saved in the current directory to be recovered whenever | |
67 ;; Emacs is invoked without any arguments. | |
68 | |
69 (provide 'saveconf) | |
70 | |
71 (defconst save-context-version "Norma Jean" | |
72 "A unique string which is placed at the beginning of every saved context | |
73 file. If the string at the beginning of the context file doesn't match the | |
74 value of this variable the `recover-context' command will ignore the file's | |
75 contents.") | |
76 | |
77 (defvar auto-save-and-recover-context nil | |
78 "*If non-nil the `save-context' command will always be run before Emacs is | |
79 exited. Also upon Emacs startup, if this variable is non-nil and Emacs is | |
80 passed no command line arguments, `recover-context' will be run.") | |
81 | |
82 (defvar save-buffer-context nil | |
83 "*If non-nil the `save-context' command will save the context | |
84 of buffers that are visiting files, as well as the contexts of buffers | |
85 that have windows.") | |
86 | |
87 (defvar save-context-predicate | |
88 (function (lambda (w) | |
89 (and (buffer-file-name (window-buffer w)) | |
90 (not (string-match "^\\(/usr\\)?/tmp/" | |
91 (buffer-file-name (window-buffer w))))))) | |
92 "*Value is a predicate function which determines which windows' contexts | |
93 are saved. When the `save-context' command is invoked, this function will | |
94 be called once for each existing Emacs window. The function should accept | |
95 one argument which will be a window object, and should return non-nil if | |
96 the window's context should be saved.") | |
97 | |
98 | |
99 ;; kill-emacs' function definition must be saved | |
100 (if (not (fboundp 'just-kill-emacs)) | |
101 (fset 'just-kill-emacs (symbol-function 'kill-emacs))) | |
102 | |
103 ;; Make Emacs call recover-context at startup if appropriate. | |
104 (setq top-level | |
105 (list 'let '((starting-up (not command-line-processed))) | |
106 (list 'prog1 | |
107 top-level | |
108 '(and starting-up auto-save-and-recover-context | |
109 (null (cdr command-line-args)) (recover-context))))) | |
110 | |
111 (defun kill-emacs (&optional query) | |
112 "End this Emacs session. | |
113 Prefix ARG or optional first ARG non-nil means exit with no questions asked, | |
114 even if there are unsaved buffers. If Emacs is running non-interactively | |
115 and ARG is an integer, then Emacs exits with ARG as its exit code. | |
116 | |
117 If the variable `auto-save-and-restore-context' is non-nil, | |
118 the function save-context will be called first." | |
119 (interactive "P") | |
120 ;; check the purify flag. try to save only if this is a dumped Emacs. | |
121 ;; saving context from a undumped Emacs caused a NULL pointer to be | |
122 ;; referenced through. I'm not sure why. | |
123 (if (and auto-save-and-recover-context (null purify-flag)) | |
124 (save-context)) | |
125 (just-kill-emacs query)) | |
126 | |
127 (defun save-context () | |
128 "Save context of all Emacs windows (files visited and position of point). | |
129 The information goes into a file called .emacs_<username> in the directory | |
130 where the Emacs session was started. The context can be recovered with the | |
131 `recover-context' command, provided you are in the same directory where | |
132 the context was saved. | |
133 | |
134 If the variable `save-buffer-context' is non-nil, the context of all buffers | |
135 visiting files will be saved as well. | |
136 | |
137 Window sizes and shapes are not saved, since these may not be recoverable | |
138 on terminals with a different number of rows and columns." | |
139 (interactive) | |
140 (condition-case error-data | |
141 (let (context-buffer mark save-file-name) | |
142 (setq save-file-name (concat (original-working-directory) | |
143 ".emacs_" (user-login-name))) | |
144 (if (not (file-writable-p save-file-name)) | |
145 (if (file-writable-p (original-working-directory)) | |
146 (error "context is write-protected, %s" save-file-name) | |
147 (error "can't access directory, %s" | |
148 (original-working-directory)))) | |
149 ;; | |
150 ;; set up a buffer for the saved context information | |
151 ;; Note that we can't set the visited file yet, because by | |
152 ;; giving the buffer a file to visit we are making it | |
153 ;; eligible to have it's context saved. | |
154 ;; | |
155 (setq context-buffer (get-buffer-create " *Context Info*")) | |
156 (set-buffer context-buffer) | |
157 (erase-buffer) | |
158 (set-buffer-modified-p nil) | |
159 ;; | |
160 ;; record the context information | |
161 ;; | |
162 (mapcar | |
163 (function | |
164 (lambda (w) | |
165 (cond ((funcall save-context-predicate w) | |
166 (prin1 (buffer-file-name (window-buffer w)) context-buffer) | |
167 (princ " " context-buffer) | |
168 (prin1 (window-point w) context-buffer) | |
169 (princ "\n" context-buffer))))) | |
170 (window-list)) | |
171 | |
172 ;; | |
173 ;; nil is the data sentinel. We will insert it later if we | |
174 ;; need it but for now just remember where the last line of | |
175 ;; window context ended. | |
176 ;; | |
177 (setq mark (point)) | |
178 | |
179 ;; | |
180 ;; If `save-buffer-context' is non-nil we save buffer contexts. | |
181 ;; | |
182 (if save-buffer-context | |
183 (mapcar | |
184 (function | |
185 (lambda (b) | |
186 (set-buffer b) | |
187 (cond (buffer-file-name | |
188 (prin1 buffer-file-name context-buffer) | |
189 (princ " " context-buffer) | |
190 (prin1 (point) context-buffer) | |
191 (princ "\n" context-buffer))))) | |
192 (buffer-list))) | |
193 | |
194 ;; | |
195 ;; If the context-buffer contains information, we add the version | |
196 ;; string and sentinels, and write out the saved context. | |
197 ;; If the context-buffer is empty, we don't create a file at all. | |
198 ;; If there's an old saved context in this directory we attempt | |
199 ;; to delete it. | |
200 ;; | |
201 (cond ((buffer-modified-p context-buffer) | |
202 (set-buffer context-buffer) | |
203 (setq buffer-offer-save nil) | |
204 ;; sentinel for EOF | |
205 (insert "nil\n") | |
206 ;; sentinel for end of window contexts | |
207 (goto-char mark) | |
208 (insert "nil\n") | |
209 ;; version string | |
210 (goto-char (point-min)) | |
211 (prin1 save-context-version context-buffer) | |
212 (insert "\n\n") | |
213 ;; so kill-buffer won't need confirmation later | |
214 (set-buffer-modified-p nil) | |
215 ;; save it | |
216 (write-region (point-min) (point-max) save-file-name | |
217 nil 'quiet)) | |
218 (t (condition-case data | |
219 (delete-file save-file-name) (error nil)))) | |
220 | |
221 (kill-buffer context-buffer)) | |
222 (error nil))) | |
223 | |
224 (defun recover-context () | |
225 "Recover an Emacs context saved by `save-context' command. | |
226 Files that were visible in windows when the context was saved are visited and | |
227 point is set in each window to what is was when the context was saved." | |
228 (interactive) | |
229 (condition-case error-data | |
230 ;; | |
231 ;; Set up some local variables. | |
232 ;; | |
233 (let (sexpr context-buffer recover-file-name) | |
234 (setq recover-file-name (concat (original-working-directory) | |
235 ".emacs_" (user-login-name))) | |
236 (if (not (file-readable-p recover-file-name)) | |
237 (error "can't access context, %s" recover-file-name)) | |
238 ;; | |
239 ;; create a temp buffer and copy the saved context into it. | |
240 ;; | |
241 (setq context-buffer (get-buffer-create " *Recovered Context*")) | |
242 (set-buffer context-buffer) | |
243 (erase-buffer) | |
244 (insert-file-contents recover-file-name nil) | |
245 ;; so kill-buffer won't need confirmation later | |
246 (set-buffer-modified-p nil) | |
247 ;; | |
248 ;; If it's empty forget it. | |
249 ;; | |
250 (if (zerop (buffer-size)) | |
251 (error "context file is empty, %s" recover-file-name)) | |
252 ;; | |
253 ;; check the version and make sure it matches ours | |
254 ;; | |
255 (setq sexpr (read context-buffer)) | |
256 (if (not (equal sexpr save-context-version)) | |
257 (error "version string incorrect, %s" sexpr)) | |
258 ;; | |
259 ;; Recover the window contexts | |
260 ;; | |
261 (while (setq sexpr (read context-buffer)) | |
262 (select-window (get-largest-window)) | |
263 (if (buffer-file-name) | |
264 (split-window)) | |
265 (other-window 1) | |
266 (find-file sexpr) | |
267 (goto-char (read context-buffer))) | |
268 ;; | |
269 ;; Recover buffer contexts, if any. | |
270 ;; | |
271 (while (setq sexpr (read context-buffer)) | |
272 (set-buffer (find-file-noselect sexpr)) | |
273 (goto-char (read context-buffer))) | |
274 (bury-buffer "*scratch*") | |
275 (kill-buffer context-buffer) | |
276 t ) | |
277 (error nil))) | |
278 | |
279 (defun original-working-directory () | |
280 (save-excursion | |
281 (set-buffer (get-buffer-create "*scratch*")) | |
282 default-directory)) |