Other things like shift-f1 are not supported on console yet because
Linux sends "CSI 25 ~" which means shift-f3 in urxvt, so there's
a conflict.
Closes#12787
cwd_fd is crucial to maintain: long-term vision for fish is multiple
threads each with their own CWD with the process-wide CWD used for
nothing at all except transiently (e.g. during fork).
Note this fd is heightenized per open_dir.
This reverts commit 6701b7f6c8.
Like 1b16d318cc, reproduces with `cargo test test_pthread`
Fix by using stdlib `println!` to avoid interacting with topicMonitor.
Enable `allow-print-in-tests` like with crates/printf, such that there i
no deny-warning.
Happens when running `cargo nextest run test_replace_home_directory_with_tilde`, due to process-isolation model.
Backtrace shows:
EnvStack::set_one(HOME)
EnvStack::set
env_dispatch_var_change
reader_current_data
reader_data_stack
assert_is_main_thread
is_main_thread
main_thread_id
Fix by using TestEnvironment instead, as this is a unit-test and does
not need anything more.
in `test_path_normalize_for_cd`
This happens when running the tests using `cargo nextest run`, where
each test runs in its own process, but does not happen with normal
`cargo test`.
Fix by avoiding eprintf!, which can reach SigChecker::check. Instead use a custom panic-message.
This parameter is used to suppress certain verbose errors that are
expected during tests. It was awkwardly threaded through multiple call
sites. Just set it (test only) on Parser.
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.
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
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
Prior to this commit, running
> cargo +nightly bench --features benchmark --no-run
Reports:
warning: feature `test` is declared but not used
--> src/lib.rs:1:58
|
1 | #![cfg_attr(all(nightly, feature = "benchmark"), feature(test))]
| ^^^^
|
= note: `#[warn(unused_features)]` (part of `#[warn(unused)]`) on by default
Which is a false positive. Allow unused features in this cfg_attr.
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.
As of commit a296ee085c (Stop returning a value from ScopeGuarding::commit,
2025-03-15) "ScopeGuard::commit()" is equivalent to "drop()".
Let's use that instead.
The ScopedRefCell wrapping from library_data
is used for two things
1. to allow mutating library_data from a &Parser (for this, a RefCell would be enough)
2. to replace "current_filename" for a scope
A following commit wants to pass parser as "&mut Parser", which
voids reason 1. It will also remove the ScopedRefCell wrapping
from LibraryData because reason 2 alone is not strong enough. Move
"current_filename" outside of that, next to "current_node" which is
already a ScopedRefCell. In future we could maybe consolidate them
into one field, like (or even merging with) ScopedData.
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.