Not being able to delete these for good (if unused) seems to be
a nuisance. Let's go back to storing universal __fish_initialized
also on fresh installations, which I guess is a small price to to
avoid recreating these files.
Closes#12230
Implicitly-universal variables have some downsides:
- It's surprising that "set fish_color_normal ..."
and "set fish_key_bindings fish_vi_key_bindings" propagate to other
shells and persist, especially since all other variables (and other
shells) would use the global scope.
- they don't play well with tracking configuration in Git.
- we don't know how to roll out updates to the default theme (which is
problematic since can look bad depending on terminal background
color scheme).
It's sort of possible to use only globals and unset universal variables
(because fish only sets them at first startup), but that requires
knowledge of fish internals; I don't think many people do that.
So:
- Set all color variables that are not already set as globals.
- To enable this do the following, once, after upgrading:
copy any existing universal color variables to globals, and:
- if existing universal color variables exactly match
the previous default theme, and pretend they didn't exist.
- else migrate the universals to ~/.config/fish/conf.d/fish_frozen_theme.fish,
which is a less surprising way of persisting this.
- either way, delete all universals to do the right thing for most users.
- Make sure that webconfig's "Set Theme" continues to:
- instantly update all running shells
- This is achieved by a new universal variable (but only for
notifying shells, so this doesn't actually need to be persisted).
In future, we could use any other IPC mechanism such as "kill -SIGUSR1"
or if we go for a new feature, "varsave" or "set --broadcast", see
https://github.com/fish-shell/fish-shell/issues/7317#issuecomment-701165897https://github.com/fish-shell/fish-shell/pull/8455#discussion_r757837137.
- persist the theme updates, completely overriding any previous theme.
Use the same "fish_frozen_theme.fish" snippet as for migration (see above).
It's not meant to be edited directly. If people want flexibility
the should delete it.
It could be a universal variable instead of a conf snippet file;
but I figured that the separate file looks nicer
(we can have better comments etc.)
- Ask the terminal whether it's using dark or light mode, and use an
optimized default. Add dark/light variants to themes,
and the "unknown" variant for the default theme.
Other themes don't need the "unknown" variant;
webconfig already has a background color in context,
and CLI can require the user to specify variant explicitly if
terminal doesn't advertise colors.
- Every variable that is set as part of fish's default behavior
gets a "--label=default" tacked onto it.
This is to allow our fish_terminal_color_theme event handler to
know which variables it is allowed to update. It's also necessary
until we revert 7e3fac561d (Query terminal only just before reading
from it, 2025-09-25) because since commit, we need to wait until
the first reader_push() to get query results. By this time, the
user's config.fish may already have set variables.
If the user sets variables via either webconfig, "fish_config theme
{choose,save}", or directly via "set fish_color_...", they'd almost
always remove this label.
- For consistency, make default fish_key_bindings global
(note that, for better or worse, fish_add_path still remains as
one place that implicitly sets universal variables, but it's not
something we inject by default)
- Have "fish_config theme choose" and webconfig equivalents reset
all color variables. This makes much more sense than keeping a
hardcoded subset of "known colors"; and now that we don't really
expect to be deleting universals this way, it's actually possible
to make this change without much fear.
Should have split this into two commits (the changelog entries are
intertwined though).
Closes#11580Closes#11435Closes#7317
Ref: https://github.com/fish-shell/fish-shell/issues/12096#issuecomment-3632065704
This mode still has some problems (see the next commit) but having
it behind a feature flag doesn't serve us. Let's commit to the parts
we want to keep and drop anything that we don't want.
To reduce diff noise, use "if false" in the code paths used by man
pages; a following commit will use them.
We use absence of "$__fish_data_dir[1]" as criteria to use the
"standalone" code paths that use "status list-files/get-file" instead
of $__fish_data_dir.
However, third party software seems slow to react to such breaking
changes, see https://github.com/ajeetdsouza/zoxide/issues/1045
So keep $__fish_data_dir for now to give plugins more time.
This commit makes us ignore $__fish_data_dir on standalone builds
even if defined; a following commit will actually define it again.
I guess the approach in b815fff292 (Set $__fish_data_dir to empty
for embed-data builds, 2025-04-01) made sense back when we didn't
anticipate switching to standalone builds by default yet.
Today, this file is only supported in CMake builds. This is the only
place where CMake builds currently need $__fish_data_dir as opposed
to using "status get-file".
Let's embed __fish_build_paths so we can treat it like other assets.
This enables users of "embed-data" to do "rm -rf $__fish_data_dir"
(though that might break plugins).
These builds do not use it, and setting it makes it possible to use
stale files.
So instead, we set it to empty. All uses I could find are either fine
with that (`set fish_function_path $__fish_data_dir/functions` - which
would also just be empty, which means it reads the embedded
functions),
or would break even if the variable was set but the directory was
empty (`source $__fish_data_dir/completions/git.fish`).
This is the most common and sensible env var, we check it outside,
so we can skip loading the function at all if we already know it's not
gonna do anything.
This is done on every startup of every single fish, and it saves ~0.2ms.
This removes a possibility of an infinite loop where something in
__fish_config_interactive triggers a fish_prompt or fish_read event,
which calls __fish_on_interactive which calls
__fish_config_interactive again, ...
Fixes#9564
This was already apparently supposed to work, but didn't because we
just overrode errno again.
This now means that, if a correctly named candidate exists, we don't
start the command-not-found handler.
See #8804
This tried migrating old abbreviations *twice* - once from the 2.3
scheme to the 2.4 one, and once from that to the 3.0 scheme.
Since this is purely for upgrading from fishes < 3.0, and basically
untested, let's remove it.
If anyone does that upgrade, they'll simply have to reexecute the abbrs.
In the variable handler, we just go through the entire thing and keep
every element once.
If there's a duplicate, we set it again, which calls the handler
again.
This takes a bit of time, to be paid on each startup. On my system,
with 100 already deduplicated elements, that's about 4ms (compared to
~17ms for adding them to $PATH).
It's also semantically more complicated - now this variable
specifically is deduplicated? Do we just want "unique" variables that
can't have duplicates?
However: This entirely removes the pathological case of appending to
$fish_user_paths in config.fish (which should be an FAQ entry!), and the implementation is quite simple.
jobs -p %1 prints all processes in the first job.
fg is special because it only takes one argument. Using the last process
in the pipeline works for the cases I can think of.
Fixes#7406
Previously, when a command wasn't found, fish would emit the
"fish_command_not_found" *event*.
This was annoying as it was hard to override (the code ended up
checking for a function called `__fish_command_not_found_handler`
anyway!), the setup was ugly,
and it's useless - there is no use case for multiple command-not-found handlers.
Instead, let's just call a function `fish_command_not_found` if it
exists, or print the default message otherwise.
The event is completely removed, but because a missing event is not an error
(MEISNAE in C++-speak) this isn't an issue.
Note that, for backwards-compatibility, we still keep the default
handler function around even tho the new one is hard-coded in C++.
Also, if we detect a previous handler, the new handler just calls it.
This way, the backwards-compatible way to install a custom handler is:
```fish
function __fish_command_not_found_handler --on-event fish_command_not_found
# do a little dance, make a little love, get down tonight
end
```
and the new hotness is
```fish
function fish_command_not_found
# do the thing
end
```
Fixes#7293.
This allows us to send proper debug messages via FLOG, and it removes
more things from share/config.fish.
Note that the logic differs in some subtle ways. For instance it will
now obey $COLORTERM, so if that isn't "truecolor" or "24bit" it will
deactivate truecolor.
a) they can screw up our expected output/behavior
b) they can blow up your system
In my case, the unit tests were calling Pantheon's fish integration
script which would then proceed to blow up dbus with messages about each
individual test completing.
Fixes#6556.
Although present since 2006, fish no longer relies on POSIX-compliant tools to the same degree. This
code causes a platform specific change that makes the tests fail, so remove it.
We'd use $__fish_data_dir, but that already had the "/fish" component,
and then we'd add it again later, so we would try to find vendor
functions in places like
/usr/share/fish/fish/vendor_functions.d
which obviously don't exist.
Instead let's add the "/fish" component to the xdg dirs early, which
also saves us from having to repeat it later.
Fixes#6428
See #6508
[ci skip]
$XDG_DATA_DIRS/vendor_{completions,conf,functions}.d
Additionally, CMake variables extra_{completions,conf,functions}dir are
appended, if they are not already contained in $XDG_DATA_DIRS.
If XDG_DATA_DIRS is not defined, we fall back to
$__fish_datadir/vendor_completions.d:${extra_completionsdir}
for completions. Same for conf and functions.
This variable holds an integer that resembles the fish version up to
that initializations were performed. It should be incremented whenever
some new initialization is required after upgrading fish. This should
not change the behavior for existing fish installations, except for a
minor message on installations that upgrade from fish<2.3.0.
[ci skip]
Previously, elements already existing in the path variable would keep their position when the path was being constructed from the config files. This caused issues given that $PATH typically already contains "/usr/bin:/bin" when fish initializes within a macOS terminal app. In this case, these would keep their position at the front of the $PATH, even though the system path_helper configs explicitly place them _after_ other paths, like "/usr/local/bin". This would render binaries in "/usr/local/bin" as effectively "invisible" if they also happen to live in "/usr/bin" as well. This is not the intended
This change makes the __fish_macos_set_env config function emulate the macOS standard path_helper behavior more faithfully, with:
1. The path list being constructed *from scratch* based on the paths specified in the config files
2. Any distinct entries in the exist path environment variable being appended to this list
3. And then this list being used to *replace* the existing path environment variable
The result, for a vanilla fish shell on macOS, is that the $PATH is now set to:
/usr/local/bin /usr/local/sbin /usr/bin /bin /usr/sbin /sbin
Where previously it was set to:
/usr/bin /bin /usr/local/bin /usr/sbin /sbin
This new $PATH exactly matches the order of paths specified in `/etc/paths`.