Assume you have a favorite window arrangement – an IRC buffer on the left, the calendar at the top right, and a text file at the bottom right. When you start reading news in Gnus, this window configuration will be changed.

A simple way to deal with this is to use registers. Store your favorite window configurations in registers, and jump to them later. This is the easiest solution if you’ve been using registers for other things, too.

Registers are referred to by a single character, therefore, you can use register 1, 2, a, b, etc.


It would be nice if Emacs saved the configurations in a file after exiting, especially in combination with SessionManagement. has example code in e-common.el, which detects if you are in a GUI environment. When you run the ediff command, it widens Emacs to 2 side-by-side windows. When you are done, EMacro restores Emacs to its previous size.

See also: FramesAndRegisters for similar commands for saving and restoring frame configurations.

Here is a workspace implementation, working as workspaces on windows managers. That means that you have 9 workspaces, from 1 to 9, and you can switch from one to another, they are alway saved.

    ;; VARIABLES ;;
    (defvar workspaces-list nil)
    (defvar workspaces-are-initialized nil)
    (global-set-key "\C-zd" 'workspace-goto)
    ;; FUNCTIONS ;;
    (defun workspace-create-new (deskid)
      "Create a blank workspace at id deskid, between 1 and 9"
      (interactive "cWhat ID do you want to give to blank workspace ?")
      (workspace-goto ?0)
      (window-configuration-to-register deskid)
      (add-to-list 'workspaces-list deskid)
      (workspace-goto deskid))
    (defun workspace-goto (deskid)
      "Go to another workspace, deskid is workspace number between 1 and 9;
    Workspace 0 is a template workspace, do not use it unless you know what you do;
    You can kill a workspace with 'k' and fallback on 1."
      (interactive "cTo which workspace do you want to go ? ")
      (let (add)
        (setq add (if (eq deskid ?0) "\n!-!-! This is template workspace. New workspaces are based on it. " nil))
         ((and (>= deskid ?0) (<= deskid ?9))
          (if (or (member deskid workspaces-list) (eq deskid ?0))
    	    (window-configuration-to-register current-workspace)
    	    (setq current-workspace deskid)
    	    (jump-to-register deskid))
    	(if (y-or-n-p "This workspace does not exist, should it be created ? ")
    	      (window-configuration-to-register current-workspace)
    	      (workspace-create-new deskid))
         ((and (eq deskid ?k) (not (or (eq current-workspace ?0) (eq current-workspace ?1))))
          (let ((deskid-to-del current-workspace))
    	(workspace-goto ?1)
    	(setq workspaces-list (remove deskid-to-del workspaces-list))))
         (t (setq add "\n!-!-! Please specify a valid workspace number in (1-9), 0 do edit template, 'k' to kill current workspace in (2-9)")))
        (message (concat "Now on workspace " (char-to-string current-workspace) "\nWorkspaces list is : " (mapconcat 'char-to-string (sort (copy-sequence workspaces-list) '<) ", ") add))))
    ;; HOOKS ;;
    ;; un bureau est cree au premier chargement seulement
    (unless workspaces-are-initialized
      (window-configuration-to-register ?0)
      (setq current-workspace ?0)
      (workspace-create-new ?1)
      (setq workspaces-are-initialized t))