On most Unix systems, there are two environment variables that control the user’s choice of text editor: EDITOR and VISUAL. They have different historical purposes, but are generally interchangeable today.

EDITOR is the older variable, and the one you should generally set if you only set one. It lists the name of your text editor, optionally with flags.

VISUAL is a bit different. If it’s set, it overrides EDITOR, unless you’re using a dumb terminal. When vi was created, people would set their EDITOR value to ex and VISUAL to vi. If they were on a dumb terminal, they’d get ex, but if they were on a terminal with graphics support, they’d get vi.

Nowadays, just setting EDITOR is fine, since you’re practically never going to run into a dumb terminal (unless you use gvim’s :shell command). However, your editor should be a value that stays in the foreground until you quit it; otherwise, most tools (including Git) will assume you haven’t edited the file. If you use gvim, like me, then you need to set EDITOR to gvim -f.

If the user hasn’t specified EDITOR or VISUAL, the default is vi. That’s a particularly cruel and heartless default for newbies, but it’s what people expect when working on Unix systems. Defaulting to something else means that people who need to run an occasional editor-invoking command on an infrequently accessed server will be surprised. Sysadmins don’t like surprises.

There’s frequently confusion as to whether the variables should be interpreted by the shell. The answer is emphatically yes, for several reasons. First, if your program doesn’t pass the command to the shell, people have to use shell scripts to get things like gvim -f to work. Second, on some platforms, like Cygwin, using commands with spaces in the path is quite common, and using shell interpretation allows a standard way to make that work.

Finally, Debian’s sensible-editor helper and Git pass the command to the shell. Since Debian recommends the sensible-editor script for packages by default, other packages should emulate its behavior. Similarly, Git is a tool that’s widely deployed, and it also invokes the shell.

It’s tempting to want to parse the command yourself with a shellword parsing library in your language of choice, but it’s valid to put a small amount of literal shell scripting in the variable. You really do need to invoke the shell in order to handle things correctly, and it should be the default POSIX shell on your system (usually /bin/sh).

If you’re interested in how Git implements this, you can look at its editor.c file, which provides the (relatively simple) logic. If you have a Debian or Ubuntu system, /usr/bin/sensible-editor demonstrates how to do it in shell.