Following my last article on restoring window configurations with custom functions, Clément Pit-Claudel got in touch with me and suggested a little improvement. Clément pointed out the built-in Emacs command winner-undo, which I promptly used to simplify my solution.

Let’s enable winner-mode, first, because winner-undo comes with it.

(use-package winner                     ; Restore old window configurations
:init (winner-mode t))


winner-mode automatically takes care of storing window configurations, thus I can safely remove functions like mu-ibuffer-open.

Now I only need to call winner-undo when I exit the desired, fullframed buffer1.

(defun mu-pop-window-configuration ()
"Kill current buffer and restore the previous window configuration."
(interactive)
(kill-this-buffer)
(let ((inhibit-message t))
(winner-undo)))


I wrapped (winner-undo) with (inhibit-message t) to get rid of the superfluous message about the restored window configuration number.

This is a much cleaner solution. I still have to use fullframe, of course, but by reusing an inner Emacs functionality I get the same result with less code.

However, this code has a problem. winner-mode does not save the configuration of a frame with a single window. In this case winner-undo has nothing to undo and it usually takes me back to a completely different buffer than the one I started from.

Therefore I revised my functions and made them a bit more general. Basically, I removed mu-push-window-configuration and added mu-save-wins-then-call.

(defun mu-save-wins-then-call (func &optional args)
"Save current window configuration, then call FUNC optionally with ARGS."
(interactive)
(push (current-window-configuration) mu-saved-window-configuration)
(cond
;; We have arguments for the function
((bound-and-true-p args) (funcall func args))
;; The function requires exactly one argument, and we want it to be nil
((equal args "nil") (funcall func nil))
;; The function does not expect arguments
(t (funcall func))))


The "nil" check is kind of a hack just for paradox-list-packages, which expects one non-optional argument. Since &optional args evaluates to nil when non present, I need the check to avoid calling (funcall func) in this particular case. I am sure there is a better solution, but I’ll leave that for another time.

Nonetheless, functions like the previously mentioned mu-ibuffer-open becomes cleaner.

(defun mu-ibuffer-open ()
"Save window configuration and call ibuffer'."
(interactive)
(mu-save-wins-then-call 'ibuffer))

(defun mu-elfeed-open ()
"Save window configuration and call elfeed'."
(interactive)
(mu-save-wins-then-call 'elfeed))

"Save window configuration and call paradox-list-packages'."
`