Mercurial > emacs
comparison lisp/desktop.el @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | 8c7919f99581 |
children |
comparison
equal
deleted
inserted
replaced
88154:8ce476d3ba36 | 88155:d7ddb3e565de |
---|---|
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, 1994, 1995, 1997, 2000, 2001 | 3 ;; Copyright (C) 1993, 1994, 1995, 1997, 2000, 2001, 2002, 2003, |
4 ;; Free Software Foundation, Inc. | 4 ;; 2004, 2005 Free Software Foundation, Inc. |
5 | 5 |
6 ;; Author: Morten Welinder <terra@diku.dk> | 6 ;; Author: Morten Welinder <terra@diku.dk> |
7 ;; Maintainter: Lars Hansen <larsh@soem.dk> | |
7 ;; Keywords: convenience | 8 ;; Keywords: convenience |
8 ;; Favourite-brand-of-beer: None, I hate beer. | 9 ;; Favourite-brand-of-beer: None, I hate beer. |
9 | 10 |
10 ;; This file is part of GNU Emacs. | 11 ;; This file is part of GNU Emacs. |
11 | 12 |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 ;; GNU General Public License for more details. | 21 ;; GNU General Public License for more details. |
21 | 22 |
22 ;; You should have received a copy of the GNU General Public License | 23 ;; You should have received a copy of the GNU General Public License |
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the | 24 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
25 ;; Boston, MA 02111-1307, USA. | 26 ;; Boston, MA 02110-1301, USA. |
26 | 27 |
27 ;;; Commentary: | 28 ;;; Commentary: |
28 | 29 |
29 ;; Save the Desktop, i.e., | 30 ;; Save the Desktop, i.e., |
30 ;; - some global variables | 31 ;; - some global variables |
34 ;; - the point | 35 ;; - the point |
35 ;; - the mark & mark-active | 36 ;; - the mark & mark-active |
36 ;; - buffer-read-only | 37 ;; - buffer-read-only |
37 ;; - some local variables | 38 ;; - some local variables |
38 | 39 |
39 ;; To use this, first put these two lines in the bottom of your .emacs | 40 ;; To use this, use customize to turn on desktop-save-mode or add the |
40 ;; file (the later the better): | 41 ;; following line somewhere in your .emacs file: |
41 ;; | 42 ;; |
42 ;; (desktop-load-default) | 43 ;; (desktop-save-mode 1) |
43 ;; (desktop-read) | |
44 ;; | 44 ;; |
45 ;; Between these two lines you may wish to add something that updates the | 45 ;; For further usage information, look at the section |
46 ;; variables `desktop-globals-to-save' and/or `desktop-locals-to-save'. If | 46 ;; "Saving Emacs Sessions" in the GNU Emacs Manual. |
47 ;; for instance you want to save the local variable `foobar' for every buffer | 47 |
48 ;; in which it is local, you could add the line | 48 ;; When the desktop module is loaded, the function `desktop-kill' is |
49 ;; | 49 ;; added to the `kill-emacs-hook'. This function is responsible for |
50 ;; (setq desktop-locals-to-save (cons 'foobar desktop-locals-to-save)) | 50 ;; saving the desktop when Emacs is killed. Furthermore an anonymous |
51 ;; | 51 ;; function is added to the `after-init-hook'. This function is |
52 ;; To avoid saving excessive amounts of data you may also wish to add | 52 ;; responsible for loading the desktop when Emacs is started. |
53 ;; something like the following | 53 |
54 ;; | 54 ;; Special handling. |
55 ;; (add-hook 'kill-emacs-hook | 55 ;; ----------------- |
56 ;; '(lambda () | 56 ;; Variables `desktop-buffer-mode-handlers' and `desktop-minor-mode-handlers' |
57 ;; (desktop-truncate search-ring 3) | 57 ;; are supplied to handle special major and minor modes respectively. |
58 ;; (desktop-truncate regexp-search-ring 3))) | 58 ;; `desktop-buffer-mode-handlers' is an alist of major mode specific functions |
59 ;; | 59 ;; to restore a desktop buffer. Elements must have the form |
60 ;; which will make sure that no more than three search items are saved. You | 60 ;; |
61 ;; must place this line *after* the `(desktop-load-default)' line. See also | 61 ;; (MAJOR-MODE . RESTORE-BUFFER-FUNCTION). |
62 ;; the variable `desktop-save-hook'. | 62 ;; |
63 | 63 ;; Functions listed are called by `desktop-create-buffer' when `desktop-read' |
64 ;; Start Emacs in the root directory of your "project". The desktop saver | 64 ;; evaluates the desktop file. Buffers with a major mode not specified here, |
65 ;; is inactive by default. You activate it by M-x desktop-save RET. When | 65 ;; are restored by the default handler `desktop-restore-file-buffer'. |
66 ;; you exit the next time the above data will be saved. This ensures that | 66 ;; `desktop-minor-mode-handlers' is an alist of functions to restore |
67 ;; all the files you were editing will be reloaded the next time you start | 67 ;; non-standard minor modes. Elements must have the form |
68 ;; Emacs from the same directory and that points will be set where you | 68 ;; |
69 ;; left them. If you save a desktop file in your home directory it will | 69 ;; (MINOR-MODE . RESTORE-FUNCTION). |
70 ;; act as a default desktop when you start Emacs from a directory that | 70 ;; |
71 ;; doesn't have its own. I never do this, but you may want to. | 71 ;; Functions are called by `desktop-create-buffer' to restore minor modes. |
72 | 72 ;; Minor modes not specified here, are restored by the standard minor mode |
73 ;; Some words on minor modes: Most minor modes are controlled by | 73 ;; function. If you write a module that defines a major or minor mode that |
74 ;; buffer-local variables, which have a standard save / restore | 74 ;; needs a special handler, then place code like |
75 ;; mechanism. To handle all minor modes, we take the following | 75 |
76 ;; approach: (1) check whether the variable name from | 76 ;; (defun foo-restore-desktop-buffer |
77 ;; `minor-mode-alist' is also a function; and (2) use translation | 77 ;; ... |
78 ;; table `desktop-minor-mode-table' in the case where the two names | 78 ;; (add-to-list 'desktop-buffer-mode-handlers |
79 ;; are not the same. | 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 ;; --------------------------------------------------------------------------- | |
80 | 114 |
81 ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs | 115 ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs |
82 ;; in your home directory is used for that. Saving global default values | 116 ;; in your home directory is used for that. Saving global default values |
83 ;; for buffers is an example of misuse. | 117 ;; for buffers is an example of misuse. |
84 | 118 |
97 ;; TODO: | 131 ;; TODO: |
98 ;; | 132 ;; |
99 ;; Save window configuration. | 133 ;; Save window configuration. |
100 ;; Recognize more minor modes. | 134 ;; Recognize more minor modes. |
101 ;; Save mark rings. | 135 ;; Save mark rings. |
102 ;; Start-up with buffer-menu??? | |
103 | 136 |
104 ;;; Code: | 137 ;;; Code: |
105 | 138 |
106 ;; Make the compilation more silent | 139 (defvar desktop-file-version "206" |
107 (eval-when-compile | 140 "Version number of desktop file format. |
108 ;; We use functions from these modules | 141 Written into the desktop file and used at desktop read to provide |
109 ;; We can't (require 'mh-e) since that wants to load something. | 142 backward compatibility.") |
110 (mapcar 'require '(info dired reporter))) | 143 |
111 ;; ---------------------------------------------------------------------------- | 144 ;; ---------------------------------------------------------------------------- |
112 ;; USER OPTIONS -- settings you might want to play with. | 145 ;; USER OPTIONS -- settings you might want to play with. |
113 ;; ---------------------------------------------------------------------------- | 146 ;; ---------------------------------------------------------------------------- |
114 | 147 |
115 (defgroup desktop nil | 148 (defgroup desktop nil |
116 "Save status of Emacs when you exit." | 149 "Save status of Emacs when you exit." |
117 :group 'frames) | 150 :group 'frames) |
118 | 151 |
119 (defcustom desktop-enable nil | 152 ;;;###autoload |
120 "*Non-nil enable Desktop to save the state of Emacs when you exit." | 153 (define-minor-mode desktop-save-mode |
154 "Toggle desktop saving mode. | |
155 With numeric ARG, turn desktop saving on if ARG is positive, off | |
156 otherwise. See variable `desktop-save' for a description of when the | |
157 desktop is saved." | |
158 :global t | |
159 :group 'desktop) | |
160 | |
161 ;; Maintained for backward compatibility | |
162 (define-obsolete-variable-alias 'desktop-enable | |
163 'desktop-save-mode "22.1") | |
164 | |
165 (defcustom desktop-save 'ask-if-new | |
166 "*Specifies whether the desktop should be saved when it is killed. | |
167 A desktop is killed when the user changes desktop or quits Emacs. | |
168 Possible values are: | |
169 t -- always save. | |
170 ask -- always ask. | |
171 ask-if-new -- ask if no desktop file exists, otherwise just save. | |
172 ask-if-exists -- ask if desktop file exists, otherwise don't save. | |
173 if-exists -- save if desktop file exists, otherwise don't save. | |
174 nil -- never save. | |
175 The desktop is never saved when `desktop-save-mode' is nil. | |
176 The variables `desktop-dirname' and `desktop-base-file-name' | |
177 determine where the desktop is saved." | |
178 :type '(choice | |
179 (const :tag "Always save" t) | |
180 (const :tag "Always ask" ask) | |
181 (const :tag "Ask if desktop file is new, else do save" ask-if-new) | |
182 (const :tag "Ask if desktop file exists, else don't save" ask-if-exists) | |
183 (const :tag "Save if desktop file exists, else don't" if-exists) | |
184 (const :tag "Never save" nil)) | |
121 :group 'desktop | 185 :group 'desktop |
122 :type 'boolean | 186 :version "22.1") |
123 :require 'desktop | 187 |
124 :initialize 'custom-initialize-default | 188 (defcustom desktop-base-file-name |
125 :version "20.3") | |
126 | |
127 (defcustom desktop-basefilename | |
128 (convert-standard-filename ".emacs.desktop") | 189 (convert-standard-filename ".emacs.desktop") |
129 "File for Emacs desktop, not including the directory name." | 190 "Name of file for Emacs desktop, excluding the directory part." |
130 :type 'file | 191 :type 'file |
131 :group 'desktop) | 192 :group 'desktop) |
193 (define-obsolete-variable-alias 'desktop-basefilename | |
194 'desktop-base-file-name "22.1") | |
195 | |
196 (defcustom desktop-path '("." "~") | |
197 "List of directories to search for the desktop file. | |
198 The base name of the file is specified in `desktop-base-file-name'." | |
199 :type '(repeat directory) | |
200 :group 'desktop | |
201 :version "22.1") | |
132 | 202 |
133 (defcustom desktop-missing-file-warning nil | 203 (defcustom desktop-missing-file-warning nil |
134 "*If non-nil then desktop warns when a file no longer exists. | 204 "*If non-nil then `desktop-read' asks if a non-existent file should be recreated. |
135 Otherwise it simply ignores that file." | 205 Also pause for a moment to display message about errors signaled in |
206 `desktop-buffer-mode-handlers'. | |
207 | |
208 If nil, just print error messages in the message buffer." | |
136 :type 'boolean | 209 :type 'boolean |
210 :group 'desktop | |
211 :version "22.1") | |
212 | |
213 (defcustom desktop-no-desktop-file-hook nil | |
214 "Normal hook run when `desktop-read' can't find a desktop file. | |
215 May be used to show a dired buffer." | |
216 :type 'hook | |
217 :group 'desktop | |
218 :version "22.1") | |
219 | |
220 (defcustom desktop-after-read-hook nil | |
221 "Normal hook run after a successful `desktop-read'. | |
222 May be used to show a buffer list." | |
223 :type 'hook | |
224 :group 'desktop | |
225 :version "22.1") | |
226 | |
227 (defcustom desktop-save-hook nil | |
228 "Normal hook run before the desktop is saved in a desktop file. | |
229 This is useful for truncating history lists, for example." | |
230 :type 'hook | |
137 :group 'desktop) | 231 :group 'desktop) |
138 | 232 |
139 (defvar desktop-globals-to-save | 233 (defcustom desktop-globals-to-save |
140 (list 'desktop-missing-file-warning | 234 '(desktop-missing-file-warning |
141 ;; Feature: saving kill-ring implies saving kill-ring-yank-pointer | 235 tags-file-name |
142 ;; 'kill-ring | 236 tags-table-list |
143 'tags-file-name | 237 search-ring |
144 'tags-table-list | 238 regexp-search-ring |
145 'search-ring | 239 register-alist) |
146 'regexp-search-ring | 240 "List of global variables saved by `desktop-save'. |
147 'register-alist | 241 An element may be variable name (a symbol) or a cons cell of the form |
148 ;; 'desktop-globals-to-save ; Itself! | 242 \(VAR . MAX-SIZE), which means to truncate VAR's value to at most |
149 ) | 243 MAX-SIZE elements (if the value is a list) before saving the value. |
150 "List of global variables to save when killing Emacs. | 244 Feature: Saving `kill-ring' implies saving `kill-ring-yank-pointer'." |
151 An element may be variable name (a symbol) | 245 :type '(repeat (restricted-sexp :match-alternatives (symbolp consp))) |
152 or a cons cell of the form (VAR . MAX-SIZE), | 246 :group 'desktop) |
153 which means to truncate VAR's value to at most MAX-SIZE elements | 247 |
154 \(if the value is a list) before saving the value.") | 248 (defcustom desktop-globals-to-clear |
155 | 249 '(kill-ring |
156 (defvar desktop-locals-to-save | 250 kill-ring-yank-pointer |
157 (list 'desktop-locals-to-save ; Itself! Think it over. | 251 search-ring |
158 'truncate-lines | 252 search-ring-yank-pointer |
159 'case-fold-search | 253 regexp-search-ring |
160 'case-replace | 254 regexp-search-ring-yank-pointer) |
161 'fill-column | 255 "List of global variables that `desktop-clear' will clear. |
162 'overwrite-mode | 256 An element may be variable name (a symbol) or a cons cell of the form |
163 'change-log-default-name | 257 \(VAR . FORM). Symbols are set to nil and for cons cells VAR is set |
164 'line-number-mode | 258 to the value obtained by evaluating FORM." |
165 ) | 259 :type '(repeat (restricted-sexp :match-alternatives (symbolp consp))) |
260 :group 'desktop | |
261 :version "22.1") | |
262 | |
263 (defcustom desktop-clear-preserve-buffers | |
264 '("\\*scratch\\*" "\\*Messages\\*" "\\*server\\*" "\\*tramp/.+\\*") | |
265 "*List of buffers that `desktop-clear' should not delete. | |
266 Each element is a regular expression. Buffers with a name matched by any of | |
267 these won't be deleted." | |
268 :type '(repeat string) | |
269 :group 'desktop) | |
270 | |
271 ;;;###autoload | |
272 (defcustom desktop-locals-to-save | |
273 '(desktop-locals-to-save ; Itself! Think it over. | |
274 truncate-lines | |
275 case-fold-search | |
276 case-replace | |
277 fill-column | |
278 overwrite-mode | |
279 change-log-default-name | |
280 line-number-mode | |
281 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) | |
166 "List of local variables to save for each buffer. | 288 "List of local variables to save for each buffer. |
167 The variables are saved only when they really are local.") | 289 The variables are saved only when they really are local. Conventional minor |
168 (make-variable-buffer-local 'desktop-locals-to-save) | 290 modes are restored automatically; they should not be listed here." |
291 :type '(repeat symbol) | |
292 :group 'desktop) | |
169 | 293 |
170 ;; We skip .log files because they are normally temporary. | 294 ;; We skip .log files because they are normally temporary. |
171 ;; (ftp) files because they require passwords and whatnot. | 295 ;; (ftp) files because they require passwords and whatnot. |
172 ;; TAGS files to save time (tags-file-name is saved instead). | |
173 (defcustom desktop-buffers-not-to-save | 296 (defcustom desktop-buffers-not-to-save |
174 "\\(^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS\\)$" | 297 "\\(^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\)$" |
175 "Regexp identifying buffers that are to be excluded from saving." | 298 "Regexp identifying buffers that are to be excluded from saving." |
176 :type 'regexp | 299 :type 'regexp |
177 :group 'desktop) | 300 :group 'desktop) |
178 | 301 |
179 ;; Skip ange-ftp files | 302 ;; Skip tramp and ange-ftp files |
180 (defcustom desktop-files-not-to-save | 303 (defcustom desktop-files-not-to-save |
181 "^/[^/:]*:" | 304 "^/[^/:]*:" |
182 "Regexp identifying files whose buffers are to be excluded from saving." | 305 "Regexp identifying files whose buffers are to be excluded from saving." |
183 :type 'regexp | 306 :type 'regexp |
184 :group 'desktop) | 307 :group 'desktop) |
185 | 308 |
186 (defcustom desktop-buffer-modes-to-save | 309 ;; We skip TAGS files to save time (tags-file-name is saved instead). |
187 '(Info-mode rmail-mode) | 310 (defcustom desktop-modes-not-to-save |
188 "If a buffer is of one of these major modes, save the buffer name. | 311 '(tags-table-mode) |
189 It is up to the functions in `desktop-buffer-handlers' to decide | |
190 whether the buffer should be recreated or not, and how." | |
191 :type '(repeat symbol) | |
192 :group 'desktop) | |
193 | |
194 (defcustom desktop-modes-not-to-save nil | |
195 "List of major modes whose buffers should not be saved." | 312 "List of major modes whose buffers should not be saved." |
196 :type '(repeat symbol) | 313 :type '(repeat symbol) |
197 :group 'desktop) | 314 :group 'desktop) |
198 | 315 |
199 (defcustom desktop-buffer-major-mode nil | 316 (defcustom desktop-file-name-format 'absolute |
200 "When desktop creates a buffer, this holds the desired Major mode." | 317 "*Format in which desktop file names should be saved. |
201 :type 'symbol | 318 Possible values are: |
202 :group 'desktop) | 319 absolute -- Absolute file name. |
203 | 320 tilde -- Relative to ~. |
204 (defcustom desktop-buffer-file-name nil | 321 local -- Relative to directory of desktop file." |
205 "When desktop creates a buffer, this holds the file name to visit." | 322 :type '(choice (const absolute) (const tilde) (const local)) |
206 :type '(choice file (const nil)) | 323 :group 'desktop |
207 :group 'desktop) | 324 :version "22.1") |
208 | 325 |
209 (defcustom desktop-buffer-name nil | 326 (defcustom desktop-restore-eager t |
210 "When desktop creates a buffer, this holds the desired buffer name." | 327 "Number of buffers to restore immediately. |
211 :type '(choice string (const nil)) | 328 Remaining buffers are restored lazily (when Emacs is idle). |
212 :group 'desktop) | 329 If value is t, all buffers are restored immediately." |
213 | 330 :type '(choice (const t) integer) |
214 (defvar desktop-buffer-misc nil | 331 :group 'desktop |
215 "When desktop creates a buffer, this holds a list of misc info. | 332 :version "22.1") |
216 It is used by the `desktop-buffer-handlers' functions.") | 333 |
217 | 334 (defcustom desktop-lazy-verbose t |
218 (defcustom desktop-buffer-misc-functions | 335 "Verbose reporting of lazily created buffers." |
219 '(desktop-buffer-info-misc-data | 336 :type 'boolean |
220 desktop-buffer-dired-misc-data) | 337 :group 'desktop |
221 "*Functions used to determine auxiliary information for a buffer. | 338 :version "22.1") |
222 These functions are called in order, with no arguments. If a function | 339 |
223 returns non-nil, its value is saved along with the desktop buffer for | 340 (defcustom desktop-lazy-idle-delay 5 |
224 which it was called; no further functions will be called. | 341 "Idle delay before starting to create buffers. |
225 | 342 See `desktop-restore-eager'." |
226 Later, when desktop.el restores the buffers it has saved, each of the | 343 :type 'integer |
227 `desktop-buffer-handlers' functions will have access to a buffer local | 344 :group 'desktop |
228 variable, named `desktop-buffer-misc', whose value is what the | 345 :version "22.1") |
229 \"misc\" function returned previously." | 346 |
230 :type '(repeat function) | 347 ;;;###autoload |
231 :group 'desktop) | 348 (defvar desktop-save-buffer nil |
232 | 349 "When non-nil, save buffer status in desktop file. |
233 (defcustom desktop-buffer-handlers | 350 This variable becomes buffer local when set. |
234 '(desktop-buffer-dired | 351 |
235 desktop-buffer-rmail | 352 If the value is a function, it is called by `desktop-save' with argument |
236 desktop-buffer-mh | 353 DESKTOP-DIRNAME to obtain auxiliary information to save in the desktop |
237 desktop-buffer-info | 354 file along with the state of the buffer for which it was called. |
238 desktop-buffer-file) | 355 |
239 "*List of functions to call in order to create a buffer. | 356 When file names are returned, they should be formatted using the call |
240 The functions are called without explicit parameters but can use the | 357 \"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\". |
241 variables `desktop-buffer-major-mode', `desktop-buffer-file-name', | 358 |
242 `desktop-buffer-name'. | 359 Later, when `desktop-read' evaluates the desktop file, auxiliary information |
243 If one function returns non-nil, no further functions are called. | 360 is passed as the argument DESKTOP-BUFFER-MISC to functions in |
244 If the function returns a buffer, then the saved mode settings | 361 `desktop-buffer-mode-handlers'.") |
245 and variable values for that buffer are copied into it." | 362 (make-variable-buffer-local 'desktop-save-buffer) |
246 :type '(repeat function) | 363 (make-obsolete-variable 'desktop-buffer-modes-to-save |
247 :group 'desktop) | 364 'desktop-save-buffer "22.1") |
248 | 365 (make-obsolete-variable 'desktop-buffer-misc-functions |
249 (put 'desktop-buffer-handlers 'risky-local-variable t) | 366 'desktop-save-buffer "22.1") |
250 | 367 |
251 (defvar desktop-create-buffer-form "(desktop-create-buffer 205" | 368 ;;;###autoload |
252 "Opening of form for creation of new buffers.") | 369 (defvar desktop-buffer-mode-handlers |
253 | 370 nil |
254 (defcustom desktop-save-hook nil | 371 "Alist of major mode specific functions to restore a desktop buffer. |
255 "Hook run before desktop saves the state of Emacs. | 372 Functions listed are called by `desktop-create-buffer' when `desktop-read' |
256 This is useful for truncating history lists, for example." | 373 evaluates the desktop file. List elements must have the form |
257 :type 'hook | 374 |
258 :group 'desktop) | 375 (MAJOR-MODE . RESTORE-BUFFER-FUNCTION). |
376 | |
377 Buffers with a major mode not specified here, are restored by the default | |
378 handler `desktop-restore-file-buffer'. | |
379 | |
380 Handlers are called with argument list | |
381 | |
382 (DESKTOP-BUFFER-FILE-NAME DESKTOP-BUFFER-NAME DESKTOP-BUFFER-MISC) | |
383 | |
384 Furthermore, they may use the following variables: | |
385 | |
386 desktop-file-version | |
387 desktop-buffer-major-mode | |
388 desktop-buffer-minor-modes | |
389 desktop-buffer-point | |
390 desktop-buffer-mark | |
391 desktop-buffer-read-only | |
392 desktop-buffer-locals | |
393 | |
394 If a handler returns a buffer, then the saved mode settings | |
395 and variable values for that buffer are copied into it. | |
396 | |
397 Modules that define a major mode that needs a special handler should contain | |
398 code like | |
399 | |
400 (defun foo-restore-desktop-buffer | |
401 ... | |
402 (add-to-list 'desktop-buffer-mode-handlers | |
403 '(foo-mode . foo-restore-desktop-buffer)) | |
404 | |
405 Furthermore the major mode function must be autoloaded.") | |
406 | |
407 ;;;###autoload | |
408 (put 'desktop-buffer-mode-handlers 'risky-local-variable t) | |
409 (make-obsolete-variable 'desktop-buffer-handlers | |
410 'desktop-buffer-mode-handlers "22.1") | |
259 | 411 |
260 (defcustom desktop-minor-mode-table | 412 (defcustom desktop-minor-mode-table |
261 '((auto-fill-function auto-fill-mode) | 413 '((auto-fill-function auto-fill-mode) |
262 (vc-mode nil)) | 414 (vc-mode nil) |
415 (vc-dired-mode nil)) | |
263 "Table mapping minor mode variables to minor mode functions. | 416 "Table mapping minor mode variables to minor mode functions. |
264 Each entry has the form (NAME RESTORE-FUNCTION). | 417 Each entry has the form (NAME RESTORE-FUNCTION). |
265 NAME is the name of the buffer-local variable indicating that the minor | 418 NAME is the name of the buffer-local variable indicating that the minor |
266 mode is active. RESTORE-FUNCTION is the function to activate the minor mode. | 419 mode is active. RESTORE-FUNCTION is the function to activate the minor mode. |
267 called. RESTORE-FUNCTION nil means don't try to restore the minor mode. | 420 called. RESTORE-FUNCTION nil means don't try to restore the minor mode. |
268 Only minor modes for which the name of the buffer-local variable | 421 Only minor modes for which the name of the buffer-local variable |
269 and the name of the minor mode function are different have to added to | 422 and the name of the minor mode function are different have to be added to |
270 this table." | 423 this table. See also `desktop-minor-mode-handlers'." |
271 :type 'sexp | 424 :type 'sexp |
272 :group 'desktop) | 425 :group 'desktop) |
273 | 426 |
427 ;;;###autoload | |
428 (defvar desktop-minor-mode-handlers | |
429 nil | |
430 "Alist of functions to restore non-standard minor modes. | |
431 Functions are called by `desktop-create-buffer' to restore minor modes. | |
432 List elements must have the form | |
433 | |
434 (MINOR-MODE . RESTORE-FUNCTION). | |
435 | |
436 Minor modes not specified here, are restored by the standard minor mode | |
437 function. | |
438 | |
439 Handlers are called with argument list | |
440 | |
441 (DESKTOP-BUFFER-LOCALS) | |
442 | |
443 Furthermore, they may use the following variables: | |
444 | |
445 desktop-file-version | |
446 desktop-buffer-file-name | |
447 desktop-buffer-name | |
448 desktop-buffer-major-mode | |
449 desktop-buffer-minor-modes | |
450 desktop-buffer-point | |
451 desktop-buffer-mark | |
452 desktop-buffer-read-only | |
453 desktop-buffer-misc | |
454 | |
455 When a handler is called, the buffer has been created and the major mode has | |
456 been set, but local variables listed in desktop-buffer-locals has not yet been | |
457 created and set. | |
458 | |
459 Modules that define a minor mode that needs a special handler should contain | |
460 code like | |
461 | |
462 (defun foo-desktop-restore | |
463 ... | |
464 (add-to-list 'desktop-minor-mode-handlers | |
465 '(foo-mode . foo-desktop-restore)) | |
466 | |
467 Furthermore the minor mode function must be autoloaded. | |
468 | |
469 See also `desktop-minor-mode-table'.") | |
470 | |
471 ;;;###autoload | |
472 (put 'desktop-minor-mode-handlers 'risky-local-variable t) | |
473 | |
274 ;; ---------------------------------------------------------------------------- | 474 ;; ---------------------------------------------------------------------------- |
275 (defvar desktop-dirname nil | 475 (defvar desktop-dirname nil |
276 "The directory in which the current desktop file resides.") | 476 "The directory in which the desktop file should be saved.") |
277 | 477 |
278 (defconst desktop-header | 478 (defconst desktop-header |
279 ";; -------------------------------------------------------------------------- | 479 ";; -------------------------------------------------------------------------- |
280 ;; Desktop File for Emacs | 480 ;; Desktop File for Emacs |
281 ;; -------------------------------------------------------------------------- | 481 ;; -------------------------------------------------------------------------- |
283 | 483 |
284 (defvar desktop-delay-hook nil | 484 (defvar desktop-delay-hook nil |
285 "Hooks run after all buffers are loaded; intended for internal use.") | 485 "Hooks run after all buffers are loaded; intended for internal use.") |
286 | 486 |
287 ;; ---------------------------------------------------------------------------- | 487 ;; ---------------------------------------------------------------------------- |
288 (defun desktop-truncate (l n) | 488 (defun desktop-truncate (list n) |
289 "Truncate LIST to at most N elements destructively." | 489 "Truncate LIST to at most N elements destructively." |
290 (let ((here (nthcdr (1- n) l))) | 490 (let ((here (nthcdr (1- n) list))) |
291 (if (consp here) | 491 (if (consp here) |
292 (setcdr here nil)))) | 492 (setcdr here nil)))) |
293 ;; ---------------------------------------------------------------------------- | 493 |
294 (defcustom desktop-clear-preserve-buffers | 494 ;; ---------------------------------------------------------------------------- |
295 '("*scratch*" "*Messages*") | |
296 "*Buffer names that `desktop-clear' should not delete." | |
297 :type '(repeat string) | |
298 :group 'desktop) | |
299 | |
300 (defun desktop-clear () | 495 (defun desktop-clear () |
301 "Empty the Desktop. | 496 "Empty the Desktop. |
302 This kills all buffers except for internal ones | 497 This kills all buffers except for internal ones and those with names matched by |
303 and those listed in `desktop-clear-preserve-buffers'." | 498 a regular expression in the list `desktop-clear-preserve-buffers'. |
499 Furthermore, it clears the variables listed in `desktop-globals-to-clear'." | |
304 (interactive) | 500 (interactive) |
305 (setq kill-ring nil | 501 (desktop-lazy-abort) |
306 kill-ring-yank-pointer nil | 502 (dolist (var desktop-globals-to-clear) |
307 search-ring nil | 503 (if (symbolp var) |
308 search-ring-yank-pointer nil | 504 (eval `(setq-default ,var nil)) |
309 regexp-search-ring nil | 505 (eval `(setq-default ,(car var) ,(cdr var))))) |
310 regexp-search-ring-yank-pointer nil) | 506 (let ((buffers (buffer-list)) |
311 (let ((buffers (buffer-list))) | 507 (preserve-regexp (concat "^\\(" |
508 (mapconcat (lambda (regexp) | |
509 (concat "\\(" regexp "\\)")) | |
510 desktop-clear-preserve-buffers | |
511 "\\|") | |
512 "\\)$"))) | |
312 (while buffers | 513 (while buffers |
313 (or (member (buffer-name (car buffers)) desktop-clear-preserve-buffers) | 514 (let ((bufname (buffer-name (car buffers)))) |
314 (null (buffer-name (car buffers))) | 515 (or |
315 ;; Don't kill buffers made for internal purposes. | 516 (null bufname) |
316 (and (not (equal (buffer-name (car buffers)) "")) | 517 (string-match preserve-regexp bufname) |
317 (eq (aref (buffer-name (car buffers)) 0) ?\ )) | 518 ;; Don't kill buffers made for internal purposes. |
318 (kill-buffer (car buffers))) | 519 (and (not (equal bufname "")) (eq (aref bufname 0) ?\s)) |
520 (kill-buffer (car buffers)))) | |
319 (setq buffers (cdr buffers)))) | 521 (setq buffers (cdr buffers)))) |
320 (delete-other-windows)) | 522 (delete-other-windows)) |
523 | |
321 ;; ---------------------------------------------------------------------------- | 524 ;; ---------------------------------------------------------------------------- |
322 (add-hook 'kill-emacs-hook 'desktop-kill) | 525 (add-hook 'kill-emacs-hook 'desktop-kill) |
323 | 526 |
324 (defun desktop-kill () | 527 (defun desktop-kill () |
325 (if desktop-dirname | 528 "If `desktop-save-mode' is non-nil, do what `desktop-save' says to do. |
326 (condition-case err | 529 If the desktop should be saved and `desktop-dirname' |
327 (desktop-save desktop-dirname) | 530 is nil, ask the user where to save the desktop." |
328 (file-error | 531 (when |
329 (if (yes-or-no-p "Error while saving the desktop. Quit anyway? ") | 532 (and |
330 nil | 533 desktop-save-mode |
331 (signal (car err) (cdr err))))))) | 534 (let ((exists (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname)))) |
535 (or | |
536 (eq desktop-save t) | |
537 (and exists (memq desktop-save '(ask-if-new if-exists))) | |
538 (and | |
539 (or | |
540 (memq desktop-save '(ask ask-if-new)) | |
541 (and exists (eq desktop-save 'ask-if-exists))) | |
542 (y-or-n-p "Save desktop? "))))) | |
543 (unless desktop-dirname | |
544 (setq desktop-dirname | |
545 (file-name-as-directory | |
546 (expand-file-name | |
547 (call-interactively | |
548 (lambda (dir) (interactive "DDirectory for desktop file: ") dir)))))) | |
549 (condition-case err | |
550 (desktop-save desktop-dirname) | |
551 (file-error | |
552 (unless (yes-or-no-p "Error while saving the desktop. Ignore? ") | |
553 (signal (car err) (cdr err))))))) | |
554 | |
332 ;; ---------------------------------------------------------------------------- | 555 ;; ---------------------------------------------------------------------------- |
333 (defun desktop-list* (&rest args) | 556 (defun desktop-list* (&rest args) |
334 (if (null (cdr args)) | 557 (if (null (cdr args)) |
335 (car args) | 558 (car args) |
336 (setq args (nreverse args)) | 559 (setq args (nreverse args)) |
339 (while args | 562 (while args |
340 (setq value (cons (car args) value)) | 563 (setq value (cons (car args) value)) |
341 (setq args (cdr args))) | 564 (setq args (cdr args))) |
342 value))) | 565 value))) |
343 | 566 |
344 (defun desktop-internal-v2s (val) | 567 ;; ---------------------------------------------------------------------------- |
568 (defun desktop-internal-v2s (value) | |
345 "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE. | 569 "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE. |
346 TXT is a string that when read and evaluated yields value. | 570 TXT is a string that when read and evaluated yields value. |
347 QUOTE may be `may' (value may be quoted), | 571 QUOTE may be `may' (value may be quoted), |
348 `must' (values must be quoted), or nil (value may not be quoted)." | 572 `must' (values must be quoted), or nil (value may not be quoted)." |
349 (cond | 573 (cond |
350 ((or (numberp val) (null val) (eq t val)) | 574 ((or (numberp value) (null value) (eq t value) (keywordp value)) |
351 (cons 'may (prin1-to-string val))) | 575 (cons 'may (prin1-to-string value))) |
352 ((stringp val) | 576 ((stringp value) |
353 (let ((copy (copy-sequence val))) | 577 (let ((copy (copy-sequence value))) |
354 (set-text-properties 0 (length copy) nil copy) | 578 (set-text-properties 0 (length copy) nil copy) |
355 ;; Get rid of text properties because we cannot read them | 579 ;; Get rid of text properties because we cannot read them |
356 (cons 'may (prin1-to-string copy)))) | 580 (cons 'may (prin1-to-string copy)))) |
357 ((symbolp val) | 581 ((symbolp value) |
358 (cons 'must (prin1-to-string val))) | 582 (cons 'must (prin1-to-string value))) |
359 ((vectorp val) | 583 ((vectorp value) |
360 (let* ((special nil) | 584 (let* ((special nil) |
361 (pass1 (mapcar | 585 (pass1 (mapcar |
362 (lambda (el) | 586 (lambda (el) |
363 (let ((res (desktop-internal-v2s el))) | 587 (let ((res (desktop-internal-v2s el))) |
364 (if (null (car res)) | 588 (if (null (car res)) |
365 (setq special t)) | 589 (setq special t)) |
366 res)) | 590 res)) |
367 val))) | 591 value))) |
368 (if special | 592 (if special |
369 (cons nil (concat "(vector " | 593 (cons nil (concat "(vector " |
370 (mapconcat (lambda (el) | 594 (mapconcat (lambda (el) |
371 (if (eq (car el) 'must) | 595 (if (eq (car el) 'must) |
372 (concat "'" (cdr el)) | 596 (concat "'" (cdr el)) |
373 (cdr el))) | 597 (cdr el))) |
374 pass1 | 598 pass1 |
375 " ") | 599 " ") |
376 ")")) | 600 ")")) |
377 (cons 'may (concat "[" (mapconcat 'cdr pass1 " ") "]"))))) | 601 (cons 'may (concat "[" (mapconcat 'cdr pass1 " ") "]"))))) |
378 ((consp val) | 602 ((consp value) |
379 (let ((p val) | 603 (let ((p value) |
380 newlist | 604 newlist |
381 use-list* | 605 use-list* |
382 anynil) | 606 anynil) |
383 (while (consp p) | 607 (while (consp p) |
384 (let ((q.txt (desktop-internal-v2s (car p)))) | 608 (let ((q.txt (desktop-internal-v2s (car p)))) |
404 newlist | 628 newlist |
405 " ") | 629 " ") |
406 ")")) | 630 ")")) |
407 (cons 'must | 631 (cons 'must |
408 (concat "(" (mapconcat 'cdr newlist " ") ")"))))) | 632 (concat "(" (mapconcat 'cdr newlist " ") ")"))))) |
409 ((subrp val) | 633 ((subrp value) |
410 (cons nil (concat "(symbol-function '" | 634 (cons nil (concat "(symbol-function '" |
411 (substring (prin1-to-string val) 7 -1) | 635 (substring (prin1-to-string value) 7 -1) |
412 ")"))) | 636 ")"))) |
413 ((markerp val) | 637 ((markerp value) |
414 (let ((pos (prin1-to-string (marker-position val))) | 638 (let ((pos (prin1-to-string (marker-position value))) |
415 (buf (prin1-to-string (buffer-name (marker-buffer val))))) | 639 (buf (prin1-to-string (buffer-name (marker-buffer value))))) |
416 (cons nil (concat "(let ((mk (make-marker)))" | 640 (cons nil (concat "(let ((mk (make-marker)))" |
417 " (add-hook 'desktop-delay-hook" | 641 " (add-hook 'desktop-delay-hook" |
418 " (list 'lambda '() (list 'set-marker mk " | 642 " (list 'lambda '() (list 'set-marker mk " |
419 pos " (get-buffer " buf ")))) mk)")))) | 643 pos " (get-buffer " buf ")))) mk)")))) |
420 (t ; save as text | 644 (t ; save as text |
421 (cons 'may "\"Unprintable entity\"")))) | 645 (cons 'may "\"Unprintable entity\"")))) |
422 | 646 |
423 (defun desktop-value-to-string (val) | 647 ;; ---------------------------------------------------------------------------- |
648 (defun desktop-value-to-string (value) | |
424 "Convert VALUE to a string that when read evaluates to the same value. | 649 "Convert VALUE to a string that when read evaluates to the same value. |
425 Not all types of values are supported." | 650 Not all types of values are supported." |
426 (let* ((print-escape-newlines t) | 651 (let* ((print-escape-newlines t) |
427 (float-output-format nil) | 652 (float-output-format nil) |
428 (quote.txt (desktop-internal-v2s val)) | 653 (quote.txt (desktop-internal-v2s value)) |
429 (quote (car quote.txt)) | 654 (quote (car quote.txt)) |
430 (txt (cdr quote.txt))) | 655 (txt (cdr quote.txt))) |
431 (if (eq quote 'must) | 656 (if (eq quote 'must) |
432 (concat "'" txt) | 657 (concat "'" txt) |
433 txt))) | 658 txt))) |
659 | |
434 ;; ---------------------------------------------------------------------------- | 660 ;; ---------------------------------------------------------------------------- |
435 (defun desktop-outvar (varspec) | 661 (defun desktop-outvar (varspec) |
436 "Output a setq statement for variable VAR to the desktop file. | 662 "Output a setq statement for variable VAR to the desktop file. |
437 The argument VARSPEC may be the variable name VAR (a symbol), | 663 The argument VARSPEC may be the variable name VAR (a symbol), |
438 or a cons cell of the form (VAR . MAX-SIZE), | 664 or a cons cell of the form (VAR . MAX-SIZE), |
451 (insert "(setq " | 677 (insert "(setq " |
452 (symbol-name var) | 678 (symbol-name var) |
453 " " | 679 " " |
454 (desktop-value-to-string (symbol-value var)) | 680 (desktop-value-to-string (symbol-value var)) |
455 ")\n"))))) | 681 ")\n"))))) |
682 | |
456 ;; ---------------------------------------------------------------------------- | 683 ;; ---------------------------------------------------------------------------- |
457 (defun desktop-save-buffer-p (filename bufname mode &rest dummy) | 684 (defun desktop-save-buffer-p (filename bufname mode &rest dummy) |
458 "Return t if the desktop should record a particular buffer for next startup. | 685 "Return t if buffer should have its state saved in the desktop file. |
459 FILENAME is the visited file name, BUFNAME is the buffer name, and | 686 FILENAME is the visited file name, BUFNAME is the buffer name, and |
460 MODE is the major mode." | 687 MODE is the major mode." |
461 (let ((case-fold-search nil)) | 688 (let ((case-fold-search nil)) |
462 (and (not (string-match desktop-buffers-not-to-save bufname)) | 689 (and (not (string-match desktop-buffers-not-to-save bufname)) |
463 (not (memq mode desktop-modes-not-to-save)) | 690 (not (memq mode desktop-modes-not-to-save)) |
464 (or (and filename | 691 (or (and filename |
465 (not (string-match desktop-files-not-to-save filename))) | 692 (not (string-match desktop-files-not-to-save filename))) |
466 (and (eq mode 'dired-mode) | 693 (and (eq mode 'dired-mode) |
467 (save-excursion | 694 (with-current-buffer bufname |
468 (set-buffer (get-buffer bufname)) | 695 (not (string-match desktop-files-not-to-save |
469 (not (string-match desktop-files-not-to-save | 696 default-directory)))) |
470 default-directory)))) | 697 (and (null filename) |
471 (and (null filename) | 698 (with-current-buffer bufname desktop-save-buffer)))))) |
472 (memq mode desktop-buffer-modes-to-save)))))) | 699 |
473 ;; ---------------------------------------------------------------------------- | 700 ;; ---------------------------------------------------------------------------- |
474 (defcustom desktop-relative-file-names nil | 701 (defun desktop-file-name (filename dirname) |
475 "*Store relative file names in the desktop file." | 702 "Convert FILENAME to format specified in `desktop-file-name-format'. |
476 :type 'boolean | 703 DIRNAME must be the directory in which the desktop file will be saved." |
477 :group 'desktop) | 704 (cond |
478 | 705 ((not filename) nil) |
706 ((eq desktop-file-name-format 'tilde) | |
707 (let ((relative-name (file-relative-name (expand-file-name filename) "~"))) | |
708 (cond | |
709 ((file-name-absolute-p relative-name) relative-name) | |
710 ((string= "./" relative-name) "~/") | |
711 ((string= "." relative-name) "~") | |
712 (t (concat "~/" relative-name))))) | |
713 ((eq desktop-file-name-format 'local) (file-relative-name filename dirname)) | |
714 (t (expand-file-name filename)))) | |
715 | |
716 ;; ---------------------------------------------------------------------------- | |
479 (defun desktop-save (dirname) | 717 (defun desktop-save (dirname) |
480 "Save the Desktop file. Parameter DIRNAME specifies where to save desktop." | 718 "Save the desktop in a desktop file. |
719 Parameter DIRNAME specifies where to save the desktop file. | |
720 See also `desktop-base-file-name'." | |
481 (interactive "DDirectory to save desktop file in: ") | 721 (interactive "DDirectory to save desktop file in: ") |
482 (run-hooks 'desktop-save-hook) | 722 (run-hooks 'desktop-save-hook) |
723 (setq dirname (file-name-as-directory (expand-file-name dirname))) | |
483 (save-excursion | 724 (save-excursion |
484 (let ((filename (expand-file-name desktop-basefilename dirname)) | 725 (let ((filename (expand-file-name desktop-base-file-name dirname)) |
485 (info (nreverse | 726 (info |
486 (mapcar | 727 (mapcar |
487 (function | 728 #'(lambda (b) |
488 (lambda (b) | 729 (set-buffer b) |
489 (set-buffer b) | 730 (list |
490 (list | 731 (desktop-file-name (buffer-file-name) dirname) |
491 (let ((bn (buffer-file-name))) | 732 (buffer-name) |
492 (if bn | 733 major-mode |
493 (if desktop-relative-file-names | 734 ;; minor modes |
494 (file-relative-name bn dirname) | 735 (let (ret) |
495 bn))) | 736 (mapc |
496 (buffer-name) | 737 #'(lambda (minor-mode) |
497 major-mode | 738 (and |
498 ;; minor modes | 739 (boundp minor-mode) |
499 (let (ret) | 740 (symbol-value minor-mode) |
500 (mapcar | 741 (let* ((special (assq minor-mode desktop-minor-mode-table)) |
501 #'(lambda (mim) | 742 (value (cond (special (cadr special)) |
502 (and (boundp mim) | 743 ((functionp minor-mode) minor-mode)))) |
503 (symbol-value mim) | 744 (when value (add-to-list 'ret value))))) |
504 (setq ret | |
505 (cons (let ((special (assq mim desktop-minor-mode-table))) | |
506 (if special | |
507 (cadr special) | |
508 mim)) | |
509 ret)))) | |
510 (mapcar #'car minor-mode-alist)) | 745 (mapcar #'car minor-mode-alist)) |
511 ret) | 746 ret) |
512 (point) | 747 (point) |
513 (list (mark t) mark-active) | 748 (list (mark t) mark-active) |
514 buffer-read-only | 749 buffer-read-only |
515 (run-hook-with-args-until-success | 750 ;; Auxiliary information |
516 'desktop-buffer-misc-functions) | 751 (when (functionp desktop-save-buffer) |
517 (let ((locals desktop-locals-to-save) | 752 (funcall desktop-save-buffer dirname)) |
518 (loclist (buffer-local-variables)) | 753 (let ((locals desktop-locals-to-save) |
519 (ll)) | 754 (loclist (buffer-local-variables)) |
520 (while locals | 755 (ll)) |
521 (let ((here (assq (car locals) loclist))) | 756 (while locals |
522 (if here | 757 (let ((here (assq (car locals) loclist))) |
523 (setq ll (cons here ll)) | 758 (if here |
524 (if (member (car locals) loclist) | 759 (setq ll (cons here ll)) |
525 (setq ll (cons (car locals) ll))))) | 760 (when (member (car locals) loclist) |
526 (setq locals (cdr locals))) | 761 (setq ll (cons (car locals) ll))))) |
527 ll) | 762 (setq locals (cdr locals))) |
528 ))) | 763 ll))) |
529 (buffer-list)))) | 764 (buffer-list))) |
530 (buf (get-buffer-create "*desktop*"))) | 765 (eager desktop-restore-eager) |
766 (buf (get-buffer-create "*desktop*"))) | |
531 (set-buffer buf) | 767 (set-buffer buf) |
532 (erase-buffer) | 768 (erase-buffer) |
533 | 769 |
534 (insert ";; -*- coding: emacs-mule; -*-\n" | 770 (insert |
535 desktop-header | 771 ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n" |
536 ";; Created " (current-time-string) "\n" | 772 desktop-header |
537 ";; Emacs version " emacs-version "\n\n" | 773 ";; Created " (current-time-string) "\n" |
538 ";; Global section:\n") | 774 ";; Desktop file format version " desktop-file-version "\n" |
539 (mapcar (function desktop-outvar) desktop-globals-to-save) | 775 ";; Emacs version " emacs-version "\n\n" |
776 ";; Global section:\n") | |
777 (mapc (function desktop-outvar) desktop-globals-to-save) | |
540 (if (memq 'kill-ring desktop-globals-to-save) | 778 (if (memq 'kill-ring desktop-globals-to-save) |
541 (insert "(setq kill-ring-yank-pointer (nthcdr " | 779 (insert |
542 (int-to-string | 780 "(setq kill-ring-yank-pointer (nthcdr " |
543 (- (length kill-ring) (length kill-ring-yank-pointer))) | 781 (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer))) |
544 " kill-ring))\n")) | 782 " kill-ring))\n")) |
545 | 783 |
546 (insert "\n;; Buffer section:\n") | 784 (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n") |
547 (mapcar | 785 (mapc #'(lambda (l) |
548 (function (lambda (l) | 786 (when (apply 'desktop-save-buffer-p l) |
549 (if (apply 'desktop-save-buffer-p l) | 787 (insert "(" |
550 (progn | 788 (if (or (not (integerp eager)) |
551 (insert desktop-create-buffer-form) | 789 (unless (zerop eager) |
552 (mapcar | 790 (setq eager (1- eager)) |
553 (function (lambda (e) | 791 t)) |
554 (insert "\n " | 792 "desktop-create-buffer" |
555 (desktop-value-to-string e)))) | 793 "desktop-append-buffer-args") |
556 l) | 794 " " |
557 (insert ")\n\n"))))) | 795 desktop-file-version) |
558 info) | 796 (mapc #'(lambda (e) |
797 (insert "\n " (desktop-value-to-string e))) | |
798 l) | |
799 (insert ")\n\n"))) | |
800 info) | |
559 (setq default-directory dirname) | 801 (setq default-directory dirname) |
560 (if (file-exists-p filename) (delete-file filename)) | |
561 (let ((coding-system-for-write 'emacs-mule)) | 802 (let ((coding-system-for-write 'emacs-mule)) |
562 (write-region (point-min) (point-max) filename nil 'nomessage)))) | 803 (write-region (point-min) (point-max) filename nil 'nomessage)))) |
563 (setq desktop-dirname dirname)) | 804 (setq desktop-dirname dirname)) |
805 | |
564 ;; ---------------------------------------------------------------------------- | 806 ;; ---------------------------------------------------------------------------- |
565 (defun desktop-remove () | 807 (defun desktop-remove () |
566 "Delete the Desktop file and inactivate the desktop system." | 808 "Delete desktop file in `desktop-dirname'. |
809 This function also sets `desktop-dirname' to nil." | |
567 (interactive) | 810 (interactive) |
568 (if desktop-dirname | 811 (when desktop-dirname |
569 (let ((filename (concat desktop-dirname desktop-basefilename))) | 812 (let ((filename (expand-file-name desktop-base-file-name desktop-dirname))) |
570 (setq desktop-dirname nil) | 813 (setq desktop-dirname nil) |
571 (if (file-exists-p filename) | 814 (when (file-exists-p filename) |
572 (delete-file filename))))) | 815 (delete-file filename))))) |
816 | |
817 (defvar desktop-buffer-args-list nil | |
818 "List of args for `desktop-create-buffer'.") | |
819 | |
820 (defvar desktop-lazy-timer nil) | |
821 | |
573 ;; ---------------------------------------------------------------------------- | 822 ;; ---------------------------------------------------------------------------- |
574 ;;;###autoload | 823 ;;;###autoload |
575 (defun desktop-read () | 824 (defun desktop-read (&optional dirname) |
576 "Read the Desktop file and the files it specifies. | 825 "Read and process the desktop file in directory DIRNAME. |
577 This is a no-op when Emacs is running in batch mode." | 826 Look for a desktop file in DIRNAME, or if DIRNAME is omitted, look in |
827 directories listed in `desktop-path'. If a desktop file is found, it | |
828 is processed and `desktop-after-read-hook' is run. If no desktop file | |
829 is found, clear the desktop and run `desktop-no-desktop-file-hook'. | |
830 This function is a no-op when Emacs is running in batch mode. | |
831 It returns t if a desktop file was loaded, nil otherwise." | |
578 (interactive) | 832 (interactive) |
579 (if noninteractive | 833 (unless noninteractive |
580 nil | 834 (setq desktop-dirname |
581 (let ((dirs '("./" "~/"))) | 835 (file-name-as-directory |
582 (while (and dirs | 836 (expand-file-name |
583 (not (file-exists-p (expand-file-name | 837 (or |
584 desktop-basefilename | 838 ;; If DIRNAME is specified, use it. |
585 (car dirs))))) | 839 (and (< 0 (length dirname)) dirname) |
586 (setq dirs (cdr dirs))) | 840 ;; Otherwise search desktop file in desktop-path. |
587 (setq desktop-dirname (and dirs (expand-file-name (car dirs)))) | 841 (let ((dirs desktop-path)) |
588 (if desktop-dirname | 842 (while |
589 (let ((desktop-last-buffer nil)) | 843 (and |
590 ;; `load-with-code-conversion' calls `eval-buffer' which | 844 dirs |
591 ;; contains a `save-excursion', so we end up with the same | 845 (not |
592 ;; buffer before and after the load. This is a problem | 846 (file-exists-p (expand-file-name desktop-base-file-name (car dirs))))) |
593 ;; when the desktop is read initially when Emacs starts up | 847 (setq dirs (cdr dirs))) |
594 ;; because, if we still are in *scratch* after running | 848 (and dirs (car dirs))) |
595 ;; `after-init-hook', the splash screen will be displayed. | 849 ;; If not found and `desktop-path' is non-nil, use its first element. |
596 (load (expand-file-name desktop-basefilename desktop-dirname) | 850 (and desktop-path (car desktop-path)) |
597 t t t) | 851 ;; Default: Home directory. |
598 (when desktop-last-buffer | 852 "~")))) |
599 (switch-to-buffer desktop-last-buffer)) | 853 (if (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname)) |
600 (run-hooks 'desktop-delay-hook) | 854 ;; Desktop file found, process it. |
601 (setq desktop-delay-hook nil) | 855 (let ((desktop-first-buffer nil) |
602 (message "Desktop loaded.")) | 856 (desktop-buffer-ok-count 0) |
603 (desktop-clear))))) | 857 (desktop-buffer-fail-count 0)) |
604 ;; ---------------------------------------------------------------------------- | 858 (setq desktop-lazy-timer nil) |
859 ;; Evaluate desktop buffer. | |
860 (load (expand-file-name desktop-base-file-name desktop-dirname) t t t) | |
861 ;; `desktop-create-buffer' puts buffers at end of the buffer list. | |
862 ;; We want buffers existing prior to evaluating the desktop (and not reused) | |
863 ;; to be placed at the end of the buffer list, so we move them here. | |
864 (mapc 'bury-buffer | |
865 (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list)))))) | |
866 (switch-to-buffer (car (buffer-list))) | |
867 (run-hooks 'desktop-delay-hook) | |
868 (setq desktop-delay-hook nil) | |
869 (run-hooks 'desktop-after-read-hook) | |
870 (message "Desktop: %d buffer%s restored%s%s." | |
871 desktop-buffer-ok-count | |
872 (if (= 1 desktop-buffer-ok-count) "" "s") | |
873 (if (< 0 desktop-buffer-fail-count) | |
874 (format ", %d failed to restore" desktop-buffer-fail-count) | |
875 "") | |
876 (if desktop-buffer-args-list | |
877 (format ", %d to restore lazily" | |
878 (length desktop-buffer-args-list)) | |
879 "")) | |
880 t) | |
881 ;; No desktop file found. | |
882 (desktop-clear) | |
883 (let ((default-directory desktop-dirname)) | |
884 (run-hooks 'desktop-no-desktop-file-hook)) | |
885 (message "No desktop file.") | |
886 nil))) | |
887 | |
888 ;; ---------------------------------------------------------------------------- | |
889 ;; Maintained for backward compatibility | |
605 ;;;###autoload | 890 ;;;###autoload |
606 (defun desktop-load-default () | 891 (defun desktop-load-default () |
607 "Load the `default' start-up library manually. | 892 "Load the `default' start-up library manually. |
608 Also inhibit further loading of it. Call this from your `.emacs' file | 893 Also inhibit further loading of it." |
609 to provide correct modes for autoloaded files." | 894 (unless inhibit-default-init ; safety check |
610 (if (not inhibit-default-init) ; safety check | 895 (load "default" t t) |
611 (progn | 896 (setq inhibit-default-init t))) |
612 (load "default" t t) | 897 (make-obsolete 'desktop-load-default |
613 (setq inhibit-default-init t)))) | 898 'desktop-save-mode "22.1") |
614 ;; ---------------------------------------------------------------------------- | 899 |
615 ;; Note: the following functions use the dynamic variable binding in Lisp. | 900 ;; ---------------------------------------------------------------------------- |
616 ;; | 901 ;;;###autoload |
617 (defun desktop-buffer-info-misc-data () | 902 (defun desktop-change-dir (dirname) |
618 (if (eq major-mode 'Info-mode) | 903 "Change to desktop saved in DIRNAME. |
619 (list Info-current-file | 904 Kill the desktop as specified by variables `desktop-save-mode' and |
620 Info-current-node))) | 905 `desktop-save', then clear the desktop and load the desktop file in |
621 | 906 directory DIRNAME." |
622 (defun desktop-buffer-dired-misc-data () | 907 (interactive "DChange to directory: ") |
623 (if (eq major-mode 'dired-mode) | 908 (setq dirname (file-name-as-directory (expand-file-name dirname desktop-dirname))) |
624 (cons | 909 (desktop-kill) |
625 (expand-file-name dired-directory) | 910 (desktop-clear) |
626 (cdr | 911 (desktop-read dirname)) |
627 (nreverse | 912 |
628 (mapcar | 913 ;; ---------------------------------------------------------------------------- |
629 (function car) | 914 ;;;###autoload |
630 dired-subdir-alist)))))) | 915 (defun desktop-save-in-desktop-dir () |
631 | 916 "Save the desktop in directory `desktop-dirname'." |
632 (defun desktop-buffer-info () "Load an info file." | 917 (interactive) |
633 (if (eq 'Info-mode desktop-buffer-major-mode) | 918 (if desktop-dirname |
634 (progn | 919 (desktop-save desktop-dirname) |
635 (let ((first (nth 0 desktop-buffer-misc)) | 920 (call-interactively 'desktop-save)) |
636 (second (nth 1 desktop-buffer-misc))) | 921 (message "Desktop saved in %s" desktop-dirname)) |
637 (when (and first second) | 922 |
638 (require 'info) | 923 ;; ---------------------------------------------------------------------------- |
639 (Info-find-node first second) | 924 ;;;###autoload |
640 (current-buffer)))))) | 925 (defun desktop-revert () |
641 ;; ---------------------------------------------------------------------------- | 926 "Revert to the last loaded desktop." |
642 (defun desktop-buffer-rmail () "Load an RMAIL file." | 927 (interactive) |
643 (if (eq 'rmail-mode desktop-buffer-major-mode) | 928 (unless desktop-dirname |
644 (condition-case error | 929 (error "Unknown desktop directory")) |
645 (progn (rmail-input desktop-buffer-file-name) | 930 (unless (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname)) |
646 (if (eq major-mode 'rmail-mode) | 931 (error "No desktop file found")) |
647 (current-buffer) | 932 (desktop-clear) |
648 rmail-buffer)) | 933 (desktop-read desktop-dirname)) |
649 (file-locked | 934 |
650 (kill-buffer (current-buffer)) | 935 ;; ---------------------------------------------------------------------------- |
651 'ignored)))) | 936 (defun desktop-restore-file-buffer (desktop-buffer-file-name |
652 ;; ---------------------------------------------------------------------------- | 937 desktop-buffer-name |
653 (defun desktop-buffer-mh () "Load a folder in the mh system." | 938 desktop-buffer-misc) |
654 (if (eq 'mh-folder-mode desktop-buffer-major-mode) | 939 "Restore a file buffer." |
655 (progn | 940 (eval-when-compile ; Just to silence the byte compiler |
656 (require 'mh-e) | 941 (defvar desktop-buffer-major-mode) |
657 (mh-find-path) | 942 (defvar desktop-buffer-locals)) |
658 (mh-visit-folder desktop-buffer-name) | |
659 (current-buffer)))) | |
660 ;; ---------------------------------------------------------------------------- | |
661 (defun desktop-buffer-dired () "Load a directory using dired." | |
662 (if (eq 'dired-mode desktop-buffer-major-mode) | |
663 (if (file-directory-p (file-name-directory (car desktop-buffer-misc))) | |
664 (progn | |
665 (dired (car desktop-buffer-misc)) | |
666 (mapcar 'dired-maybe-insert-subdir (cdr desktop-buffer-misc)) | |
667 (current-buffer)) | |
668 (message "Directory %s no longer exists." (car desktop-buffer-misc)) | |
669 (sit-for 1) | |
670 'ignored))) | |
671 ;; ---------------------------------------------------------------------------- | |
672 (defun desktop-buffer-file () "Load a file." | |
673 (if desktop-buffer-file-name | 943 (if desktop-buffer-file-name |
674 (if (or (file-exists-p desktop-buffer-file-name) | 944 (if (or (file-exists-p desktop-buffer-file-name) |
675 (and desktop-missing-file-warning | 945 (let ((msg (format "Desktop: File \"%s\" no longer exists." |
676 (y-or-n-p (format | 946 desktop-buffer-file-name))) |
677 "File \"%s\" no longer exists. Re-create? " | 947 (if desktop-missing-file-warning |
678 desktop-buffer-file-name)))) | 948 (y-or-n-p (concat msg " Re-create? ")) |
679 (let ((buf (find-file-noselect desktop-buffer-file-name))) | 949 (message "%s" msg) |
950 nil))) | |
951 (let* ((auto-insert nil) ; Disable auto insertion | |
952 (coding-system-for-read | |
953 (or coding-system-for-read | |
954 (cdr (assq 'buffer-file-coding-system | |
955 desktop-buffer-locals)))) | |
956 (buf (find-file-noselect desktop-buffer-file-name))) | |
680 (condition-case nil | 957 (condition-case nil |
681 (switch-to-buffer buf) | 958 (switch-to-buffer buf) |
682 (error (pop-to-buffer buf))) | 959 (error (pop-to-buffer buf))) |
960 (and (not (eq major-mode desktop-buffer-major-mode)) | |
961 (functionp desktop-buffer-major-mode) | |
962 (funcall desktop-buffer-major-mode)) | |
683 buf) | 963 buf) |
684 'ignored))) | 964 nil))) |
685 ;; ---------------------------------------------------------------------------- | 965 |
686 ;; Create a buffer, load its file, set is mode, ...; called from Desktop file | 966 (defun desktop-load-file (function) |
687 ;; only. | 967 "Load the file where auto loaded FUNCTION is defined." |
688 | 968 (when function |
689 (defvar desktop-last-buffer nil | 969 (let ((fcell (symbol-function function))) |
690 "Last buffer read. Dynamically bound in `desktop-read'.") | 970 (when (and (listp fcell) |
691 | 971 (eq 'autoload (car fcell))) |
692 (defun desktop-create-buffer (ver desktop-buffer-file-name desktop-buffer-name | 972 (load (cadr fcell)))))) |
693 desktop-buffer-major-mode | 973 |
694 mim pt mk ro desktop-buffer-misc | 974 ;; ---------------------------------------------------------------------------- |
695 &optional locals) | 975 ;; Create a buffer, load its file, set its mode, ...; |
696 (let ((hlist desktop-buffer-handlers) | 976 ;; called from Desktop file only. |
697 (result) | 977 |
698 (handler)) | 978 ;; Just to silence the byte compiler. |
699 (while (and (not result) hlist) | 979 (eval-when-compile |
700 (setq handler (car hlist)) | 980 (defvar desktop-first-buffer)) ; Dynamically bound in `desktop-read' |
701 (setq result (funcall handler)) | 981 |
702 (setq hlist (cdr hlist))) | 982 (defun desktop-create-buffer |
703 (when (bufferp result) | 983 (desktop-file-version |
704 (setq desktop-last-buffer result) | 984 desktop-buffer-file-name |
705 (set-buffer result) | 985 desktop-buffer-name |
706 (if (not (equal (buffer-name) desktop-buffer-name)) | 986 desktop-buffer-major-mode |
707 (rename-buffer desktop-buffer-name)) | 987 desktop-buffer-minor-modes |
708 ;; minor modes | 988 desktop-buffer-point |
709 (cond ((equal '(t) mim) (auto-fill-mode 1)) ; backwards compatible | 989 desktop-buffer-mark |
710 ((equal '(nil) mim) (auto-fill-mode 0)) | 990 desktop-buffer-read-only |
711 (t (mapcar #'(lambda (minor-mode) | 991 desktop-buffer-misc |
712 (when (functionp minor-mode) | 992 &optional |
713 (funcall minor-mode 1))) | 993 desktop-buffer-locals) |
714 mim))) | 994 ;; Just to silence the byte compiler. Bound locally in `desktop-read'. |
715 (goto-char pt) | 995 (eval-when-compile |
716 (if (consp mk) | 996 (defvar desktop-buffer-ok-count) |
717 (progn | 997 (defvar desktop-buffer-fail-count)) |
718 (set-mark (car mk)) | 998 ;; To make desktop files with relative file names possible, we cannot |
719 (setq mark-active (car (cdr mk)))) | 999 ;; allow `default-directory' to change. Therefore we save current buffer. |
720 (set-mark mk)) | 1000 (save-current-buffer |
721 ;; Never override file system if the file really is read-only marked. | 1001 ;; Give major mode module a chance to add a handler. |
722 (if ro (setq buffer-read-only ro)) | 1002 (desktop-load-file desktop-buffer-major-mode) |
723 (while locals | 1003 (let ((buffer-list (buffer-list)) |
724 (let ((this (car locals))) | 1004 (result |
725 (if (consp this) | 1005 (condition-case err |
726 ;; an entry of this form `(symbol . value)' | 1006 (funcall (or (cdr (assq desktop-buffer-major-mode |
727 (progn | 1007 desktop-buffer-mode-handlers)) |
728 (make-local-variable (car this)) | 1008 'desktop-restore-file-buffer) |
729 (set (car this) (cdr this))) | 1009 desktop-buffer-file-name |
730 ;; an entry of the form `symbol' | 1010 desktop-buffer-name |
731 (make-local-variable this) | 1011 desktop-buffer-misc) |
732 (makunbound this))) | 1012 (error |
733 (setq locals (cdr locals)))))) | 1013 (message "Desktop: Can't load buffer %s: %s" |
734 | 1014 desktop-buffer-name |
1015 (error-message-string err)) | |
1016 (when desktop-missing-file-warning (sit-for 1)) | |
1017 nil)))) | |
1018 (if (bufferp result) | |
1019 (setq desktop-buffer-ok-count (1+ desktop-buffer-ok-count)) | |
1020 (setq desktop-buffer-fail-count (1+ desktop-buffer-fail-count)) | |
1021 (setq result nil)) | |
1022 ;; Restore buffer list order with new buffer at end. Don't change | |
1023 ;; the order for old desktop files (old desktop module behaviour). | |
1024 (unless (< desktop-file-version 206) | |
1025 (mapc 'bury-buffer buffer-list) | |
1026 (when result (bury-buffer result))) | |
1027 (when result | |
1028 (unless (or desktop-first-buffer (< desktop-file-version 206)) | |
1029 (setq desktop-first-buffer result)) | |
1030 (set-buffer result) | |
1031 (unless (equal (buffer-name) desktop-buffer-name) | |
1032 (rename-buffer desktop-buffer-name)) | |
1033 ;; minor modes | |
1034 (cond ((equal '(t) desktop-buffer-minor-modes) ; backwards compatible | |
1035 (auto-fill-mode 1)) | |
1036 ((equal '(nil) desktop-buffer-minor-modes) ; backwards compatible | |
1037 (auto-fill-mode 0)) | |
1038 (t | |
1039 (mapc #'(lambda (minor-mode) | |
1040 ;; Give minor mode module a chance to add a handler. | |
1041 (desktop-load-file minor-mode) | |
1042 (let ((handler (cdr (assq minor-mode desktop-minor-mode-handlers)))) | |
1043 (if handler | |
1044 (funcall handler desktop-buffer-locals) | |
1045 (when (functionp minor-mode) | |
1046 (funcall minor-mode 1))))) | |
1047 desktop-buffer-minor-modes))) | |
1048 ;; Even though point and mark are non-nil when written by `desktop-save', | |
1049 ;; they may be modified by handlers wanting to set point or mark themselves. | |
1050 (when desktop-buffer-point | |
1051 (goto-char | |
1052 (condition-case err | |
1053 ;; Evaluate point. Thus point can be something like '(search-forward ... | |
1054 (eval desktop-buffer-point) | |
1055 (error (message "%s" (error-message-string err)) 1)))) | |
1056 (when desktop-buffer-mark | |
1057 (if (consp desktop-buffer-mark) | |
1058 (progn | |
1059 (set-mark (car desktop-buffer-mark)) | |
1060 (setq mark-active (car (cdr desktop-buffer-mark)))) | |
1061 (set-mark desktop-buffer-mark))) | |
1062 ;; Never override file system if the file really is read-only marked. | |
1063 (if desktop-buffer-read-only (setq buffer-read-only desktop-buffer-read-only)) | |
1064 (while desktop-buffer-locals | |
1065 (let ((this (car desktop-buffer-locals))) | |
1066 (if (consp this) | |
1067 ;; an entry of this form `(symbol . value)' | |
1068 (progn | |
1069 (make-local-variable (car this)) | |
1070 (set (car this) (cdr this))) | |
1071 ;; an entry of the form `symbol' | |
1072 (make-local-variable this) | |
1073 (makunbound this))) | |
1074 (setq desktop-buffer-locals (cdr desktop-buffer-locals))))))) | |
1075 | |
1076 ;; ---------------------------------------------------------------------------- | |
735 ;; Backward compatibility -- update parameters to 205 standards. | 1077 ;; Backward compatibility -- update parameters to 205 standards. |
736 (defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name | 1078 (defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name |
737 desktop-buffer-major-mode | 1079 desktop-buffer-major-mode |
738 mim pt mk ro tl fc cfs cr desktop-buffer-misc) | 1080 mim pt mk ro tl fc cfs cr desktop-buffer-misc) |
739 (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name | 1081 (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name |
742 (list (cons 'truncate-lines tl) | 1084 (list (cons 'truncate-lines tl) |
743 (cons 'fill-column fc) | 1085 (cons 'fill-column fc) |
744 (cons 'case-fold-search cfs) | 1086 (cons 'case-fold-search cfs) |
745 (cons 'case-replace cr) | 1087 (cons 'case-replace cr) |
746 (cons 'overwrite-mode (car mim))))) | 1088 (cons 'overwrite-mode (car mim))))) |
747 ;; ---------------------------------------------------------------------------- | 1089 |
748 | 1090 (defun desktop-append-buffer-args (&rest args) |
749 ;; If the user set desktop-enable to t with Custom, | 1091 "Append ARGS at end of `desktop-buffer-args-list'. |
750 ;; do the rest of what it takes to use desktop, | 1092 ARGS must be an argument list for `desktop-create-buffer'." |
751 ;; but do it after finishing loading the init file. | 1093 (setq desktop-buffer-args-list (nconc desktop-buffer-args-list (list args))) |
752 (add-hook 'after-init-hook | 1094 (unless desktop-lazy-timer |
753 '(lambda () | 1095 (setq desktop-lazy-timer |
754 (when desktop-enable | 1096 (run-with-idle-timer desktop-lazy-idle-delay t 'desktop-idle-create-buffers)))) |
755 (desktop-load-default) | 1097 |
756 (desktop-read)))) | 1098 (defun desktop-lazy-create-buffer () |
1099 "Pop args from `desktop-buffer-args-list', create buffer and bury it." | |
1100 (when desktop-buffer-args-list | |
1101 (let* ((remaining (length desktop-buffer-args-list)) | |
1102 (args (pop desktop-buffer-args-list)) | |
1103 (buffer-name (nth 2 args)) | |
1104 (msg (format "Desktop lazily opening %s (%s remaining)..." | |
1105 buffer-name remaining))) | |
1106 (when desktop-lazy-verbose | |
1107 (message "%s" msg)) | |
1108 (let ((desktop-first-buffer nil) | |
1109 (desktop-buffer-ok-count 0) | |
1110 (desktop-buffer-fail-count 0)) | |
1111 (apply 'desktop-create-buffer args) | |
1112 (run-hooks 'desktop-delay-hook) | |
1113 (setq desktop-delay-hook nil) | |
1114 (bury-buffer (get-buffer buffer-name)) | |
1115 (when desktop-lazy-verbose | |
1116 (message "%s%s" msg (if (> desktop-buffer-ok-count 0) "done" "failed"))))))) | |
1117 | |
1118 (defun desktop-idle-create-buffers () | |
1119 "Create buffers until the user does something, then stop. | |
1120 If there are no buffers left to create, kill the timer." | |
1121 (let ((repeat 1)) | |
1122 (while (and repeat desktop-buffer-args-list) | |
1123 (save-window-excursion | |
1124 (desktop-lazy-create-buffer)) | |
1125 (setq repeat (sit-for 0.2)) | |
1126 (unless desktop-buffer-args-list | |
1127 (cancel-timer desktop-lazy-timer) | |
1128 (setq desktop-lazy-timer nil) | |
1129 (message "Lazy desktop load complete") | |
1130 (sit-for 3) | |
1131 (message ""))))) | |
1132 | |
1133 (defun desktop-lazy-complete () | |
1134 "Run the desktop load to completion." | |
1135 (interactive) | |
1136 (let ((desktop-lazy-verbose t)) | |
1137 (while desktop-buffer-args-list | |
1138 (save-window-excursion | |
1139 (desktop-lazy-create-buffer))) | |
1140 (message "Lazy desktop load complete"))) | |
1141 | |
1142 (defun desktop-lazy-abort () | |
1143 "Abort lazy loading of the desktop." | |
1144 (interactive) | |
1145 (when desktop-lazy-timer | |
1146 (cancel-timer desktop-lazy-timer) | |
1147 (setq desktop-lazy-timer nil)) | |
1148 (when desktop-buffer-args-list | |
1149 (setq desktop-buffer-args-list nil) | |
1150 (when (interactive-p) | |
1151 (message "Lazy desktop load aborted")))) | |
1152 | |
1153 ;; ---------------------------------------------------------------------------- | |
1154 ;; When `desktop-save-mode' is non-nil and "--no-desktop" is not specified on the | |
1155 ;; command line, we do the rest of what it takes to use desktop, but do it | |
1156 ;; after finishing loading the init file. | |
1157 ;; We cannot use `command-switch-alist' to process "--no-desktop" because these | |
1158 ;; functions are processed after `after-init-hook'. | |
1159 (add-hook | |
1160 'after-init-hook | |
1161 '(lambda () | |
1162 (let ((key "--no-desktop")) | |
1163 (when (member key command-line-args) | |
1164 (setq command-line-args (delete key command-line-args)) | |
1165 (setq desktop-save-mode nil))) | |
1166 (when desktop-save-mode (desktop-read)))) | |
757 | 1167 |
758 (provide 'desktop) | 1168 (provide 'desktop) |
759 | 1169 |
1170 ;;; arch-tag: 221907c3-1771-4fd3-9c2e-c6f700c6ede9 | |
760 ;;; desktop.el ends here | 1171 ;;; desktop.el ends here |