The current file has no platform detection, causing GNU-only completions
on macOS/BSD. It also has a factual error: -H is described as "Human
readable sizes, powers of 1000", but -H actually follows command-line
symlinks.
Rewritten using __fish_gnu_complete and GNU detection, following
the same pattern as sed.fish. Platform-specific flags added.
Closes#12767
We source "COMPLETE=fish cargo xtask" at completion load time.
This means that completions will be missing if completions were requested
before entering a fish-shell worktree.
Also, as reported in [1], this will compile xtask even for non-fish
projects, which is usually fast but not necessarily (it might download
crates etc).
As suggested in the initial revision of #12763, we could
hardcode the output of
$ COMPLETE=fish cargo xtask
complete --keep-order --exclusive --command cargo --arguments \
"(COMPLETE=fish /home/johannes/git/fish-shell/target/debug/xtask --
(commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))"
but that might still be too intrusive because according to [2],
calls to "cargo metadata" can be slow on big repos with hundreds of
Cargo.toml files.
[1]: 959cbb4259 (r185615416)
[2]: 959cbb4259 (r185637424)
FWIW, commit comments are also accessible via
gh api -H "X-GitHub-Api-Version: 2026-03-10" \
/repos/fish-shell/fish-shell/commits/959cbb42597444577d26ed5ba6151ccb1d7f3600/comments
Set RUSTUP_AUTO_INSTALL=0 for completions, to be consistent with
88d01f7eb8 (completions/cargo: avoid auto-installing toolchain via
rustup, 2026-03-27).
Extend the hack added in ebc140a3ea (Hack path component movement to
skip escaped spaces, 2025-12-16) to apply to all characters, such as
";" that may be part of a file name.
The test balloon in 012007ce7b (Test balloon for ST OSC terminator,
2025-11-18) released in 4.3.0 did not trigger problem reports.
Bravely switch over to the standard ST rather than xterm's BEL.
Closes#12032
Doing
firefox --pro TAB TAB TAB
results in
firefox --profile --ProfileManager
git-bisect points to 3546ffa3ef (reader
handle_completions(): remove dead filtering code, 2026-01-02)
but that regression has already been fixed by 85e76ba356
(Fix option substr completions not being filtered out, 2026-04-16).
However in between those two commits, the above case has also been
broken by 2f6b1eaaf9 (reader handle_completions(): don't consider
odd replacing completions for common prefix, 2026-01-02)
The first TAB inserts "--profile ", including the trailing space.
However it also shows the completion pager, which means that subsequent
TABs will insert after the space.
The trailing space does not make sense unless we navigate the pager.
Remove it in all cases, to fix this smartcase scenario.
Alternatively, we could start navigating the pager in this case
(and keep the trailing space), but that's probably too inconsistent.
Commit f86c9af455 (fish_git_prompt: skip rename/copy source paths in
status parsing, 2026-05-12). filters from "git-status --porcelain"
output all lines that don't look like a status entry. This is
to filter out the rename source path. But the filtering has false
positives, e.g. if a rename source path starts with "AA". Let's only
skip lines immediately after each rename entry. Also for copy (C)
though I haven't found a test case for that yet.
Treating `en` the same as any other language is problematic as shown by
#12690. When the language precedence list contains entries after
English and we don't treat English specially, a lack of translations in
`en.po` (or a lack of `en.po`, once we delete it) results in
translations into those subsequent languages being displayed, instead of
the msgid, which is in English, and thus preferable.
By truncating the fallback list when we encounter `en`, this problem is
resolved. As it is implemented now, the `en.po` catalog is never used.
This is intended, as the plan is to delete it (#12745). In any case, its
translations are identical to the msgids modulo some fancy quotes.
While at it, also treat `LANGUAGE` values of `C` and `POSIX` as
referring to the English version of the messages.
Fixes#12690Closes#12747
The status entry filter regex was missing T, which is a valid
porcelain status code for file type changes (e.g. regular file
to symlink). Without it, typechange entries would be silently
dropped from dirty/staged detection.
Closes#12754
When git status --porcelain -z reports renames or copies, it outputs
the source filename as a separate NUL-delimited field after the status
line. This extra entry was counted as an additional change, inflating
staged/dirty counts when the source filename started with [ACDMRTU].
Filter split results to entries matching a valid two-char status code
prefix, which excludes the bare source filenames.
Fixes#11296
Part of #12754
git status --porcelain -z outputs the rename source filename as a
separate NUL-delimited entry after the status line. When the source
filename starts with [ACDMRTU], the informative prompt miscounts it
as an additional staged change.
Part of #12754
Force the encoding to not be dependent on the environment locale.
In particular on Windows, the encoding could default to an ANSI page
code, which would fail to load any file containing bytes 0x80+, i.e any
multi-byte UTF-8 character.
Closes#12748
Use `clap_complete` to generate completions for our xtasks. This comes
with two complications:
- Due to the unusual CLI of the whole xtask CLI definition being itself
a subcommand under `cargo` (via the `cargo xtask` alias), we need to
tell `clap_complete` that we're generating completions for `cargo`,
which is fairly straightforward to do via two new types which are only
used for generating completions.
- Our completions for `cargo xtask` only make sense within fish's
workspace, so we need to ensure that they are not active elsewhere.
`clap_complete` does not support adding such conditions, so we hack
them together by post-processing its output with sed.
Closes#12739
This command was added in git 2.54:
94f057755b/Documentation/RelNotes/2.54.0.adoc
Both subcommands (`reword` and `split`) take a commit-ish object to
target. `split` also optionally accepts filenames so I tried to handle
that by copying the pattern from existing completions.
Closes#12737
When we push a new reader for builtin read, we use the default
CursorSelectionMode::Exclusive, which is wrong in Vi mode.
Add a haphazard fix for that.
This is very ugly, we should improve this.
Closes#12724
This removes the need to double-escape the values on the command line
(once for the command line parser, another for the option handling)
This also brings it in line with the implicit case (`complete cmd ...`)
Fixes#12712Closes#12718
As described in
https://github.com/fish-shell/fish-shell/pull/9990#discussion_r1382494440,
prior to 77aeb6a2a8 (Port execution, 2023-10-08), "Parser" was
passed by mutable reference ("parser_t&"), even though operation
context was passed as "const operation_context_t &". This worked
because C++ doesn't propagate const to pointers by default (see
https://en.cppreference.com/cpp/experimental/propagate_const).
class operation_context_t {
std::shared_ptr<parser_t> parser;
...
};
So "*ctx->parser" was a "parser_t&", not "const parser_t&".
Rust has stricter const propagation rules which means that const
operation context can't simply hand out a non-const reference to parser.
To be able to port code without changing its structure,
77aeb6a2a8 passed "Parser" by shared reference, using interior
mutability (RefCell) to modify parser fields. This is a bit ugly
(c.f. https://doc.rust-lang.org/std/cell/index.html "interior mutability
is something of a last resort") and means that some borrowing conflicts
are not found at compile time but runtime.
Pass both parser and operation context by exclusive reference, and
remove the interior mutability wrappers from parser's fields.
Since "libdata" is no longer inside a "RefCell", add a "ScopedRefCell"
around "transient_commandline".
The downside is that "ScopeGuard" use can become more intrusive
when we pass "Parser" or "OperationContext" as context (especially
when we use "zelf" since we can't shadow "self"), see
* 2930466d53 (Introduce ScopedCell and ScopedRefCell, 2025-03-15)
* 29ae571afa (Make scoped_push nicer, 2024-12-28)
Avoid this in some cases, specifically when using "ScopedCell" or
"ScopedRefCell". Since "&mut Parser" prevents the "ScopeCell"'s
"ScopeGuard" from holding a shared reference, use an "Rc" to capture
a dynamically-checked reference to the Cell. We could also use raw
pointers instead.
Change "Completer::apply_var_assignments" to return a block ID, to
avoid the need to return a "zelf" "ScopeGuard". In future, we could
probably untangle completer and get away with returning a "ScopeGuard"
called "ctx".
Closes#12694
During our one-time migration away from universal variables,
we create ~/.config/fish/conf.d/fish_frozen_theme.fish
if we think that the current theme is different from the default.
The default uvar-backed theme had changed over time, but existing
installations would not be upgraded. Because of this, we have
a heuristic that assumes that values coinciding with historical
default values also stem from a default. Some historical values are
missing. Add them.
There are more left, see 03b23dd1b6 (Update default colors,
2022-01-27).
Fixes#12725
In non-interactive shells we only ever use our simple command-not-found
handler; the fancy ones are only intended for interactive shells, see
537ab32dd9 (Add support for the Ubuntu 'command-no-found' handler,
which suggests a package to install in order to get a command.,
2008-01-15).
I'm not sure if this behavior difference is really a good idea,
but I guess we can avoid rocking the boat for now.
Make the implementation less surprising by moving it into the obvious
file. No behavior change intended.
We no longer emit the "fish_command_not_found" event ourselves,
so the event handlers are only useful to users who
1. run "emit fish_command_not_found"
2. copy the definition of "fish_command_not_found" to their config and run
that with fish < 3.2.
Probably no one does 1; there are no matches in
https://github.com/search?utf8=%E2%9C%93&q=%22emit+fish_command_not_found%22+language%3Afish&type=code
Reason 2 is less relevant after 5 years.
For additional evidence, none of our specializations
("/usr/libexec/pk-command-not-found" etc.) react to the event,
and no one has ever complained.
Stop registering any fish_command_not_found as event handler,
for consistency and simplicity.
While at it, remove the documentation on how to make it work for
version < 3.2.
If a user passes "-i" when running a script, they ought to expect
weird behavior i.e. fish might run the user's interactive-only
configuration which might print things to TTY etc. But at least
for our part of the configuration, we can avoid depending on the
user-settable interactive bit.
__fish_config_interactive is already only called when we paint the
first prompt, either for a prompt (which implies we're an interactive
shell) or for builtin read (which does not imply anything about the
interactivity of the shell).
Only print greetings when not in interactive read. Notably, "status
is-interactive-read" is not overridable by the user.
This helps us get rid of more "status is-interactive" switches.
The "if status is-interactive" was added by ae593decfc (Replace
__fish_git_branch_prompt.fish with __fish_git_prompt.fish, 2012-06-20)
presumably to avoid repaints in noninteractive cases. The repaints
have been removed in 76457bdc4e (fish_git_prompt: Remove repaint
from variable handlers, 2021-03-04) so this is no longer necessary.
There is already a GitHub workflow doing lint checks so it is redundant
and wastes time (4+ min).
Moreover, other platforms do not do it, so when it fails, it gives
the appearance that there is a Windows specific build issue beyond
linting.
Closes#12740