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?

Asked By: bastian

||

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.

Answered By: Stéphane Chazelas
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.