This highlighting function is always called with with an operation
context created from a parser; Since parser.context().vars() is the same
as parser.vars(), we can use the former, reducing the number of aliases.
Rewrite the PO file handling logic in Rust and make it available via an
xtask. Replaces the
`build_tools/{update_translations,fish_xgettext}.fish` scripts.
Main benefits:
- Better ergonomics
- Better error handling
- Eliminates the need for a fish executable for updating PO files,
which is particularly useful in CI
- Improved performance, mainly due to concurrent threads working on the
PO files in parallel
The behavior is mostly unchanged, with the minor exception that section
headers for empty sections are now omitted in PO files.
The interface for invoking the tooling is quite different. Instead of
working with flags, `cargo xtask gettext` has 3 subcommands:
- `update` modifies the PO files to match the current sources
- `check` is like update, but instead of modifying the PO files, it
shows diffs between the current version of the PO files and what they
would look like after updating. When there is a difference, the xtask
exits non-zero, making it useful for checks to detect outdated PO
files.
- `new` creates a new PO file for the given language.
Both the `update` and `check` command take any number of file paths to
specify the PO files to consider. If none are specified, all files in
`localization/po/` are considered.
Extracting gettext messages from Rust still requires compiling with the
`gettext-extract` feature active. In situations where compilation is
needed for other purposes as well, it can make sense to only build once
and then tell the gettext xtask about the directory into which the
messages have been extracted. This can be done via the
`--rust-extraction-dir` flag. If we stop having gettext messages in
Rust, this logic can be removed.
Closes#12676
Commit 3534c07584 (Adopt the new AST in parse_execution, 2020-07-03)
added to parse_execution_context_t::run_job_conjunction an early
return when any job in a job conjunction fails to launch. This causes
"nosuchcommand || echo hello" to not execute the continuation.
Fix this by restoring the previous behavior.
Fixes#12654
"commandline -f repaint" might be triggered for various reasons;
since this sets "last_cmd", it will reset some UI states, notably
pager selection:
1. press tab
2. trigger repaint
3. press tab
The repaint prevents us from selecting the first candidate.
Work around this by ignoring repaint events for the last_cmd logic.
Fixes#12683
It is unspecified what `select()` returns if a descriptor is closed
while `select()` uses it. This can result in spurious error messages,
notably in Cygwin.
Also delete corresponding tests since they don't really help with
anything. Any `select()` result is valid when a socket is closed, so
checking that result is pointless. Moreover, fish already does not rely
on any specific result beyond logging.
Part of #12171
In Rust, "safety" is usually used in the context of unsafe functions,
which have documented preconditions. Our async-signal-safe functions
are different; they offer extra safety properties. Rename them to
reduce confusion.
Ref: https://github.com/fish-shell/fish-shell/pull/12625#discussion_r3067819966
Commit a4b6348315 (clippy: fix collapsible_match lint, 2026-04-18) made
it so '$' characters are handled here, which contradicts the comment.
Remove it.
This flag is implied by matches that require replacements. Reflect that
in the Completion::new, reducing the number of places where we raise the
flag. This slightly simplifies tasks like proving the parent commit.
There are other scenarios (e.g. wildcards) where we currently set
the flag additionally.
Commit 3546ffa3ef (reader handle_completions(): remove dead filtering code,
2026-01-02) gives a proof of correctness that still makes sense;
The first lemma ("if will_replace_token") is trivially true, so no need to
assert it.
The second lemma ("if !will_replace_token") is violated in some edge cases:
we claim that given a token "-c", the option completion "--clip" is an exact match,
which is not true, it's a substring match.
Fix that, asserting the claim.
If we get to this code path, we'll only get completions for user
names, so technically the full StringFuzzyMatch with its ranking of
samecase/smartcase/icase (only showing the best) might be overkill,
but it seems like a good idea to treat this the same way as other
completions.
The occasion for this commit is to correct a wrong
StringFuzzyMatch::exact_match() in the icase branch; which will be
important for a following commit. Add a test for that.
Previously, SIGTERM immediately re-raised with SIG_DFL, killing
fish without saving history. SIGHUP deferred via a flag but never
re-raised, so the parent saw a normal exit instead of signal death.
Unify both signals: the handler stores the signal number in a single
AtomicI32, the reader loop exits normally, throwing_main() saves
history and re-raises with SIG_DFL so the parent sees WIFSIGNALED.
Fixes#10300Closes#12615
Move the functions for escaping and unescaping strings from
`src/common.rs` into `fish_common`. It might make sense to move them
into a dedicated crate at some point, but for now just move them to the
preexisting crate to unblock other extraction.
Closes#12625
This time, move char constants from `src/expand.rs` to
`fish_widestring`, which resolves a dependency cycle between
`src/expand.rs` and `src/common.rs`.
Part of #12625
The decoding functions for our widestrings are already in the
`fish_widestring` crate, so by symmetry, it makes sense to put the
encoding functions there as well. This also makes it easier to depend on
these functions, giving more options when it comes to further code
extraction.
Part of #12625
Use `fish_widestring` as the place where char definitions live. This has
the advantage that all our code can depend on `fish_widestring` without
introducing dependency cycles. Having a common place for character
definitions also makes it easier to see which chars have a special
meaning assigned to them.
This change also unblocks some follow-up refactoring by removing a
dependency cycle between `src/common.rs` and `src/wildcard.rs`.
Part of #12625
These functions don't depend on `wcstringutil` functionality, so there
is no need for them to be there. The advantage of putting them into our
`widestring` crate is that quite a lot of code depends on it, and
extracting some of that code would result in crate dependency cycles if
the functions stayed in the `wcstringutil` crate. Our `widestring` crate
does not depend on any of our other crates, so there won't be any cyclic
dependency issues with code in it.
Part of #12625