docs: improve set -Ux language and example

By far the most common problem with universal variables being overridden
by global variables is other values being imported from the environment;
the `set -q; or set -gx` is much more of an edge case.
This commit is contained in:
David Adam 2017-08-10 13:14:20 +08:00 committed by Kurtis Rader
parent 74f0be2a53
commit 7b92217273

View File

@ -14,7 +14,7 @@
- <a href='#faq-subcommand'>How do I run a subcommand? The backtick doesn't work!</a>
- <a href='#faq-exit-status'>How do I get the exit status of a command?</a>
- <a href='#faq-single-env'>How do I set an environment variable for just one command?</a>
- <a href='#faq-exported-uvar'>Why doesn't `set -Ux` (exported universal vars) seem to work?</a>
- <a href='#faq-exported-uvar'>Why doesn't `set -Ux` (exported universal varables) seem to work?</a>
- <a href='#faq-customize-colors'>How do I customize my syntax highlighting colors?</a>
- <a href='#faq-update-manpage-completions'>How do I update man page completions?</a>
- <a href='#faq-cwd-symlink'>Why does cd, pwd and other fish commands always resolve symlinked directories to their canonical path?</a>
@ -126,19 +126,27 @@ begin
end
\endfish
\section faq-exported-uvar Why doesn't `set -Ux` (exported universal vars) seem to work?
\section faq-exported-uvar Why doesn't `set -Ux` (exported universal variables) seem to work?
Lots of users try to set exported environment variables like `EDITOR` and `TZ` as universal variables; e.g., `set -Ux`. That works but the behavior can be surprising. Keep in mind that when resolving a variable reference (e.g., `echo $EDITOR`) fish first looks in local scope, then global scope, and finally universal scope. Also keep in mind that environment vars imported when fish starts running are placed in the global scope. So if `EDITOR` or `TZ` is already in the environment when fish starts running your universal var by the same name is not used.
A global variable of the same name already exists.
The recommended practice is to not export universal variables in the hope they will be present in all future shells. Instead place statements like the following example in your config.fish file:
Environment variables such as `EDITOR` or `TZ` can be set universally using `set -Ux`. However, if
there is an environment variable already set before fish starts (such as by login scripts or system
administrators), it is imported into fish as a global variable. The <a
href="index.html#variables-scope">variable scopes</a> are searched from the "inside out", which
means that local variables are checked first, followed by global variables, and finally universal
variables.
This means that the global value takes precedence over the universal value.
To avoid this problem, consider changing the setting which fish inherits. If this is not possible,
add a statement to your <a href="index.html#">user initilization file</a> (usually
`~/.config/fish/config.fish`):
\fish{cli-dark}
set -q EDITOR
or set -gx EDITOR vim
set -gx EDITOR vim
\endfish
Now when fish starts it will use the existing value for the variable if it was in the environment. Otherwise it will be set to your preferred default. This allows programs like emacs or an IDE to start a fish shell with a different value for the var. This is effectively the same behavior seen when setting it as a uvar but is explicit and therefore easier to reason about and debug. If you don't want to allow using the existing environment value just unconditionally `set -gx` the var in your config.fish file.
\section faq-customize-colors How do I customize my syntax highlighting colors?
Use the web configuration tool, <a href="commands.html#fish_config">`fish_config`</a>, or alter the <a href="index.html#variables-color">`fish_color` family of environment variables</a>.