Mercurial > emacs
comparison lisp/desktop.el @ 3404:777e0d4f775a
Initial revision
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Tue, 01 Jun 1993 20:09:25 +0000 |
parents | |
children | b48f023e8e29 |
comparison
equal
deleted
inserted
replaced
3403:4151b7a0e415 | 3404:777e0d4f775a |
---|---|
1 ;;; desktop.el --- save partial status of Emacs when killed | |
2 | |
3 ;; Copyright (C) 1993 Free Software Foundation, Inc. | |
4 | |
5 ;; Author: Morten Welinder <terra@diku.dk> | |
6 ;; Version: 2.01 | |
7 | |
8 ;; This file is part of GNU Emacs. | |
9 | |
10 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
11 ;; it under the terms of the GNU General Public License as published by | |
12 ;; the Free Software Foundation; either version 2, or (at your option) | |
13 ;; any later version. | |
14 | |
15 ;; GNU Emacs is distributed in the hope that it will be useful, | |
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 ;; GNU General Public License for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
21 ;; along with GNU Emacs; see the file COPYING. If not, write to | |
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
23 | |
24 ;;; Commentary: | |
25 | |
26 ; Save the Desktop, i.e., | |
27 ; - some global variables | |
28 ; - the list of buffers with associated files. For each buffer also | |
29 ; - the major mode | |
30 ; - the default directory | |
31 ; - the point | |
32 ; - the mark | |
33 ; - buffer-read-only | |
34 ; - truncate-lines | |
35 ; - case-fold-search | |
36 ; - case-replace | |
37 ; - fill-column | |
38 | |
39 ; To use this, first put these three lines in the bottom of your .emacs | |
40 ; file (the later the better): | |
41 ; | |
42 ; (load "desktop") | |
43 ; (desktop-load-default) | |
44 ; (desktop-read) | |
45 ; | |
46 | |
47 ; Start Emacs in the root directory of your "project". The desktop saver | |
48 ; is inactive by default. You activate it by M-X desktop-save RET. When | |
49 ; you exit the next time the above data will be saved. This ensures that | |
50 ; all the files you were editing will be reloaded the next time you start | |
51 ; Emacs from the same directory and that points will be set where you | |
52 ; left them. | |
53 ; | |
54 ; PLEASE NOTE: When the kill ring is saved as specified by the variable | |
55 ; `desktop-globals-to-save' (by default it isn't). This may result in saving | |
56 ; things you did not mean to keep. Use M-X desktop-clear RET. | |
57 ; | |
58 ; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas. | |
59 ; --------------------------------------------------------------------------- | |
60 ; HISTORY: | |
61 ; | |
62 ; Dec , 1992: Version 1.0 written; never released. | |
63 ; Jan , 1993: Minor modes now saved: auto-fill-mode, overwrite-mode. | |
64 ; Apr 26, 1993: Version 1.1 released. | |
65 ; Apr 29, 1993: Now supports RMAIL, Info, and dired modes. | |
66 ; Will now search home directory for desktop file. | |
67 ; desktop-save asks for directory to save in. | |
68 ; May 31, 1993: Version 1.3 | |
69 ; Now works with Emacs 19. | |
70 ; Jun 1, 1993: Minor bug fix. | |
71 ; | |
72 ; TODO: | |
73 ; | |
74 ; Save window configuration. | |
75 ; Recognize more minor modes. | |
76 ; Save mark rings. | |
77 ; Start-up with buffer-menu??? | |
78 | |
79 ;;; Code: | |
80 | |
81 ; USER OPTIONS -- settings you might want to play with. | |
82 ; ----------------------------------------------------------------------------- | |
83 (defconst desktop-basefilename | |
84 (if (equal system-type 'ms-dos) | |
85 "emacs.dsk" ; Ms-Dos does not support multiple dots in file name | |
86 ".emacs.desktop") | |
87 "File for Emacs desktop. A directory name will be prepended to this name.") | |
88 | |
89 (defvar desktop-missing-file-warning t | |
90 "*If non-nil then issue warning if a file no longer exists. | |
91 Otherwise simply ignore the file.") | |
92 | |
93 (defvar desktop-globals-to-save | |
94 (list 'desktop-missing-file-warning | |
95 ; 'kill-ring ; Feature: Also saves kill-ring-yank-pointer | |
96 'desktop-globals-to-save) ; Itself! | |
97 "List of global variables to save when killing Emacs.") | |
98 | |
99 (defvar desktop-buffers-not-to-save | |
100 "\\(\\.log\\|(ftp)\\)$" | |
101 "Regexp identifying buffers that are to be excluded from saving.") | |
102 | |
103 (defvar desktop-buffer-handlers | |
104 '(desktop-buffer-dired | |
105 desktop-buffer-rmail | |
106 desktop-buffer-info | |
107 desktop-buffer-file) | |
108 "*List of functions to call in order to create a buffer. | |
109 The functions are called without parameters | |
110 but may access the the major mode as `mam', | |
111 the file name as `fn', the buffer name as `bn', the default directory as | |
112 `dd'. If some function returns non-nil no further functions are called. | |
113 If the function returns t then the buffer is considered created.") | |
114 ; --------------------------------------------------------------------------- | |
115 (defvar desktop-dirname nil | |
116 "The directory in which the current desktop file resides.") | |
117 | |
118 (defconst desktop-header | |
119 "; --------------------------------------------------------------------------- | |
120 ; Desktop File for Emacs | |
121 ; --------------------------------------------------------------------------- | |
122 " "*Header to place in Desktop file.") | |
123 ; --------------------------------------------------------------------------- | |
124 (defconst postv18 | |
125 (string-lessp "19" emacs-version) | |
126 "t is Emacs version 19 or later.") | |
127 | |
128 (defun desktop-clear () "Empty the Desktop." | |
129 (interactive) | |
130 (setq kill-ring nil) | |
131 (setq kill-ring-yank-pointer nil) | |
132 (mapcar (function kill-buffer) (buffer-list))) | |
133 ; --------------------------------------------------------------------------- | |
134 (if (not (boundp 'desktop-kill)) | |
135 (if postv18 | |
136 (add-hook 'kill-emacs-hook 'desktop-kill) | |
137 (setq old-kill-emacs kill-emacs-hook) | |
138 (setq kill-emacs-hook | |
139 (function (lambda () (progn (desktop-kill) | |
140 (run-hooks old-kill-emacs))))))) | |
141 ; --------------------------------------------------------------------------- | |
142 (defun desktop-kill () | |
143 (if desktop-dirname | |
144 (progn | |
145 (desktop-save desktop-dirname)))) | |
146 | |
147 ;(defun kill-emacs (&optional query) | |
148 ; "End this Emacs session. | |
149 ;Prefix ARG or optional first ARG non-nil means exit with no questions asked, | |
150 ;even if there are unsaved buffers. If Emacs is running non-interactively | |
151 ;and ARG is an integer, then Emacs exits with ARG as its exit code. | |
152 ; | |
153 ;If the variable `desktop-dirname' is non-nil, | |
154 ;the function desktop-save will be called first." | |
155 ; (interactive "P") | |
156 ; (if desktop-dirname (desktop-save desktop-dirname)) | |
157 ; (original-kill-emacs query)) | |
158 ; --------------------------------------------------------------------------- | |
159 (defun desktop-outvar (VAR) | |
160 "Output a setq statement for VAR to the desktop file." | |
161 (if (boundp VAR) | |
162 (progn | |
163 (insert "(setq ") | |
164 (prin1 VAR (current-buffer)) | |
165 (insert " '") | |
166 (prin1 (symbol-value VAR) (current-buffer)) | |
167 (insert ")\n")))) | |
168 ; --------------------------------------------------------------------------- | |
169 (defun desktop-save-buffer-p (filename bufname mode) | |
170 "Return t if should record a particular buffer for next startup. | |
171 FILENAME is the visited file name, BUFNAME is the buffer name, and | |
172 MODE is the major mode." | |
173 | |
174 (or (and filename | |
175 (not (string-match desktop-buffers-not-to-save bufname))) | |
176 (and (null filename) | |
177 (memq mode '(Info-mode dired-mode rmail-mode))))) | |
178 ; --------------------------------------------------------------------------- | |
179 (defun desktop-save (dirname) | |
180 "Save the Desktop file. Parameter DIRNAME specifies where to save desktop." | |
181 (interactive "DDirectory to save desktop file in: ") | |
182 (save-excursion | |
183 (let ((filename (expand-file-name | |
184 (concat dirname desktop-basefilename))) | |
185 (info (nreverse | |
186 (mapcar | |
187 (function (lambda (b) | |
188 (set-buffer b) | |
189 (list | |
190 (buffer-file-name) | |
191 (buffer-name) | |
192 (list 'quote major-mode) | |
193 (list 'quote | |
194 (list overwrite-mode | |
195 (not (null | |
196 (if postv18 | |
197 auto-fill-function | |
198 auto-fill-hook))))) | |
199 (point) | |
200 (if postv18 | |
201 (mark t) | |
202 (mark)) | |
203 buffer-read-only | |
204 truncate-lines | |
205 fill-column | |
206 case-fold-search | |
207 case-replace | |
208 (list | |
209 'quote | |
210 (cond ((equal major-mode 'Info-mode) | |
211 (list Info-current-file | |
212 Info-current-node)) | |
213 ((equal major-mode 'dired-mode) | |
214 (list default-directory)) | |
215 )) | |
216 ))) | |
217 (buffer-list)))) | |
218 (buf (get-buffer-create "*desktop*"))) | |
219 (set-buffer buf) | |
220 (erase-buffer) | |
221 | |
222 (insert desktop-header | |
223 "; Created " (current-time-string) "\n" | |
224 "; Emacs version " emacs-version "\n\n" | |
225 "; Global section:\n") | |
226 (mapcar (function desktop-outvar) desktop-globals-to-save) | |
227 (if (memq 'kill-ring desktop-globals-to-save) | |
228 (insert "(setq kill-ring-yank-pointer (nthcdr " | |
229 (int-to-string | |
230 (- (length kill-ring) (length kill-ring-yank-pointer))) | |
231 " kill-ring))\n")) | |
232 | |
233 (insert "\n; Buffer section:\n") | |
234 (mapcar | |
235 (function (lambda (l) | |
236 (if (desktop-save-buffer-p | |
237 (car l) | |
238 (nth 1 l) | |
239 (nth 1 (nth 2 l))) | |
240 (progn | |
241 (insert "(desktop-buffer") | |
242 (mapcar | |
243 (function (lambda (e) | |
244 (insert "\n ") | |
245 (prin1 e (current-buffer)))) | |
246 l) | |
247 (insert ")\n\n"))))) | |
248 info) | |
249 (setq default-directory dirname) | |
250 (if (file-exists-p filename) (delete-file filename)) | |
251 (write-region (point-min) (point-max) filename nil 'nomessage))) | |
252 (setq desktop-dirname dirname)) | |
253 ; --------------------------------------------------------------------------- | |
254 (defun desktop-remove () | |
255 "Delete the Desktop file and inactivate the desktop system." | |
256 (interactive) | |
257 (if desktop-dirname | |
258 (let ((filename (concat desktop-dirname desktop-basefilename))) | |
259 (if (file-exists-p filename) (delete-file filename)) | |
260 (setq desktop-dirname nil)))) | |
261 ; --------------------------------------------------------------------------- | |
262 (defun desktop-read () | |
263 "Read the Desktop file and the files it specifies." | |
264 (interactive) | |
265 (let ((filename)) | |
266 (if (file-exists-p (concat "./" desktop-basefilename)) | |
267 (setq desktop-dirname (expand-file-name "./")) | |
268 (if (file-exists-p (concat "~/" desktop-basefilename)) | |
269 (setq desktop-dirname (expand-file-name "~/")) | |
270 (setq desktop-dirname nil))) | |
271 (if desktop-dirname | |
272 (progn | |
273 (load (concat desktop-dirname desktop-basefilename) t t t) | |
274 (message "Desktop loaded.")) | |
275 (desktop-clear)))) | |
276 ; --------------------------------------------------------------------------- | |
277 (defun desktop-load-default () | |
278 "Load the `default' start-up library manually. | |
279 Also inhibit further loading of it. | |
280 Call this from your `.emacs' file | |
281 provide correct modes for autoloaded files." | |
282 (if (not inhibit-default-init) | |
283 (progn | |
284 (load "default" t t) | |
285 (setq inhibit-default-init t)))) | |
286 ; --------------------------------------------------------------------------- | |
287 (defun desktop-buffer-info () "Load an info file." | |
288 (if (equal 'Info-mode mam) | |
289 (progn | |
290 (require 'info) | |
291 (Info-find-node (nth 0 misc) (nth 1 misc)) | |
292 t))) | |
293 ; --------------------------------------------------------------------------- | |
294 (defun desktop-buffer-rmail () "Load a RMAIL file." | |
295 (if (equal 'rmail-mode mam) | |
296 (progn (rmail-input fn) t))) | |
297 ; --------------------------------------------------------------------------- | |
298 (defun desktop-buffer-dired () "Load a directory using dired." | |
299 (if (equal 'dired-mode mam) | |
300 (progn (dired (nth 0 misc)) t))) | |
301 ; --------------------------------------------------------------------------- | |
302 (defun desktop-buffer-file () "Load a file." | |
303 (if fn | |
304 (if (or (file-exists-p fn) | |
305 (and desktop-missing-file-warning | |
306 (y-or-n-p (format | |
307 "File \"%s\" no longer exists. Re-create? " | |
308 fn)))) | |
309 (progn (find-file fn) t) | |
310 'ignored))) | |
311 ; --------------------------------------------------------------------------- | |
312 ;;Create a buffer, load its file, set is mode, ...; called from Desktop file | |
313 ;; only. | |
314 (defun desktop-buffer (fn bn mam mim pt mk ro tl fc cfs cr misc) | |
315 (let ((hlist desktop-buffer-handlers) | |
316 (result) | |
317 (handler)) | |
318 (while (and (not result) hlist) | |
319 (setq handler (car hlist)) | |
320 (setq result (funcall handler)) | |
321 (setq hlist (cdr hlist))) | |
322 (if (equal result t) | |
323 (progn | |
324 (if (not (equal (buffer-name) bn)) | |
325 (rename-buffer bn)) | |
326 (if (nth 0 mim) | |
327 (overwrite-mode 1) | |
328 (overwrite-mode 0)) | |
329 (if (nth 1 mim) | |
330 (auto-fill-mode 1) | |
331 (overwrite-mode 0)) | |
332 (goto-char pt) | |
333 (set-mark mk) | |
334 (setq buffer-read-only ro) | |
335 (setq truncate-lines tl) | |
336 (setq fill-column fc) | |
337 (setq case-fold-search cfs) | |
338 (setq case-replace cr) | |
339 )))) | |
340 ; --------------------------------------------------------------------------- | |
341 | |
342 | |
343 | |
344 ;; desktop.el ends here. |