This article is part of a multi-post series about how to better deal with interactive shell buffers in Emacs:
Quitting a shell
On some terminal emulators, when the spawned process dies, the terminal window does not close.
<Return> can bring the process back from the dead1.
This is notably the case when using KiTTY2 to access a remote server (via SSH).
But Emacs doesn’t work exactly that way.
The buffer stays open but is basically useless.
shx to the rescue
Package shx.el offer many goodies enhancing the user experience of interactive shell in Emacs.
One of its little-known feature is the ability to resurrect shell buffers!
It works right out of the box, you just have to add this to your config3:
(use-package shx :disabled :hook (shell-mode . shx-mode)
And once a shell buffer is dead, just press
<Return> to resurrect its shell!
So let’s assumed that you’ve spawn a shell with a non-default interpreter (
zsh instead of
(let ((explicit-shell-file-name "zsh")) (shell))
If the process dies and after attempting to respawn it with shx, we’ll end up with a
In fact this is because shx doesn’t have any knowledge of the interpreter being used for the shell.
This is not a limitation in the package but of Emacs itself. More precisely, shell-mode does not keep track of the connection parameters in any buffer-local variable.
Everything works fine for static declaration of interpreters (read Emacs shell interpreter configuration for more details) but as soon as we start to bind things dynamically Emacs looses track.
That’s were friendly-shell4 shines.
When invoking a shell with
(defun my-zsh-on-raspi () (interractive) (friendly-shell :path "/ssh:pi@raspberry:/~" :interpreter "zsh"))
… the interpreter-related vars have their values preserved as buffer-local vars!
This way, shx can find them back and dynamically spawned buffer can be resurrected with the right interpreter with no additional trick.
Spawn a new one in fact, but for the user it appears as if it was the same being resurected. ↩