Helper for Emacs shell command APIs, making implicit argument as explicit keyword arguments.
This package is a library and does not provide any command.
It is inspired by the eval-after-load
/ with-eval-after-load
functions.
It does the heavy lifting behind packages friendly-shell-command and friendly-shell.
For more context, read the accompanying blog post.
The package is available on Melpa.
With use-package
:
(use-package with-shell-interpreter)
Manually:
M-x package-install with-shell-interpreter
We recommend using the macro with-shell-interpreter
. It's a more convenient version of with-shell-interpreter-eval
that prevents having to quote :form and wrap it in a progn
.
default-directory
❌ The path from which to eval. :interpreter explicit-shell-file-name
/ shell-file-name
❌ Name or absolute path of shell interpreter executable. :interpreter-args explicit-INTEPRETER-args
❌ Login args to call interpreter with for login. :command-switch shell-command-switch
❌ Command switch arg for asking interpreter to run a shell command. :w32-arg-quote w32-quote-process-args
❌ Character to use for quoting shell arguments (only on the Windows build of Emacs) :allow-local-vars n/a ❌ Whether to allow buffer-local and/or connection-local values
:form is expected to contain calls to functions relying on the Emacs shell APIs (e.g. shell
, shell-command
, async-shell-command
and shell-command-to-string
).
Setting :path to a remote location (with TRAMP format, i.e. /<method>:<user>@<host>:<localname>
) allows running form with interpreter of remote server.
:interpreter-args is only usefull for interactive shells (from package shell-mode).
:command-switch is only usefull for single shell commands (from package simple).
:allow-local-vars can take the following values:
If left empty, here are the default values being used:
keyword argument fallback value (local path) fallback value (remote path) :path currentdefault-directory
current default-directory
:interpreter shell-file-name
with-shell-interpreter-default-remote
:interpreter-args explicit-INTEPRETER-args
if set with-shell-interpreter-default-remote-args
:command-switch shell-command-switch
with-shell-interpreter-default-remote-command-switch
:w32-arg-quote w32-quote-process-args
w32-quote-process-args
:allow-local-vars nil 'connection
Getting the temperature from a Raspberry Pi:
(with-shell-interpreter :path "/ssh:pi@raspberry:/~" :interpreter "bash" :form (shell-command-to-string "vcgencmd measure_temp"))
Under Microsoft Windows, launching an interactive shell with the git-bash interpreter:
(with-shell-interpreter :path "~" ; ensure local path :interpreter "C:/Program Files/Git/bin/bash.exe" :form (let (current-prefix-arg '(4)) ; don't prompt user for interpreter (shell)))
For more practical examples, have a look at packages friendly-shell-command and friendly-shell (examples).
Per connection default configurationWe generally want to have different values for remote connection as the user might have redefined the value of shell-file-name
with something exotic (e.g. zsh) and we would want a safer default for remote servers.
Furthermore, under Microsoft Windows, shell-file-name
defaults to cmdproxy.exe which is OK for local shells but sucks for remote ones...
We can of course use the :interpreter, :interpreter-args and :command-switch keyword parameters but it's cumbersome to define a function for each remote connection with a custom configuration.
Instead, the preferred way is to rely on connection-local variables.
with-shell-interpreter
comes by default with its own custom implementation of connection-local variables. It can be configured with var with-shell-interpreter-connection-local-vars
.
It comes with a fallback entry for default configuration of remote interpreters:
'((".*" . ((explicit-shell-file-name . "/bin/bash") (explicit-bash-args . ("-c" "export EMACS=; export TERM=dumb; stty echo; bash")) (shell-command-switch . "-c"))))
To add an entry, just:
(add-to-list with-shell-interpreter-connection-local-vars '(".*@openwrt") . ((explicit-shell-file-name . "/bin/ash") (explicit-bash-args . ("-i")) (shell-command-switch . "-c")))
Alternatively, you can instead choose to use Emacs' native implementation (more restrictive and cumbersome to configure):
(setq with-shell-interpreter-connection-local-vars-implem 'native)
The native implementation is only available since Emacs 26.1. Read docstrings of connection-local-set-profiles
and connection-local-set-profile-variables
for more details about it.
You might want to change the value of tramp-default-user
if you usually connect to remote host with a user different than your local one.
This code uses form feeds (^L
character) as separators.
Either package form-feed or page-break-lines makes them appear as intended.
Package lisp-extra-font-lock is also recommended to distinguish between local and global vars in let expressions.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4