You can use the desktop package to save the state of Emacs sessions, i.e. which files are open, where point is in them and so on. This is cool, but it saves the information in the current directory, which can be inconvenient. What would be better is if you could save the session by name, like "task-a" or "project-b".
I originally wrote some elisp to do this in answer to a StackOverflow question, but found it so useful myself that I expanded it to do more. The code is below, but here are the commands:
- my-desktop-save -- Save the current session by name
- my-desktop-save-and-clear -- Same as above, but clear out all the buffers so you start with a "clean" session
- my-desktop-read -- Load a session by name
- my-desktop-change -- Save the current session and load a different one
- my-desktop-name -- Echo the current session name
(require 'desktop) (defvar my-desktop-session-dir (concat (getenv "HOME") "/.emacs.d/desktop-sessions/") "*Directory to save desktop sessions in") (defvar my-desktop-session-name-hist nil "Desktop session name history") (defun my-desktop-save (&optional name) "Save desktop by name." (interactive) (unless name (setq name (my-desktop-get-session-name "Save session" t))) (when name (make-directory (concat my-desktop-session-dir name) t) (desktop-save (concat my-desktop-session-dir name) t))) (defun my-desktop-save-and-clear () "Save and clear desktop." (interactive) (call-interactively 'my-desktop-save) (desktop-clear) (setq desktop-dirname nil)) (defun my-desktop-read (&optional name) "Read desktop by name." (interactive) (unless name (setq name (my-desktop-get-session-name "Load session"))) (when name (desktop-clear) (desktop-read (concat my-desktop-session-dir name)))) (defun my-desktop-change (&optional name) "Change desktops by name." (interactive) (let ((name (my-desktop-get-current-name))) (when name (my-desktop-save name)) (call-interactively 'my-desktop-read))) (defun my-desktop-name () "Return the current desktop name." (interactive) (let ((name (my-desktop-get-current-name))) (if name (message (concat "Desktop name: " name)) (message "No named desktop loaded")))) (defun my-desktop-get-current-name () "Get the current desktop name." (when desktop-dirname (let ((dirname (substring desktop-dirname 0 -1))) (when (string= (file-name-directory dirname) my-desktop-session-dir) (file-name-nondirectory dirname))))) (defun my-desktop-get-session-name (prompt &optional use-default) "Get a session name." (let* ((default (and use-default (my-desktop-get-current-name))) (full-prompt (concat prompt (if default (concat " (default " default "): ") ": ")))) (completing-read full-prompt (and (file-exists-p my-desktop-session-dir) (directory-files my-desktop-session-dir)) nil nil nil my-desktop-session-name-hist default))) (defun my-desktop-kill-emacs-hook () "Save desktop before killing emacs." (when (file-exists-p (concat my-desktop-session-dir "last-session")) (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name (concat my-desktop-session-dir "last-session")))))) (my-desktop-save "last-session")) (add-hook 'kill-emacs-hook 'my-desktop-kill-emacs-hook)