comparison lisp/desktop.el @ 5465:9fcfca1caec7

(desktop-buffer-mh): New function for mh mail system. (desktop-buffer-handlers): Add desktop-buffer-mh. (desktop-buffer): Correct setting of auto-fill-mode. Make the compilation silent using (eval-when-compile ...) (old-kill-emacs): New explicit variable (for Emacs 18 comp.) (desktop-globals-to-save): Add the history rings for interactive searches. (postv18): Remove. (desktop-create-buffer-form): New variable. (desktop-save): Use desktop-create-buffer-form. (desktop-value-to-string): New function. (desktop-outvar): Clean-up using desktop-value-to-string. (desktop-save): clean-up Using desktop-value-to-string. (desktop-save): Decide Emacs version at compile time. (desktop-locals-to-save): New variable. (desktop-truncate): New function.
author Richard M. Stallman <rms@gnu.org>
date Thu, 06 Jan 1994 11:34:51 +0000
parents e65e125e5334
children 913f27480fad
comparison
equal deleted inserted replaced
5464:4823e14b1314 5465:9fcfca1caec7
1 ;;; desktop.el --- save partial status of Emacs when killed 1 ;;; desktop.el --- save partial status of Emacs when killed
2 2
3 ;; Copyright (C) 1993 Free Software Foundation, Inc. 3 ;; Copyright (C) 1993 Free Software Foundation, Inc.
4 4
5 ;; Author: Morten Welinder <terra@diku.dk> 5 ;; Author: Morten Welinder <terra@diku.dk>
6 ;; Version: 2.03 6 ;; Version: 2.05
7 ;; Keywords: customization 7 ;; Keywords: customization
8 ;; Favourite-brand-of-beer: None, I hate beer. 8 ;; Favourite-brand-of-beer: None, I hate beer.
9 9
10 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
11 11
31 ;; - the major mode 31 ;; - the major mode
32 ;; - the default directory 32 ;; - the default directory
33 ;; - the point 33 ;; - the point
34 ;; - the mark & mark-active 34 ;; - the mark & mark-active
35 ;; - buffer-read-only 35 ;; - buffer-read-only
36 ;; - truncate-lines 36 ;; - some local variables
37 ;; - case-fold-search
38 ;; - case-replace
39 ;; - fill-column
40 37
41 ;; To use this, first put these three lines in the bottom of your .emacs 38 ;; To use this, first put these three lines in the bottom of your .emacs
42 ;; file (the later the better): 39 ;; file (the later the better):
43 ;; 40 ;;
44 ;; (load "desktop") 41 ;; (load "desktop")
45 ;; (desktop-load-default) 42 ;; (desktop-load-default)
46 ;; (desktop-read) 43 ;; (desktop-read)
47 ;; 44 ;;
45 ;; Between the second and the third line you may wish to add something that
46 ;; updates the variables `desktop-globals-to-save' and/or
47 ;; `desktop-locals-to-save'. If for instance you want to save the local
48 ;; variable `foobar' for every buffer in which it is local, you could add
49 ;; the line
50 ;;
51 ;; (setq desktop-locals-to-save (cons 'foobar desktop-locals-to-save))
52 ;;
53 ;; To avoid saving excessive amounts of data you may also with to add
54 ;; something like the following
55 ;;
56 ;; (add-hook 'kill-emacs-hook
57 ;; '(lambda ()
58 ;; (desktop-truncate search-ring 3)
59 ;; (desktop-truncate regexp-search-ring 3)))
60 ;;
61 ;; which will make sure that no more than three search items are saved. You
62 ;; must place this line *after* the (load "desktop") line.
48 63
49 ;; Start Emacs in the root directory of your "project". The desktop saver 64 ;; Start Emacs in the root directory of your "project". The desktop saver
50 ;; is inactive by default. You activate it by M-x desktop-save RET. When 65 ;; is inactive by default. You activate it by M-x desktop-save RET. When
51 ;; you exit the next time the above data will be saved. This ensures that 66 ;; you exit the next time the above data will be saved. This ensures that
52 ;; all the files you were editing will be reloaded the next time you start 67 ;; all the files you were editing will be reloaded the next time you start
53 ;; Emacs from the same directory and that points will be set where you 68 ;; Emacs from the same directory and that points will be set where you
54 ;; left them. 69 ;; left them. If you save a desktop file in your home directory it will
55 ;; 70 ;; act as a default desktop when you start Emacs from a directory that
71 ;; doesn't have its own. I never do this, but you may want to.
72
73 ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
74 ;; in your home directory is used for that. Saving global default values
75 ;; for buffers is an example of misuse.
76
56 ;; PLEASE NOTE: The kill ring can be saved as specified by the variable 77 ;; PLEASE NOTE: The kill ring can be saved as specified by the variable
57 ;; `desktop-globals-to-save' (by default it isn't). This may result in saving 78 ;; `desktop-globals-to-save' (by default it isn't). This may result in saving
58 ;; things you did not mean to keep. Use M-x desktop-clear RET. 79 ;; things you did not mean to keep. Use M-x desktop-clear RET.
59 ;; 80
60 ;; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas. 81 ;; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas.
61 ;; avk@rtsg.mot.com (Andrew V. Klein) for a dired tip. 82 ;; avk@rtsg.mot.com (Andrew V. Klein) for a dired tip.
62 ;; chris@tecc.co.uk (Chris Boucher) for a mark tip. 83 ;; chris@tecc.co.uk (Chris Boucher) for a mark tip.
84 ;; f89-kam@nada.kth.se (Klas Mellbourn) for a mh-e tip.
63 ;; --------------------------------------------------------------------------- 85 ;; ---------------------------------------------------------------------------
64 ;; TODO: 86 ;; TODO:
65 ;; 87 ;;
66 ;; Save window configuration. 88 ;; Save window configuration.
67 ;; Recognize more minor modes. 89 ;; Recognize more minor modes.
68 ;; Save mark rings. 90 ;; Save mark rings.
69 ;; Start-up with buffer-menu??? 91 ;; Start-up with buffer-menu???
70 92
71 ;;; Code: 93 ;;; Code:
72 94
95 ;; Make the compilation more silent
96 (eval-when-compile
97 ;; We use functions from these modules
98 (mapcar 'require '(info mh-e dired))
99 ;; We handle auto-fill-hook in a way that is ok.
100 (put 'auto-fill-hook 'byte-obsolete-variable nil)
101 ;; Some things are different in version 18.
102 (setq postv18 (string-lessp "19" emacs-version)))
103 ;; ----------------------------------------------------------------------------
73 ;; USER OPTIONS -- settings you might want to play with. 104 ;; USER OPTIONS -- settings you might want to play with.
74 ;; ---------------------------------------------------------------------------- 105 ;; ----------------------------------------------------------------------------
75 (defconst desktop-basefilename 106 (defconst desktop-basefilename
76 (if (equal system-type 'ms-dos) 107 (if (equal system-type 'ms-dos)
77 "emacs.dsk" ; Ms-Dos does not support multiple dots in file name 108 "emacs.dsk" ; Ms-Dos does not support multiple dots in file name
83 Otherwise simply ignore the file.") 114 Otherwise simply ignore the file.")
84 115
85 (defvar desktop-globals-to-save 116 (defvar desktop-globals-to-save
86 (list 'desktop-missing-file-warning 117 (list 'desktop-missing-file-warning
87 ;; Feature: saving kill-ring implies saving kill-ring-yank-pointer 118 ;; Feature: saving kill-ring implies saving kill-ring-yank-pointer
88 ;; 'kill-ring 119 ;; 'kill-ring
89 'tags-file-name 120 'tags-file-name
90 'tags-table-list 121 'tags-table-list
122 'search-ring
123 'regexp-search-ring
91 ;; 'desktop-globals-to-save ; Itself! 124 ;; 'desktop-globals-to-save ; Itself!
92 ) 125 )
93 "List of global variables to save when killing Emacs.") 126 "List of global variables to save when killing Emacs.")
127
128 (defvar desktop-locals-to-save
129 (list 'desktop-locals-to-save ; Itself! Think it over.
130 'truncate-lines
131 'case-fold-search
132 'case-replace
133 'fill-column
134 'overwrite-mode
135 'change-log-default-name
136 )
137 "List of local variables to save for each buffer. The variables are saved
138 only when they really are local.")
94 139
95 ;; We skip .log files because they are normally temporary. 140 ;; We skip .log files because they are normally temporary.
96 ;; (ftp) files because they require passwords and whatsnot. 141 ;; (ftp) files because they require passwords and whatsnot.
97 ;; TAGS files to save time (tags-file-name is saved instead). 142 ;; TAGS files to save time (tags-file-name is saved instead).
98 (defvar desktop-buffers-not-to-save 143 (defvar desktop-buffers-not-to-save
100 "Regexp identifying buffers that are to be excluded from saving.") 145 "Regexp identifying buffers that are to be excluded from saving.")
101 146
102 (defvar desktop-buffer-handlers 147 (defvar desktop-buffer-handlers
103 '(desktop-buffer-dired 148 '(desktop-buffer-dired
104 desktop-buffer-rmail 149 desktop-buffer-rmail
150 desktop-buffer-mh
105 desktop-buffer-info 151 desktop-buffer-info
106 desktop-buffer-file) 152 desktop-buffer-file)
107 "*List of functions to call in order to create a buffer. The functions are 153 "*List of functions to call in order to create a buffer. The functions are
108 called without explicit parameters but may access the the major mode as `mam', 154 called without explicit parameters but may access the the major mode as `mam',
109 the file name as `fn', the buffer name as `bn', the default directory as 155 the file name as `fn', the buffer name as `bn', the default directory as
110 `dd'. If some function returns non-nil no further functions are called. 156 `dd'. If some function returns non-nil no further functions are called.
111 If the function returns t then the buffer is considered created.") 157 If the function returns t then the buffer is considered created.")
158
159 (defvar desktop-create-buffer-form "(desktop-create-buffer 205"
160 "Opening of form for creation of new buffers.")
112 ;; ---------------------------------------------------------------------------- 161 ;; ----------------------------------------------------------------------------
113 (defvar desktop-dirname nil 162 (defvar desktop-dirname nil
114 "The directory in which the current desktop file resides.") 163 "The directory in which the current desktop file resides.")
115 164
116 (defconst desktop-header 165 (defconst desktop-header
117 ";; -------------------------------------------------------------------------- 166 ";; --------------------------------------------------------------------------
118 ;; Desktop File for Emacs 167 ;; Desktop File for Emacs
119 ;; -------------------------------------------------------------------------- 168 ;; --------------------------------------------------------------------------
120 " "*Header to place in Desktop file.") 169 " "*Header to place in Desktop file.")
121 ;; ---------------------------------------------------------------------------- 170 ;; ----------------------------------------------------------------------------
122 (defconst postv18 171 (defun desktop-truncate (l n)
123 (string-lessp "19" emacs-version) 172 "Truncate LIST to at most N elements destructively."
124 "t if Emacs version 19 or later.") 173 (let ((here (nthcdr (1- n) l)))
125 174 (if (consp here)
175 (setcdr here nil))))
176 ;; ----------------------------------------------------------------------------
126 (defun desktop-clear () "Empty the Desktop." 177 (defun desktop-clear () "Empty the Desktop."
127 (interactive) 178 (interactive)
128 (setq kill-ring nil) 179 (setq kill-ring nil)
129 (setq kill-ring-yank-pointer nil) 180 (setq kill-ring-yank-pointer nil)
130 (mapcar (function kill-buffer) (buffer-list)) 181 (mapcar (function kill-buffer) (buffer-list))
131 (delete-other-windows)) 182 (delete-other-windows))
132 ;; ---------------------------------------------------------------------------- 183 ;; ----------------------------------------------------------------------------
133 ;; This is a bit dirty for version 18 because that version of Emacs was not 184 ;; This is a bit dirty for version 18 because that version of Emacs was not
134 ;; toilet-trained considering hooks. 185 ;; toilet-trained considering hooks.
135 (if (not (boundp 'desktop-kill)) 186 (defvar old-kill-emacs)
136 (if postv18 187
137 (add-hook 'kill-emacs-hook 'desktop-kill) 188 (if (eval-when-compile postv18)
138 (setq old-kill-emacs kill-emacs-hook) 189 (add-hook 'kill-emacs-hook 'desktop-kill)
139 (setq kill-emacs-hook 190 (if (not (boundp 'desktop-kill))
191 (setq old-kill-emacs kill-emacs-hook
192 kill-emacs-hook
140 (function (lambda () 193 (function (lambda ()
141 (progn (desktop-kill) 194 (progn (desktop-kill)
142 (if (or (null old-kill-emacs) 195 (if (or (null old-kill-emacs)
143 (symbolp old-kill-emacs)) 196 (symbolp old-kill-emacs))
144 (run-hooks old-kill-emacs) 197 (run-hooks old-kill-emacs)
147 (defun desktop-kill () 200 (defun desktop-kill ()
148 (if desktop-dirname 201 (if desktop-dirname
149 (progn 202 (progn
150 (desktop-save desktop-dirname)))) 203 (desktop-save desktop-dirname))))
151 ;; ---------------------------------------------------------------------------- 204 ;; ----------------------------------------------------------------------------
205 (defun desktop-value-to-string (val)
206 (let ((print-escape-newlines t))
207 (concat
208 ;; symbols are needed for cons cells and for symbols except
209 ;; `t' and `nil'.
210 (if (or (consp val)
211 (and (symbolp val) val (not (eq t val))))
212 "'"
213 "")
214 (prin1-to-string val))))
215 ;; ----------------------------------------------------------------------------
152 (defun desktop-outvar (var) 216 (defun desktop-outvar (var)
153 "Output a setq statement for VAR to the desktop file." 217 "Output a setq statement for VAR to the desktop file."
154 (if (boundp var) 218 (if (boundp var)
155 (let ((print-escape-newlines t) 219 (insert "(setq "
156 (val (symbol-value var))) 220 (symbol-name var)
157 (insert "(setq ") 221 " "
158 (prin1 var (current-buffer)) 222 (desktop-value-to-string (symbol-value var))
159 ;; symbols are needed for cons cells and for symbols except 223 ")\n")))
160 ;; `t' and `nil'. 224 ;; ----------------------------------------------------------------------------
161 (if (or (consp val) 225 (defun desktop-save-buffer-p (filename bufname mode &rest dummy)
162 (and (symbolp val) val (not (eq t val))))
163 (insert " '")
164 (insert " "))
165 (prin1 val (current-buffer))
166 (insert ")\n"))))
167 ;; ----------------------------------------------------------------------------
168 (defun desktop-save-buffer-p (filename bufname mode)
169 "Return t if the desktop should record a particular buffer for next startup. 226 "Return t if the desktop should record a particular buffer for next startup.
170 FILENAME is the visited file name, BUFNAME is the buffer name, and 227 FILENAME is the visited file name, BUFNAME is the buffer name, and
171 MODE is the major mode." 228 MODE is the major mode."
172 (or (and filename 229 (or (and filename
173 (not (string-match desktop-buffers-not-to-save bufname))) 230 (not (string-match desktop-buffers-not-to-save bufname)))
185 (function (lambda (b) 242 (function (lambda (b)
186 (set-buffer b) 243 (set-buffer b)
187 (list 244 (list
188 (buffer-file-name) 245 (buffer-file-name)
189 (buffer-name) 246 (buffer-name)
190 (list 'quote major-mode) 247 major-mode
191 (list 'quote 248 (list ; list explaining minor modes
192 (list overwrite-mode 249 (not (null
193 (not (null 250 (if (eval-when-compile postv18)
194 (if postv18 251 auto-fill-function
195 auto-fill-function 252 auto-fill-hook))))
196 auto-fill-hook)))))
197 (point) 253 (point)
198 (if postv18 254 (if (eval-when-compile postv18)
199 (list 'quote (list (mark t) mark-active)) 255 (list (mark t) mark-active)
200 (mark)) 256 (mark))
201 buffer-read-only 257 buffer-read-only
202 truncate-lines 258 (cond ((eq major-mode 'Info-mode)
203 fill-column 259 (list Info-current-file
204 case-fold-search 260 Info-current-node))
205 case-replace 261 ((eq major-mode 'dired-mode)
206 (list 262 (if (eval-when-compile postv18)
207 'quote 263 (nreverse
208 (cond ((equal major-mode 'Info-mode) 264 (mapcar
209 (list Info-current-file 265 (function car)
210 Info-current-node)) 266 dired-subdir-alist))
211 ((equal major-mode 'dired-mode) 267 (list default-directory)))
212 (if postv18 268 )
213 (nreverse 269 (let ((locals desktop-locals-to-save)
214 (mapcar 270 (loclist (buffer-local-variables))
215 (function car) 271 (ll))
216 dired-subdir-alist)) 272 (while locals
217 (list default-directory))) 273 (let ((here (assq (car locals) loclist)))
218 )) 274 (if here
275 (setq ll (cons here ll))
276 (if (member (car locals) loclist)
277 (setq ll (cons (car locals) ll)))))
278 (setq locals (cdr locals)))
279 ll)
219 ))) 280 )))
220 (buffer-list)))) 281 (buffer-list))))
221 (buf (get-buffer-create "*desktop*"))) 282 (buf (get-buffer-create "*desktop*")))
222 (set-buffer buf) 283 (set-buffer buf)
223 (erase-buffer) 284 (erase-buffer)
235 296
236 (insert "\n;; Buffer section:\n") 297 (insert "\n;; Buffer section:\n")
237 (let ((print-escape-newlines t)) 298 (let ((print-escape-newlines t))
238 (mapcar 299 (mapcar
239 (function (lambda (l) 300 (function (lambda (l)
240 (if (desktop-save-buffer-p 301 (if (apply 'desktop-save-buffer-p l)
241 (car l)
242 (nth 1 l)
243 (nth 1 (nth 2 l)))
244 (progn 302 (progn
245 (insert "(desktop-buffer") 303 (insert desktop-create-buffer-form)
246 (mapcar 304 (mapcar
247 (function (lambda (e) 305 (function (lambda (e)
248 (insert "\n ") 306 (insert "\n "
249 (prin1 e (current-buffer)))) 307 (desktop-value-to-string e))))
250 l) 308 l)
251 (insert ")\n\n"))))) 309 (insert ")\n\n")))))
252 info)) 310 info))
253 (setq default-directory dirname) 311 (setq default-directory dirname)
254 (if (file-exists-p filename) (delete-file filename)) 312 (if (file-exists-p filename) (delete-file filename))
278 (message "Desktop loaded.")) 336 (message "Desktop loaded."))
279 (desktop-clear)))) 337 (desktop-clear))))
280 ;; ---------------------------------------------------------------------------- 338 ;; ----------------------------------------------------------------------------
281 (defun desktop-load-default () 339 (defun desktop-load-default ()
282 "Load the `default' start-up library manually. Also inhibit further loading 340 "Load the `default' start-up library manually. Also inhibit further loading
283 of it. Call this from your `.emacs' file to provide correct modes for 341 of it. Call this from your `.emacs' file to provide correct modes for
284 autoloaded files." 342 autoloaded files."
285 (if (not inhibit-default-init) ; safety check 343 (if (not inhibit-default-init) ; safety check
286 (progn 344 (progn
287 (load "default" t t) 345 (load "default" t t)
288 (setq inhibit-default-init t)))) 346 (setq inhibit-default-init t))))
289 ;; ---------------------------------------------------------------------------- 347 ;; ----------------------------------------------------------------------------
290 ;; Note: the following functions use the dynamic variable binding in Lisp. 348 ;; Note: the following functions use the dynamic variable binding in Lisp.
291 ;; The byte compiler may therefore complain of undeclared variables.
292 ;; 349 ;;
293 (defun desktop-buffer-info () "Load an info file." 350 (defun desktop-buffer-info () "Load an info file."
294 (if (equal 'Info-mode mam) 351 (if (eq 'Info-mode mam)
295 (progn 352 (progn
296 (require 'info) 353 (require 'info)
297 (Info-find-node (nth 0 misc) (nth 1 misc)) 354 (Info-find-node (nth 0 misc) (nth 1 misc))
298 t))) 355 t)))
299 ;; ---------------------------------------------------------------------------- 356 ;; ----------------------------------------------------------------------------
300 (defun desktop-buffer-rmail () "Load an RMAIL file." 357 (defun desktop-buffer-rmail () "Load an RMAIL file."
301 (if (eq 'rmail-mode mam) 358 (if (eq 'rmail-mode mam)
302 (progn (rmail-input fn) t))) 359 (progn (rmail-input fn) t)))
360 ;; ----------------------------------------------------------------------------
361 (defun desktop-buffer-mh () "Load a folder in the mh system."
362 (if (eq 'mh-folder-mode mam)
363 (progn
364 (require 'mh-e)
365 (mh-find-path)
366 (mh-visit-folder bn)
367 t)))
303 ;; ---------------------------------------------------------------------------- 368 ;; ----------------------------------------------------------------------------
304 (defun desktop-buffer-dired () "Load a directory using dired." 369 (defun desktop-buffer-dired () "Load a directory using dired."
305 (if (eq 'dired-mode mam) 370 (if (eq 'dired-mode mam)
306 (progn 371 (progn
307 (dired (car misc)) 372 (dired (car misc))
318 (progn (find-file fn) t) 383 (progn (find-file fn) t)
319 'ignored))) 384 'ignored)))
320 ;; ---------------------------------------------------------------------------- 385 ;; ----------------------------------------------------------------------------
321 ;; Create a buffer, load its file, set is mode, ...; called from Desktop file 386 ;; Create a buffer, load its file, set is mode, ...; called from Desktop file
322 ;; only. 387 ;; only.
323 (defun desktop-buffer (fn bn mam mim pt mk ro tl fc cfs cr misc) 388 (defun desktop-create-buffer (ver fn bn mam mim pt mk ro misc &optional locals)
324 (let ((hlist desktop-buffer-handlers) 389 (let ((hlist desktop-buffer-handlers)
325 (result) 390 (result)
326 (handler)) 391 (handler))
327 (while (and (not result) hlist) 392 (while (and (not result) hlist)
328 (setq handler (car hlist)) 393 (setq handler (car hlist))
330 (setq hlist (cdr hlist))) 395 (setq hlist (cdr hlist)))
331 (if (eq result t) 396 (if (eq result t)
332 (progn 397 (progn
333 (if (not (equal (buffer-name) bn)) 398 (if (not (equal (buffer-name) bn))
334 (rename-buffer bn)) 399 (rename-buffer bn))
335 (if (nth 0 mim) 400 (auto-fill-mode (if (nth 0 mim) 1 0))
336 (overwrite-mode 1)
337 (overwrite-mode 0))
338 (if (nth 1 mim)
339 (auto-fill-mode 1)
340 (overwrite-mode 0))
341 (goto-char pt) 401 (goto-char pt)
342 (if (consp mk) 402 (if (consp mk)
343 (progn 403 (progn
344 (set-mark (car mk)) 404 (set-mark (car mk))
345 (setq mark-active (car (cdr mk)))) 405 (setq mark-active (car (cdr mk))))
346 (set-mark mk)) 406 (set-mark mk))
347 ;; Never override file system if the file really is read-only marked. 407 ;; Never override file system if the file really is read-only marked.
348 (if ro (setq buffer-read-only ro)) 408 (if ro (setq buffer-read-only ro))
349 (setq truncate-lines tl) 409 (while locals
350 (setq fill-column fc) 410 (let ((this (car locals)))
351 (setq case-fold-search cfs) 411 (if (consp this)
352 (setq case-replace cr) 412 ;; an entry of this form `(symbol . value)'
413 (progn
414 (make-local-variable (car this))
415 (set (car this) (cdr this)))
416 ;; an entry of the form `symbol'
417 (make-local-variable this)
418 (makunbound this)))
419 (setq locals (cdr locals)))
353 )))) 420 ))))
421
422 ;; Backward compatibility -- update parameters to 205 standards.
423 (defun desktop-buffer (fn bn mam mim pt mk ro tl fc cfs cr misc)
424 (desktop-create-buffer 205 fn bn mam (cdr mim) pt mk ro misc
425 (list (cons 'truncate-lines tl)
426 (cons 'fill-column fc)
427 (cons 'case-fold-search cfs)
428 (cons 'case-replace cr)
429 (cons 'overwrite-mode (car mim)))))
354 ;; ---------------------------------------------------------------------------- 430 ;; ----------------------------------------------------------------------------
355 (provide 'desktop) 431 (provide 'desktop)
356 432
357 ;; desktop.el ends here. 433 ;; desktop.el ends here.