Fish EDITOR environment variable does not seem to work
I recently started using the Fish shell.
echo $EDITOR
returns vim
But yet, when using programs that need to launch an editor and look for it in the EDITOR
environment variable they don’t seem to find anything.
As an example when using pass edit
(from https://www.passwordstore.org/) it returns
vi: command not found
(it uses vi as a fallback when nothing is set in the EDITOR
env variable)
What did I miss?
Note that a few programs look for the $VISUAL
environment variable before the $EDITOR
environment variable, so if you have both set, $VISUAL
will take precedence.
Also note that shell variables are just that, variables in the shell language. You’d need to call commands with EDITOR=preferred-editor
in their environment for them to pick it up.
Shells can map some of their variables to environment variables that are then passed as var=value
in the environment of all the commands they execute. In rc
-like shells, that’s done for all shell variables, in Bourne-like shells, that’s done with export var
. In csh
, you use setenv var value
to set an environment variable. In fish
, you use the -x
option of set
:
> set var value
> echo $var
value
> printenv var
>
A $var
shell variable was set, but not exported (as var=value
) to the environment passed to printenv
.
> set -x var value2
> echo $var
value2
> printenv var
value2
This time, printenv
did get a var=value2
in the environment it received.
printenv
is not a standard command but is commonly available. env
is a standard command, so if your system doesn’t have printenv
, you could try:
env | grep -E '^(VISUAL|EDITOR)='
Though it could be fooled if you had variables with values such as var=<newline>VISUAL=
or values larger than LINE_MAX
.
Other options could be:
perl -le 'print $ENV{VISUAL}'
python -c 'import os; print(os.getenv("VISUAL"))'
Also note that though it is highly unlikely to be the case here, it is possible to execute a command with more than one var=value
for a given var
in their environment.
For instance, you could do
execve("/path/to/cmd", ["cmd", "some arg"], ["VISUAL=vi", "VISUAL=emacs"])
What value cmd
will consider the VISUAL
environment variable as having will depend on how they scan that env var list they received upon exceve()
. You’ll find that some commands / libraries (like libc
‘s getenv()
) will pick the first while some will pick the last. Some shells will map one of them to their corresponding env var but may leave the other one around and passed along in further executions.
So you could be doing set -x VISUAL vim
, and printenv
seeing emacs
because fish
was executed with both VISUAL=vi
and VISUAL=emacs
and only modified the first VISUAL
whilst printenv
gives you the second.
For this kind of thing to happen though, you’d need something or someone actively trying to trick you, and after double checking, it seems fish
is one of those shells that do remove the duplicates from the environment if any.