Commit 2971887bbd (Access fish_history from $XDG_DATA_HOME, 2015-09-16)
changed the history file path to ~/.local/share/fish/fish_history.
Migration is done by commit b13f0701a4 (Migrate fish_history from
config to data dir, 2015-09-18).
This should no longer be needed in practice. Remove it.
FWIW, we used a similar-length grace period (10 years) when dropping
support for history file format version 1 in 77aeb6a2a8 (Port
execution, 2023-10-08).
While at it, rename "input mapping" to "binding", to be consistent
with builtin bind. The "input" bit is already implied by the module
hierarchy.
Also, merge definitions of "enum ReadlineCmd" and
"INPUT_FUNCTION_METADATA" using a macro.
Review with
git show --color-moved=zebra --color-moved-ws=allow-indentation-change
Types like Environment are sometimes imported using their FQN and
sometimes via their re-export in the parent module; it seems better
to have one canonical name. I think we usually use the re-exports
already, so use them always.
It't not as trivial to enforce this in child modules (such as "mod
tests" which) but that's not a big loss.
While at it, make some other consistency improvements to imports.
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.
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.
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
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
In C++ we can't have a field and method sharing a name,
but in Rust we can.
For some structs, most getters don't have a "get_", so it's weird
that some do. Remove the "get_" prefix where it's obvious enough.
While at it, give some related getters better names.
A following commit wants to pass parser by exclusive reference,
which disallows passing "parser" as well as "parser.vars()"
in one function call. This use case also doesn't make sense.
The "OperationContext::test_only_foreground" constructor is used to
inject a special "PwdEnvironment" into the context. When we don't need
this environment, we can use a regular constructor, which already uses
"parser.vars()".
A following commit will pass parser as "&mut Parser". This would
create aliasing issues in our calls to exec_prompt_cmd; make it a
free function so rustc can understand how the borrows are split.
"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
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
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
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
It makes a lot more sense to have this function in the same module as
the other escaping functions. There was no usage of this function in
`parse_util` except for the test, so it makes little sense to keep the
function there. Moving it also eliminates a pointless cyclic dependency
between `common` and `parse_util`.
Part of #12625
Not reexporting means that imports have to change to directly import
from `fish_common`. This makes it easier to see which dependencies on
`src/common.rs` actually remain, which helps with identifying candidates
for extraction.
While at it, group some imports.
Part of #12625
Another step in splitting up the main library crate.
Note that this change requires removing the `#[cfg(test)]` annotations
around the `LOCAL_OVERRIDE_STACK` code, because otherwise the code would
be removed in test builds for other packages, making the `#[cfg(test)]`
functions unusable from other packages, and functions with such feature
gates in their body would have the code guarded by these gates removed
in test builds for tests in other packages.
Closes#12494
Having a public function named `test` is quite unspecific. Exporting it
both as `test` and `feature_test` results in inconsistent usage. Fix
this by renaming the function to `feature_test` and removing the alias.
Part of #12494
Return None rather than -1 for nonprintables. We probably still
differ from wcwidth which is bad (given we use the same name), but
hopefully not in a way that matters.
Fixes 146384abc6 (Stop using wcwidth entirely, 2026-03-15).
"Emoji width" refers to the width of emoji codepoints. Since Unicode
9, they're classified as "wide" according to
TR11 (https://www.unicode.org/reports/tr11/).
Unicode 9 was released in 2016, and this slowly percolated into C
libraries and terminals. Glibc updated its default in 2.26, released
in August 2017.
Until now, we'd guess support for unicode 9 by checking the system
wcwidth function for an emoji - if it returned 2, we'd set our emoji
width to 2 as well.
However, that's a problem in the common case of using ssh to connect
to an old server - modern desktop OS, old server LTS OS, boom.
So now we instead just figure you've got a system that's *displaying*
the emoji that has been updated in the last 9 years.
In effect we're putting the burden on those who run old RHEL et al as
their client OS. They need to set $fish_emoji_width to 1.
Fixes#12500
Part of #12562
Add support for the SHELL_PROMPT_PREFIX, SHELL_PROMPT_SUFFIX, and
SHELL_WELCOME environment variables as standardized by systemd v257.
SHELL_PROMPT_PREFIX and SHELL_PROMPT_SUFFIX are automatically prepended
and appended to the left prompt at the shell level, so all prompts
(default, custom, and sample) pick them up without modification.
SHELL_WELCOME is displayed after the greeting when an interactive shell
starts.
These variables provide a standard interface for tools like systemd's
run0 to communicate session context to the shell.
Fixes https://github.com/fish-shell/fish-shell/issues/10924Closes#12570
The `forward-word` readline command on "a-a-a" is wrong (jumps to
"a"); on "aa-aa-aa" it's right (jumps to "-"); that's a regression
from bbb2f0de8d (feat(vi-mode): make word movements vi-compliant,
2026-01-10).
The is_word_end check for ForwardWordEmacs only tests for blank
(whitespace) after the current char. In the Punctuation style, words
also end before punctuation.
Fix this.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
See https://github.com/fish-shell/fish-shell/issues/12543#issuecomment-4125223455
The notion of default is context dependent: there is the default for
the state (default color, non-bold, no underline, ...) and the default
for a change (no color change, no underline change, ...).
Currently, using a single default works because either the style
attributes cannot be turned off individually (the user is expected
to reset to default then re-set necessary attributes), or the code
has special handling for specific scenarios (e.g. highlighting).
So in preparation for later commits, where attribute can be turned off
individually, make the two defaults explicit.
Part of #12507
Similar to `perror_io`, we don't need to make a libc call for `nix`
results, since the error variant contains the errno, from which a static
mapping to an error message exists. Avoid using `perror` and instead use
`perror_io` or `perror_nix` as appropriate where possible.
The `perror_io` and `perror_nix` functions could be combined by
implementing `fish_printf::ToArg` for `nix::errno::Errno`, but such a
function would violate type safety, as it would allow passing any
formattable argument, not necessarily limited to functions with a `%s`
formatting.
Part of #12502
Change some files which have lines whose indentation is not a multiple
of the 4 spaces specified in the editorconfig file.
Some of these changes are fixes or clear improvements (e.g. in Rust
macros which rustfmt can't format properly). Other changes don't clearly
improve the code style, and in some cases it might actually get worse.
The goal is to eventually be able to use our editorconfig for automated
style checks, but there are a lot of cases where conforming to the
limited editorconfig style spec does not make sense, so I'm not sure how
useful such automated checks can be.
Closes#12408
Previously, we chose the ellipsis character/string based on the locale.
We now assume a UTF-8 locale, and accordingly always use the Unicode
HORIZONTAL ELLIPSIS U+2026 `…`. When this was changed, some of the logic
for handling different ellipsis values was left behind. It no longer
serves a purpose, so remove it.
The functions returning constants are replaced by constants. Since the
ellipsis as a `wstr` is only used in a single file, make it a local
const there and define it via the `ELLIPSIS_CHAR` const.
Put the `ELLIPSIS_CHAR` definition into `fish-widestring`, removing the
dependency of `fish-wcstringutil` on `fish-common`, helping future
extraction efforts.
One localized message contains an ellipsis, which was inserted via a
placeholder, preventing translators from localizing it. Since the
ellipsis is a constant, put it directly into the localized string.
Closes#12493