This post is part of a series about shells in Emacs:
- Painless Emacs shell commands
- Painless Emacs interactive shells
- Emacs shell interpreter configuration
- Painless Emacs remote shells (current)
Remote interactive shells
In a previous post we dealt with spawning interactive shells.
In it, we defined a new function
friendly-shell, an objectively clearer version of
It can be used to easilly define commands for spawning local and remote shells with an arbitrary shell interpreter.
But it can be quite cumbersome to have to define a command for each and every remote connection.
Ideally we’d want a command that prompts for a remote path and spawn a shell there.
Prompting for a remote path
The remote path format understood by Emacs looks like this:
/<method>: prefix is mandatory, required for Emacs to detect that the path is remote.
<method> can have a default value (configured with
tramp-default-method-alist) but the user still need to type in the prefix
/-: to use it.
In the context of a command explicitely prompting for a remote path, it’s quite cumbersome for the user to have to type in this
We want a light wrapper that also supports this more permissive format:
That wrapper is function
friendly-tramp-path-dissect provided by package friendly-tramp-path (source).
Default remote interpreter configuration
Introduced in Emacs 26.2, connection-local vars allow to have a per host interpreter configuration.
Package friendly-shell (source) comes with its own, more versatile, implementation of connection-local vars.
Both options are explained in details in post: Emacs shell interpreter configuration.
Putting it all together
(require 'friendly-tramp-path) (require 'with-shell-interpreter) (require 'prf-shell) (cl-defun friendly-remote-shell (&key path interpreter interpreter-args command-switch w32-arg-quote) (interactive) (let* ((path (or path (read-string "Host: "))) (path (with-shell-interpreter--normalize-path path)) (vec (friendly-tramp-path-dissect path)) (path (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) (tramp-file-name-domain vec) (tramp-file-name-host vec) (tramp-file-name-port vec) (tramp-file-name-localname vec)))) (friendly-shell :path path :interpreter interpreter :interpreter-args interpreter-args :command-switch command-switch :w32-arg-quote w32-arg-quote)))
And voilà! Now to connect to a remote server we just has to type:
M-x friendly-remote-shell <RET> pi@raspberry <RET>
friendly-remote-shell is available with package friendly-remote-shell.