51 |
;; function is added to the `after-init-hook'. This function is |
;; function is added to the `after-init-hook'. This function is |
52 |
;; responsible for loading the desktop when Emacs is started. |
;; responsible for loading the desktop when Emacs is started. |
53 |
|
|
54 |
;; Some words on minor modes: Most minor modes are controlled by |
;; Special handling. |
55 |
;; buffer-local variables, which have a standard save / restore |
;; ----------------- |
56 |
;; mechanism. To handle all minor modes, we take the following |
;; Variables `desktop-buffer-mode-handlers' and `desktop-minor-mode-handlers' |
57 |
;; approach: (1) check whether the variable name from |
;; are supplied to handle special major and minor modes respectively. |
58 |
;; `minor-mode-alist' is also a function; and (2) use translation |
;; `desktop-buffer-mode-handlers' is an alist of major mode specific functions |
59 |
;; table `desktop-minor-mode-table' in the case where the two names |
;; to restore a desktop buffer. Elements must have the form |
60 |
;; are not the same. |
;; |
61 |
|
;; (MAJOR-MODE . RESTORE-BUFFER-FUNCTION). |
62 |
|
;; |
63 |
|
;; Functions listed are called by `desktop-create-buffer' when `desktop-read' |
64 |
|
;; evaluates the desktop file. Buffers with a major mode not specified here, |
65 |
|
;; are restored by the default handler `desktop-restore-file-buffer'. |
66 |
|
;; `desktop-minor-mode-handlers' is an alist of functions to restore |
67 |
|
;; non-standard minor modes. Elements must have the form |
68 |
|
;; |
69 |
|
;; (MINOR-MODE . RESTORE-FUNCTION). |
70 |
|
;; |
71 |
|
;; Functions are called by `desktop-create-buffer' to restore minor modes. |
72 |
|
;; Minor modes not specified here, are restored by the standard minor mode |
73 |
|
;; function. If you write a module that defines a major or minor mode that |
74 |
|
;; needs a special handler, then place code like |
75 |
|
|
76 |
|
;; (defun foo-restore-desktop-buffer |
77 |
|
;; ... |
78 |
|
;; (add-to-list 'desktop-buffer-mode-handlers |
79 |
|
;; '(foo-mode . foo-restore-desktop-buffer)) |
80 |
|
|
81 |
|
;; or |
82 |
|
|
83 |
|
;; (defun bar-desktop-restore |
84 |
|
;; ... |
85 |
|
;; (add-to-list 'desktop-minor-mode-handlers |
86 |
|
;; '(bar-mode . bar-desktop-restore)) |
87 |
|
|
88 |
|
;; in the module itself, and make shure that the mode function is |
89 |
|
;; autoloaded. See the docstrings of `desktop-buffer-mode-handlers' and |
90 |
|
;; `desktop-minor-mode-handlers' for more info. |
91 |
|
|
92 |
|
;; Minor modes. |
93 |
|
;; ------------ |
94 |
|
;; Conventional minor modes (see node "Minor Mode Conventions" in the elisp |
95 |
|
;; manual) are handled in the following way: |
96 |
|
;; When `desktop-save' saves the state of a buffer to the desktop file, it |
97 |
|
;; saves as `desktop-minor-modes' the list of names of those variables in |
98 |
|
;; `minor-mode-alist' that have a non-nil value. |
99 |
|
;; When `desktop-create' restores the buffer, each of the symbols in |
100 |
|
;; `desktop-minor-modes' is called as function with parameter 1. |
101 |
|
;; The variables `desktop-minor-mode-table' and `desktop-minor-mode-handlers' |
102 |
|
;; are used to handle non-conventional minor modes. `desktop-save' uses |
103 |
|
;; `desktop-minor-mode-table' to map minor mode variables to minor mode |
104 |
|
;; functions before writing `desktop-minor-modes'. If a minor mode has a |
105 |
|
;; variable name that is different form its function name, an entry |
106 |
|
|
107 |
|
;; (NAME RESTORE-FUNCTION) |
108 |
|
|
109 |
|
;; should be added to `desktop-minor-mode-table'. If a minor mode should not |
110 |
|
;; be restored, RESTORE-FUNCTION should be set to nil. `desktop-create' uses |
111 |
|
;; `desktop-minor-mode-handlers' to lookup minor modes that needs a restore |
112 |
|
;; function different from the usual minor mode function. |
113 |
|
;; --------------------------------------------------------------------------- |
114 |
|
|
115 |
;; By the way: don't use desktop.el to customize Emacs -- the file .emacs |
;; By the way: don't use desktop.el to customize Emacs -- the file .emacs |
116 |
;; in your home directory is used for that. Saving global default values |
;; in your home directory is used for that. Saving global default values |
260 |
:group 'desktop |
:group 'desktop |
261 |
:version "22.1") |
:version "22.1") |
262 |
|
|
263 |
(defcustom desktop-clear-preserve-buffers-regexp |
(defcustom desktop-clear-preserve-buffers |
264 |
"^\\(\\*scratch\\*\\|\\*Messages\\*\\|\\*server\\*\\|\\*tramp/.+\\*\\)$" |
'("\\*scratch\\*" "\\*Messages\\*" "\\*server\\*" "\\*tramp/.+\\*") |
265 |
"Regexp identifying buffers that `desktop-clear' should not delete. |
"*List of buffers that `desktop-clear' should not delete. |
266 |
See also `desktop-clear-preserve-buffers'." |
Each element is a regular expression. Buffers with a name matched by any of |
267 |
:type 'regexp |
these won't be deleted." |
|
:group 'desktop |
|
|
:version "22.1") |
|
|
|
|
|
(defcustom desktop-clear-preserve-buffers nil |
|
|
"*List of buffer names that `desktop-clear' should not delete. |
|
|
See also `desktop-clear-preserve-buffers-regexp'." |
|
268 |
:type '(repeat string) |
:type '(repeat string) |
269 |
:group 'desktop) |
:group 'desktop) |
270 |
|
|
271 |
|
;;;###autoload |
272 |
(defcustom desktop-locals-to-save |
(defcustom desktop-locals-to-save |
273 |
'(desktop-locals-to-save ; Itself! Think it over. |
'(desktop-locals-to-save ; Itself! Think it over. |
274 |
truncate-lines |
truncate-lines |
278 |
overwrite-mode |
overwrite-mode |
279 |
change-log-default-name |
change-log-default-name |
280 |
line-number-mode |
line-number-mode |
281 |
buffer-file-coding-system) |
column-number-mode |
282 |
|
size-indication-mode |
283 |
|
buffer-file-coding-system |
284 |
|
indent-tabs-mode |
285 |
|
indicate-buffer-boundaries |
286 |
|
indicate-empty-lines |
287 |
|
show-trailing-whitespace) |
288 |
"List of local variables to save for each buffer. |
"List of local variables to save for each buffer. |
289 |
The variables are saved only when they really are local." |
The variables are saved only when they really are local. Conventional minor |
290 |
|
modes are restored automatically; they should not be listed here." |
291 |
:type '(repeat symbol) |
:type '(repeat symbol) |
292 |
:group 'desktop) |
:group 'desktop) |
|
(make-variable-buffer-local 'desktop-locals-to-save) |
|
293 |
|
|
294 |
;; We skip .log files because they are normally temporary. |
;; We skip .log files because they are normally temporary. |
295 |
;; (ftp) files because they require passwords and whatnot. |
;; (ftp) files because they require passwords and whatnot. |
355 |
When file names are returned, they should be formatted using the call |
When file names are returned, they should be formatted using the call |
356 |
\"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\". |
\"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\". |
357 |
|
|
358 |
Later, when `desktop-read' calls a function in `desktop-buffer-mode-handlers' |
Later, when `desktop-read' evaluates the desktop file, auxiliary information |
359 |
to restore the buffer, the auxiliary information is passed as the argument |
is passed as the argument DESKTOP-BUFFER-MISC to functions in |
360 |
DESKTOP-BUFFER-MISC.") |
`desktop-buffer-mode-handlers'.") |
361 |
(make-variable-buffer-local 'desktop-save-buffer) |
(make-variable-buffer-local 'desktop-save-buffer) |
362 |
(make-obsolete-variable 'desktop-buffer-modes-to-save |
(make-obsolete-variable 'desktop-buffer-modes-to-save |
363 |
'desktop-save-buffer "22.1") |
'desktop-save-buffer "22.1") |
364 |
(make-obsolete-variable 'desktop-buffer-misc-functions |
(make-obsolete-variable 'desktop-buffer-misc-functions |
365 |
'desktop-save-buffer "22.1") |
'desktop-save-buffer "22.1") |
366 |
|
|
367 |
(defcustom desktop-buffer-mode-handlers |
;;;###autoload |
368 |
'((dired-mode . dired-restore-desktop-buffer) |
(defvar desktop-buffer-mode-handlers |
369 |
(rmail-mode . rmail-restore-desktop-buffer) |
nil |
|
(mh-folder-mode . mh-restore-desktop-buffer) |
|
|
(Info-mode . Info-restore-desktop-buffer)) |
|
370 |
"Alist of major mode specific functions to restore a desktop buffer. |
"Alist of major mode specific functions to restore a desktop buffer. |
371 |
Functions are called by `desktop-read'. List elements must have the form |
Functions listed are called by `desktop-create-buffer' when `desktop-read' |
372 |
\(MAJOR-MODE . RESTORE-BUFFER-FUNCTION). |
evaluates the desktop file. List elements must have the form |
373 |
|
|
374 |
|
(MAJOR-MODE . RESTORE-BUFFER-FUNCTION). |
375 |
|
|
376 |
Buffers with a major mode not specified here, are restored by the default |
Buffers with a major mode not specified here, are restored by the default |
377 |
handler `desktop-restore-file-buffer'. |
handler `desktop-restore-file-buffer'. |
391 |
desktop-buffer-locals |
desktop-buffer-locals |
392 |
|
|
393 |
If a handler returns a buffer, then the saved mode settings |
If a handler returns a buffer, then the saved mode settings |
394 |
and variable values for that buffer are copied into it." |
and variable values for that buffer are copied into it. |
395 |
:type 'alist |
|
396 |
:group 'desktop) |
Modules that define a major mode that needs a special handler should contain |
397 |
|
code like |
398 |
|
|
399 |
|
(defun foo-restore-desktop-buffer |
400 |
|
... |
401 |
|
(add-to-list 'desktop-buffer-mode-handlers |
402 |
|
'(foo-mode . foo-restore-desktop-buffer)) |
403 |
|
|
404 |
|
Furthermore the major mode function must be autoloaded.") |
405 |
|
|
406 |
(put 'desktop-buffer-mode-handlers 'risky-local-variable t) |
(put 'desktop-buffer-mode-handlers 'risky-local-variable t) |
407 |
(make-obsolete-variable 'desktop-buffer-handlers |
(make-obsolete-variable 'desktop-buffer-handlers |
417 |
called. RESTORE-FUNCTION nil means don't try to restore the minor mode. |
called. RESTORE-FUNCTION nil means don't try to restore the minor mode. |
418 |
Only minor modes for which the name of the buffer-local variable |
Only minor modes for which the name of the buffer-local variable |
419 |
and the name of the minor mode function are different have to be added to |
and the name of the minor mode function are different have to be added to |
420 |
this table." |
this table. See also `desktop-minor-mode-handlers'." |
421 |
:type 'sexp |
:type 'sexp |
422 |
:group 'desktop) |
:group 'desktop) |
423 |
|
|
424 |
|
;;;###autoload |
425 |
|
(defvar desktop-minor-mode-handlers |
426 |
|
nil |
427 |
|
"Alist of functions to restore non-standard minor modes. |
428 |
|
Functions are called by `desktop-create-buffer' to restore minor modes. |
429 |
|
List elements must have the form |
430 |
|
|
431 |
|
(MINOR-MODE . RESTORE-FUNCTION). |
432 |
|
|
433 |
|
Minor modes not specified here, are restored by the standard minor mode |
434 |
|
function. |
435 |
|
|
436 |
|
Handlers are called with argument list |
437 |
|
|
438 |
|
(DESKTOP-BUFFER-LOCALS) |
439 |
|
|
440 |
|
Furthermore, they may use the following variables: |
441 |
|
|
442 |
|
desktop-file-version |
443 |
|
desktop-buffer-file-name |
444 |
|
desktop-buffer-name |
445 |
|
desktop-buffer-major-mode |
446 |
|
desktop-buffer-minor-modes |
447 |
|
desktop-buffer-point |
448 |
|
desktop-buffer-mark |
449 |
|
desktop-buffer-read-only |
450 |
|
desktop-buffer-misc |
451 |
|
|
452 |
|
When a handler is called, the buffer has been created and the major mode has |
453 |
|
been set, but local variables listed in desktop-buffer-locals has not yet been |
454 |
|
created and set. |
455 |
|
|
456 |
|
Modules that define a minor mode that needs a special handler should contain |
457 |
|
code like |
458 |
|
|
459 |
|
(defun foo-desktop-restore |
460 |
|
... |
461 |
|
(add-to-list 'desktop-minor-mode-handlers |
462 |
|
'(foo-mode . foo-desktop-restore)) |
463 |
|
|
464 |
|
Furthermore the minor mode function must be autoloaded. |
465 |
|
|
466 |
|
See also `desktop-minor-mode-table'.") |
467 |
|
|
468 |
|
(put 'desktop-minor-mode-handlers 'risky-local-variable t) |
469 |
|
|
470 |
;; ---------------------------------------------------------------------------- |
;; ---------------------------------------------------------------------------- |
471 |
(defvar desktop-dirname nil |
(defvar desktop-dirname nil |
472 |
"The directory in which the desktop file should be saved.") |
"The directory in which the desktop file should be saved.") |
490 |
;; ---------------------------------------------------------------------------- |
;; ---------------------------------------------------------------------------- |
491 |
(defun desktop-clear () |
(defun desktop-clear () |
492 |
"Empty the Desktop. |
"Empty the Desktop. |
493 |
This kills all buffers except for internal ones and those matching |
This kills all buffers except for internal ones and those with names matched by |
494 |
`desktop-clear-preserve-buffers-regexp' or listed in |
a regular expression in the list `desktop-clear-preserve-buffers'. |
495 |
`desktop-clear-preserve-buffers'. Furthermore, it clears the |
Furthermore, it clears the variables listed in `desktop-globals-to-clear'." |
|
variables listed in `desktop-globals-to-clear'." |
|
496 |
(interactive) |
(interactive) |
497 |
(desktop-lazy-abort) |
(desktop-lazy-abort) |
498 |
(dolist (var desktop-globals-to-clear) |
(dolist (var desktop-globals-to-clear) |
499 |
(if (symbolp var) |
(if (symbolp var) |
500 |
(eval `(setq-default ,var nil)) |
(eval `(setq-default ,var nil)) |
501 |
(eval `(setq-default ,(car var) ,(cdr var))))) |
(eval `(setq-default ,(car var) ,(cdr var))))) |
502 |
(let ((buffers (buffer-list))) |
(let ((buffers (buffer-list)) |
503 |
|
(preserve-regexp (concat "^\\(" |
504 |
|
(mapconcat (lambda (regexp) |
505 |
|
(concat "\\(" regexp "\\)")) |
506 |
|
desktop-clear-preserve-buffers |
507 |
|
"\\|") |
508 |
|
"\\)$"))) |
509 |
(while buffers |
(while buffers |
510 |
(let ((bufname (buffer-name (car buffers)))) |
(let ((bufname (buffer-name (car buffers)))) |
511 |
(or |
(or |
512 |
(null bufname) |
(null bufname) |
513 |
(string-match desktop-clear-preserve-buffers-regexp bufname) |
(string-match preserve-regexp bufname) |
|
(member bufname desktop-clear-preserve-buffers) |
|
514 |
;; Don't kill buffers made for internal purposes. |
;; Don't kill buffers made for internal purposes. |
515 |
(and (not (equal bufname "")) (eq (aref bufname 0) ?\s)) |
(and (not (equal bufname "")) (eq (aref bufname 0) ?\s)) |
516 |
(kill-buffer (car buffers)))) |
(kill-buffer (car buffers)))) |
734 |
(and |
(and |
735 |
(boundp minor-mode) |
(boundp minor-mode) |
736 |
(symbol-value minor-mode) |
(symbol-value minor-mode) |
737 |
(let ((special (assq minor-mode desktop-minor-mode-table))) |
(let* ((special (assq minor-mode desktop-minor-mode-table)) |
738 |
(when (or special (functionp minor-mode)) |
(value (cond (special (cadr special)) |
739 |
(setq ret |
((functionp minor-mode) minor-mode)))) |
740 |
(cons |
(when value (add-to-list 'ret value))))) |
|
(if special (cadr special) minor-mode) |
|
|
ret)))))) |
|
741 |
(mapcar #'car minor-mode-alist)) |
(mapcar #'car minor-mode-alist)) |
742 |
ret) |
ret) |
743 |
(point) |
(point) |
795 |
(insert ")\n\n"))) |
(insert ")\n\n"))) |
796 |
info) |
info) |
797 |
(setq default-directory dirname) |
(setq default-directory dirname) |
|
(when (file-exists-p filename) (delete-file filename)) |
|
798 |
(let ((coding-system-for-write 'emacs-mule)) |
(let ((coding-system-for-write 'emacs-mule)) |
799 |
(write-region (point-min) (point-max) filename nil 'nomessage)))) |
(write-region (point-min) (point-max) filename nil 'nomessage)))) |
800 |
(setq desktop-dirname dirname)) |
(setq desktop-dirname dirname)) |
959 |
buf) |
buf) |
960 |
nil))) |
nil))) |
961 |
|
|
962 |
|
(defun desktop-load-file (function) |
963 |
|
"Load the file where auto loaded FUNCTION is defined." |
964 |
|
(let ((fcell (symbol-function function))) |
965 |
|
(when (and (listp fcell) |
966 |
|
(eq 'autoload (car fcell))) |
967 |
|
(load (cadr fcell))))) |
968 |
|
|
969 |
;; ---------------------------------------------------------------------------- |
;; ---------------------------------------------------------------------------- |
970 |
;; Create a buffer, load its file, set its mode, ...; |
;; Create a buffer, load its file, set its mode, ...; |
971 |
;; called from Desktop file only. |
;; called from Desktop file only. |
972 |
|
|
973 |
(eval-when-compile ; Just to silence the byte compiler |
;; Just to silence the byte compiler. |
974 |
(defvar desktop-first-buffer) ;; Dynamically bound in `desktop-read' |
(eval-when-compile |
975 |
) |
(defvar desktop-first-buffer)) ; Dynamically bound in `desktop-read' |
976 |
|
|
977 |
(defun desktop-create-buffer |
(defun desktop-create-buffer |
978 |
(desktop-file-version |
(desktop-file-version |
993 |
;; To make desktop files with relative file names possible, we cannot |
;; To make desktop files with relative file names possible, we cannot |
994 |
;; allow `default-directory' to change. Therefore we save current buffer. |
;; allow `default-directory' to change. Therefore we save current buffer. |
995 |
(save-current-buffer |
(save-current-buffer |
996 |
|
;; Give major mode module a chance to add a handler. |
997 |
|
(desktop-load-file desktop-buffer-major-mode) |
998 |
(let ((buffer-list (buffer-list)) |
(let ((buffer-list (buffer-list)) |
999 |
(result |
(result |
1000 |
(condition-case err |
(condition-case err |
1032 |
(auto-fill-mode 0)) |
(auto-fill-mode 0)) |
1033 |
(t |
(t |
1034 |
(mapc #'(lambda (minor-mode) |
(mapc #'(lambda (minor-mode) |
1035 |
(when (functionp minor-mode) (funcall minor-mode 1))) |
;; Give minor mode module a chance to add a handler. |
1036 |
|
(desktop-load-file minor-mode) |
1037 |
|
(let ((handler (cdr (assq minor-mode desktop-minor-mode-handlers)))) |
1038 |
|
(if handler |
1039 |
|
(funcall handler desktop-buffer-locals) |
1040 |
|
(when (functionp minor-mode) |
1041 |
|
(funcall minor-mode 1))))) |
1042 |
desktop-buffer-minor-modes))) |
desktop-buffer-minor-modes))) |
1043 |
;; Even though point and mark are non-nil when written by `desktop-save' |
;; Even though point and mark are non-nil when written by `desktop-save', |
1044 |
;; they may be modified by handlers wanting to set point or mark themselves. |
;; they may be modified by handlers wanting to set point or mark themselves. |
1045 |
(when desktop-buffer-point |
(when desktop-buffer-point |
1046 |
(goto-char |
(goto-char |