There are many other packages providing similar functionality. See SessionManagement for alternatives.
Desktop will load, at startup, the buffers you were editing when you last quit Emacs.
In Emacs 22+, add the following to your .emacs file:
You can add any extra variables you want saved across sessions to the list
‘desktop-globals-to-save’. For example:
(setq history-length 250) (add-to-list 'desktop-globals-to-save 'file-name-history)
In Emacs 20 and 21, use code like the following, instead:
;; Customization goes between desktop-load-default and desktop-read (setq history-length 250) (add-to-list 'desktop-globals-to-save 'file-name-history)
(desktop-read) (setq desktop-enable t)
You can specify buffers which should not be saved, by name or by mode, e.g.:
(setq desktop-buffers-not-to-save (concat "\\(" "^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS" "\\|\\.emacs.*\\|\\.diary\\|\\.newsrc-dribble\\|\\.bbdb" "\\)$")) (add-to-list 'desktop-modes-not-to-save 'dired-mode) (add-to-list 'desktop-modes-not-to-save 'Info-mode) (add-to-list 'desktop-modes-not-to-save 'info-lookup-mode) (add-to-list 'desktop-modes-not-to-save 'fundamental-mode)
Since all lists will be truncated when saved, it is important to have a high default history length, for example. If that is not enough, follow the suggestions in the doc-string of
I’m starting to work on a new package called desktop-recover.el with some improvements like this. Alternatively, you can just add something like this to your init file to auto-save your desktop when Emacs is idle: – Doom
(require 'desktop) (desktop-save-mode 1) (defun my-desktop-save () (interactive) ;; Don't call desktop-save-in-desktop-dir, as it prints a message. (if (eq (desktop-owner) (emacs-pid)) (desktop-save desktop-dirname))) (add-hook 'auto-save-hook 'my-desktop-save)
The above doesn’t seem to work when emacs is run in daemon mode (--daemon)
If you are using desktop-mode and your emacs crashes (or more likely, your system crashes), then your desktop file will not be released, and emacs will bother you about using it next time you start it up. To avoid this, I wrote the following code to override the lock on a desktop file if the indicated process is not still running.
;;; desktop-override-stale-locks.el begins here (defun emacs-process-p (pid) "If pid is the process ID of an emacs process, return t, else nil. Also returns nil if pid is nil." (when pid (let* ((cmdline-file (concat "/proc/" (int-to-string pid) "/cmdline"))) (when (file-exists-p cmdline-file) (with-temp-buffer (insert-file-contents-literally cmdline-file) (goto-char (point-min)) (search-forward "emacs" nil t) pid))))) (defadvice desktop-owner (after pry-from-cold-dead-hands activate) "Don't allow dead emacsen to own the desktop file." (when (not (emacs-process-p ad-return-value)) (setq ad-return-value nil))) ;;; desktop-override-stale-locks.el ends here
If anyone has a more robust implementation of `emacs-process-p,’ feel free to provide it.
‘emacs-process-p’ by following way, it could work on both Windows and Linux.
(defun emacs-process-p (pid) "If pid is the process ID of an emacs process, return t, else nil. Also returns nil if pid is nil." (when pid (let ((attributes (process-attributes pid)) (cmd)) (dolist (attr attributes) (if (string= "comm" (car attr)) (setq cmd (cdr attr)))) (if (and cmd (or (string= "emacs" cmd) (string= "emacs.exe" cmd))) t))))
I think the original function contains an error. Should it not end something like:
(when (search-forward "emacs" nil t) pid))))))
This is for people who only want minimal session management functionality, and don’t want their previous sessions automatically restored at start-up. Note that you need desktop-save-mode NOT ENABLED for this to work as intended.
It works for me with one desktop, with more than one may need some tweaking.
;; use only one desktop (setq desktop-path '("~/.emacs.d/")) (setq desktop-dirname "~/.emacs.d/") (setq desktop-base-file-name "emacs-desktop") ;; remove desktop after it's been read (add-hook 'desktop-after-read-hook '(lambda () ;; desktop-remove clears desktop-dirname (setq desktop-dirname-tmp desktop-dirname) (desktop-remove) (setq desktop-dirname desktop-dirname-tmp))) (defun saved-session () (file-exists-p (concat desktop-dirname "/" desktop-base-file-name))) ;; use session-restore to restore the desktop manually (defun session-restore () "Restore a saved emacs session." (interactive) (if (saved-session) (desktop-read) (message "No desktop found."))) ;; use session-save to save the desktop manually (defun session-save () "Save an emacs session." (interactive) (if (saved-session) (if (y-or-n-p "Overwrite existing desktop? ") (desktop-save-in-desktop-dir) (message "Session not saved.")) (desktop-save-in-desktop-dir))) ;; ask user whether to restore desktop at start-up (add-hook 'after-init-hook '(lambda () (if (saved-session) (if (y-or-n-p "Restore desktop? ") (session-restore)))))
‘M-x session-save’, or
‘M-x session-restore’ whenever you want to save or restore a desktop. Restored desktops are deleted from disk.
The usual way to use a desktop is to (1) define (i.e., save) it as your final Emacs state, when you exit, and (2) restore it at the beginning of a new Emacs session. Library
desktop.el provides for the possibility of having multiple saved desktops, but only one per directory. It searches your
‘desktop-path’ to find a desktop file to load.
If you use Bookmark+, then you can have any number of desktops and use them as bookmarks, jumping from one to another at any time. You create a desktop bookmark using
‘C-x r K’ (command
Ordinary desktop files are used to record the information. The bookmark itself records only the location of the desktop file. Bookmarked desktops are intended to be used only as bookmarks, not in the ordinary way (e.g. at Emacs startup), so the locations of the desktop files used are unimportant. In particular, you can have any number of (bookmark) desktop files per directory.
Something to keep in mind is that all enabled modes for a buffer are saved in the desktop file, and re-enabled when restoring, and global modes in particular have the potential to cause performance issues.
global-whitespace-mode is a current example – when you enable it, it processes every buffer. As the mode is active for all buffers, it will be listed against every buffer in the desktop file, and hence the processing done by this mode when restoring n buffers is an o(n^2) operation.
(The desktop-minor-mode-table variable looks like it provides a workaround for this problem, by enabling you to specify a ‘nil’ custom handler for modes which should not be enabled when restoring the desktop.)
I’m having trouble with desktop loading lazy loading, as my final line in .emacs is
So it loads planner, but then the planner buffer gets lost when desktop starts restoring the other buffers. I tried to set desktop-restore-eager to ‘t, without any success. Any idea?
Yup, I’ve been able to solve this problem just using
(add-hook 'desktop-after-read-hook 'plan)
When I try to add an array of strings to desktop-globals-to-save it saves it with (setq name-of-array “Unprintable entity”). Has anyone an idea of how to save an array in desktop?
I could set up desktop-files-not-to-save var for any buffer opening remote file not to be saved into .emacs.desktop file while invoking (desktop-save) with its default value ("^/[^/:]*:").
In the same time, I also want save dired-mode buffers except buffers that show remote directories. I found that desktop package only check its (buffer-file-name) and (buffer-name) whether he save a ceratain buffer or not, and unfortunately (buffer-file-name) has no meaning in dired-mode buffer(it just returns nil) so finally… dired-mode buffer displaying remote directory is saved in .emacs.desktop file. How can I exclude those kind of dired-mode buffers? --JoonhwanLee
Great entry! Thanks. I had been using recentf, but desktop is more up my alley – TerrenceBrannon
On Emacs 21.4 (from Debian Etch) the desktop does not work as expected. The only way I could make it work was with
(load-library "/usr/share/emacs/21.4/lisp/desktop.elc") (setq desktop-enable t)
in my .emacs. – Randolf Schultz
A simple example of moving the desktop file save locations ~/.emacs.desktop(.lock) to ~/.emacs.d/desktop/emacs.desktop(.lock) would be very helpful.
Presuming you want to MOVE (ie you’ve already used desktop) then the steps I did for this are
‘M-x desktop-save’and emacs asks you for a
‘Directory to save desktop file’, so enter your new location
‘setq desktop-path ’(”~/.emacs.d/desktop”))’ in your .emacs, or set it by
‘M-h v desktop-path’and then choose the Customise option, set the value and “Save for future session”
And that was me all done – TimMeadowcroft
Look, let’s just be honest. It doesn’t work, does it?
/usr/bin/emacs --no-desktop eventually results in
Debugger entered--Lisp error: (error "Desktop file conflict") signal(error ("Desktop file conflict")) error("Desktop file conflict") desktop-save("/home/jg/.desktop/") desktop-save-in-desktop-dir() (lambda nil (desktop-save-in-desktop-dir))() run-hooks(auto-save-hook)
and the request
Current desktop was not loaded from a file. Overwrite this desktop file? (y or n)
which is is impossible to say ‘n’ to! (Pressing ‘n’ simply repeats the message.)
Let’s just dump this in a sack in the local canal.
Not sure where to mention this but I recommend adding the &optional release argument to the desktop-save-in-desktop-dir. This can then be passed through to save-desktop if desired. I have manually added this into my distribution and causes no issues anywhere else. I think it should be added as below.
(defun desktop-save-in-desktop-dir (&optional release) "Save the desktop in directory `desktop-dirname'." (interactive) (if desktop-dirname (desktop-save desktop-dirname release) (call-interactively 'desktop-save)) (message "Desktop saved in %s" (abbreviate-file-name desktop-dirname)))
Is there any way not to save the list of activated minor modes? I just want to revisit the list of files. – Kiwon
Here’s what I do to solve that problem:
(loop for mode in minor-mode-list do (add-to-list 'desktop-minor-mode-table (list mode nil)))
Be sure to require all of the minor modes you use, and put this at the bottom!