Commit Graph

110 Commits

Author SHA1 Message Date
Johannes Altmanninger
a580d82407 Stop exposing internal module names when we can use re-exports
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.
2026-06-09 22:24:07 +09:00
Peter Ammon
068fa42202 Reimplement test_only_suppress_stderr
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.
2026-05-23 18:13:16 -07:00
Nahor
954c68c0b1 Fix comment typo (CLO_EXEC -> CLOEXEC)
Closes #12774
2026-05-23 00:59:56 +08:00
Johannes Altmanninger
ef8e62727c Pass Parser by exclusive reference
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
2026-05-11 10:41:14 +08:00
Johannes Altmanninger
4b069b51e7 Remove "get_" prefix from some getters
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.
2026-05-01 18:35:41 +08:00
Johannes Altmanninger
d0e47cf58a Move current_filename out of LibraryData
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.
2026-05-01 18:03:13 +08:00
Johannes Altmanninger
64443aa173 Lower OnceLock to LazyLock
LazyLock is less powerful so we should use it when possible.

Ref: https://github.com/fish-shell/fish-shell/pull/12661#discussion_r3158097032
2026-05-01 18:03:13 +08:00
Johannes Altmanninger
81e8eebd8d Use UpperCamelCase for enum variants
Missed in 17ba602acf (Use PascalCase for Enums, 2025-12-14).

Fixes #12647
2026-04-28 23:11:33 +08:00
Johannes Altmanninger
1dfc75bb9c Better name for async-signal-safe functions
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
2026-04-20 21:21:24 +08:00
Johannes Altmanninger
1286745e78 Remove bits for async-signal-safety of old SIGTERM handler
This is implied by the parent commit.

To enable this, stop trying to run cleanup in panic handlers if we
panic on a background thread.
2026-04-11 18:25:26 +08:00
Daniel Rainer
816077281d refactor: move encoding functions to widestring
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
2026-04-11 17:49:47 +08:00
Daniel Rainer
6a5b9bcde1 refactor: move PUA-decoding function to widestring
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
2026-04-11 17:49:45 +08:00
Daniel Rainer
9c819c020e refactor: don't reexport fish_common in common
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
2026-04-11 17:49:41 +08:00
Daniel Rainer
0223edc639 cleanup: use nix version of getpid
Alternatively, we could also use `nix::unistd::Pid::this()`.

Part of #12502
2026-03-09 16:52:08 +11:00
Daniel Rainer
bf5fa4f681 feat: implement perror_nix
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
2026-03-09 16:52:08 +11:00
Daniel Rainer
f6f50df43d refactor: extract more from src/common.rs
This time, functions for decoding `wstr` into various types and the
`ToCString` trait are extracted.

Part of the wider goal of slimming down the main library to improve
incremental build performance and reduce dependency cycles.

Part of #12492
2026-03-03 15:14:39 +11:00
xtqqczze
4eac5f4d9d clippy: fix unused_trait_names lint
https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names

Closes #12450
2026-02-17 11:28:58 +11:00
xtqqczze
934def3b75 clippy fix semicolon_if_nothing_returned lint
https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

Closes #12395
2026-01-31 14:12:49 +11:00
Daniel Rainer
fa1a128aeb nix: use getpgrp wrapper
Part of #12380
2026-01-27 21:50:54 +11:00
xtqqczze
49b3721b75 clippy: fix unnecessary_semicolon lint
https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_semicolon

Closes #12328
2026-01-16 11:40:47 +01:00
xtqqczze
db18515aed clippy: fix range_plus_one lint
https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one

Closes #12329
2026-01-16 11:40:44 +01:00
Daniel Rainer
253f6726c0 widestring: rename wchar -> widestring
This is a more descriptive name for the crate.

https://github.com/fish-shell/fish-shell/pull/12311#discussion_r2681191208

Closes #12313
2026-01-15 17:17:40 +01:00
Johannes Altmanninger
c16677fd6f tty_handoff: use Drop consistently
We sometimes use explicit reclaim() and sometimes rely on the drop
implementation. This adds an unnecesary step to reading all uses of
this code.  Make this consistent. Use drop everywhere though we could
use explicit reclaim too.
2026-01-04 13:08:26 +01:00
Peter Ammon
848fa57144 Introduce and adopt BorrowedFdFile
Rust has this annoying design where all of the syscall conveniences on
File assume that it owns its fd; in particular this means that we can't
easily construct File from stdin, a raw file descriptor, etc.

The usual workarounds are to construct a File and then mem::forget it
(this is apparently idiomatic Rust!). But this has problems of its own:
for example it can't easily be used in Drop.

Introduce BorrowedFdFile which wraps File with ManuallyDrop and then
never drops the file (i.e. it's always forgotten). Replace some raw FDs
with BorrowedFdFile.
2025-12-30 14:07:39 -08:00
Johannes Altmanninger
2b3bd29588 Fix infinite repaint when setting magic variables in prompt
Commit 7996637db5 (Make fish immediately show color changes again,
2025-12-01) repaints unnecessarily when a local unexported color
variable changes.  Also, it repaints when the change comes from
fish_prompt, causing an easy infinite loop.  Same when changing TERM,
COLORTERM and others.

This feature is relevant when using a color-theme aware theme, so
try to keep it. Repaint only on global/universal changes.
Also ignore changes if already repainting fish prompt.

This change may be at odds with concurrent execution (parser should
not care about whether we are repainting) but that's intentional
because of 1. time constraints and 2. I'm not sure what the solution
will look like; we could use the event infrastructure.  But a lot of
existing variable listeners don't use that.

Extract a context object we pass whenever we mutate the environment; While
at it, use it to pass EnvMode::USER, to reduce EnvMode responsibilities.

Fixes #12233
2025-12-30 17:20:42 +01:00
Johannes Altmanninger
6c34bcf8f6 parser: reuse set_var() 2025-12-30 17:20:42 +01:00
David Adam
f0c8788a52 exec: add custom message for EBADMACHO error on Apple platforms
Otherwise the error is 'unknown error number 88'.
2025-12-29 22:46:47 +08:00
Johannes Altmanninger
f1c8e6995d On process exit, read output into buffer to fix ordering
This command

	echo $(/bin/echo -n 1; echo -n 2)

sometimes outputs "21" because we implement this as

	let bufferfill = IoBufferfill::create_opts(...);
	...
	let eval_res = parser.eval_with(...);
	let buffer = IoBufferfill::finish(bufferfill);

i.e. /bin/echo and builtin echo both output to the same buffer; the
builtin does inside parser.eval_with(), and the external process may
or may not output before that, depending on when the FD monitor thread
gets scheduled (to run item_callback).

(Unrelated to that we make sure to consume all available input in
"IoBufferfill::finish(bufferfill)" but that doesn't help with
ordering.)

Fix this by reading all available data from stdout after the child
process has exited.

This means we need to pass the BufferFill down to
process_mark_finished_children().

We don't need to do this for builtins like "fg" or "wait",
because commands that buffer output do not get job control, see
2ca66cff53 (Disable job control inside command substitutions,
2021-07-26).
We also don't need to do it when reaping from reader because there
should be no buffering(?).

fish still deviates from other shells in that it doesn't wait for
it's child's stdout to be closed, meaning that this will behave
non-deterministically.

	fish -c '
	    echo -n $(
	        sh -c " ( for i in \$(seq 10000); do printf .; done ) & "
	    )
	' | wc -c

We should fix that later.

Closes #12018
2025-12-25 14:35:54 +01:00
Daniel Rainer
b62a312cba rename: crate::wchar::prelude -> crate::prelude
Having the prelude in wchar is not great. The wchar module was empty
except for the prelude, and its prelude included things from wutil.

Having a top-level prelude module in the main crate resolves this. It
allows us to completely remove the wchar module, and a top-level prelude
module makes more sense conceptually. Putting non-wchar things into the
prelude also becomes more sensible, if we ever want to do that.

Closes #12182
2025-12-19 19:37:11 +01:00
xtqqczze
3b976a3364 clippy: fix map_unwrap_or lint
https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or

Closes #12188
2025-12-19 19:37:11 +01:00
Daniel Rainer
2f37eda9d9 wchar: extract logic into separate crate
Another reduction in size of the main crate. Also allows other crates to
depend on the new wchar crate.

The original `src/wchar.rs` file is kept around for now to keep the
prelude imports working.

Part of #12182
2025-12-18 15:13:50 +01:00
Toyosatomimi no Miko
bf38e1beca Rename FLOG, FLOGF, to lowercase flog, flogf
Closes #12156
2025-12-16 13:04:43 +01:00
Toyosatomimi no Miko
17ba602acf Use PascalCase for Enums
Part of #12156
2025-12-16 13:04:43 +01:00
Johannes Altmanninger
1fe5497b5d Remove redundant saving of TTY flags
The logic added by 2dbaf10c36 (Also refresh TTY timestamps
after external commands from bindings, 2024-10-21) is obsoleted
by TtyHandoff.  That module is also responsible for calling
reader_save_screen_state after it writes to the TTY, so we don't
actually need to check if it wrote anything.
2025-12-14 15:37:46 +01:00
xtqqczze
27852a6734 fix: clippy::ptr_as_ptr
https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr

Closes #12136
2025-12-11 17:46:58 +01:00
xtqqczze
cc29216ea9 fix: clippy::ptr_cast_constness
https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness

Part of #12136
2025-12-11 17:46:58 +01:00
Fabian Boehm
d99aa696db Fix includes for systems without posix_spawn
Fixes:

9cbb0715a9/packages/fish/0002-fix-import-when-posix-spawn-disabled.patch

Part of #12055
2025-11-19 17:42:17 +01:00
Johannes Altmanninger
ef3923c992 Clean up cfg() definitions
Sort. Use idiomatic names. Use cfg_if.
2025-11-19 16:36:14 +01:00
Johannes Altmanninger
a8b7d89ba5 doc terminal-compatibility: document Unicode characters used in output
Not sure if this will be useful but the fact that we use very
few Unicode characters, suggests that we are insecure about
this. Having some kind of central and explicit listing might help
future decision-making.  Obviously, completions and translations use
more characters, but those are not as central.
2025-11-08 21:18:25 +01:00
Peter Ammon
1846d7fd7e Merge branch 'cleanup-thread-pool'
This merges changes that make thread pools instanced. We no longer have
a single global thread pool. This results in significant simplifications
especially in the reader (no more "canary").
2025-11-01 11:46:25 -07:00
Johannes Altmanninger
708703b9ec Reimplement should_suppress_stderr_for_tests() for some tests
"cargo test" captures stdout by default but not stderr.

So it's probably still useful to suppress test output like

	in function 'recursive1'
	in function 'recursive2'
	[repeats many times]

This was done by should_suppress_stderr_for_tests() which has been
broken. Fix that, but only for the relevant cases instead of setting
a global.
2025-11-01 12:45:17 +01:00
Peter Ammon
d22b5910c2 Remove the "cant_wait" variants of thread pool execution
This is now handled via separate thread pools.
2025-10-31 19:40:07 -07:00
Peter Ammon
e20b06df1a Background threads to use a separate pool from reader
Sometimes we need to spawn threads to service internal processes. Make
this use a separate thread pool from the pool used for interactive tasks
(like detecting which arguments are files for syntax highlighting).
2025-10-31 19:40:03 -07:00
Peter Ammon
95e7977e70 Rename some constants to UPPER_CASE 2025-10-26 11:28:04 -07:00
Daniel Rainer
61ee695e56 refactor: use bytes instead of string
Some string handling functions deal with `Vec<u8>` or `&[u8]`, which
have been referred to as `string` or `str` in the function names. This
is confusing, since they don't deal with Rust's `String` type. Use
`bytes` in the function names instead to reduce confusion.

Closes #11969
2025-10-19 14:09:27 +02:00
Daniel Rainer
43f8d7478e style: change rustfmt edition to 2024
This commit adds `style_edition = "2024"` as a rustfmt config setting.
All other changes are automatically generated by `cargo fmt`.

The 2024 style edition fixes several bugs and changes some defaults.
https://doc.rust-lang.org/edition-guide/rust-2024/rustfmt-style-edition.html

Most of the changes made to our code result from a different sorting
method for `use` statements, improved ability to split long lines, and
contraction of short trailing expressions into single-line expressions.

While our MSRV is still 1.70, we use more recent toolchains for
development, so we can already benefit from the improvements of the new
style edition. Formatting is not require for building fish, so builds
with Rust 1.70 are not affected by this change.

More context can be found at
https://github.com/fish-shell/fish-shell/issues/11630#issuecomment-3406937077

Closes #11959
2025-10-18 09:29:50 +02:00
Johannes Altmanninger
da411f6fa7 bg/fg/wait/disown/function: check for negative PID argument
While at it, extract a function.

Seems to have regressed in 4.0.0 (fc47d9fa1d (Use strongly typed
`Pid` for job control, 2024-11-11)).

Fixes #11929
2025-10-11 17:54:09 +02:00
Isaac Oscar Gariano
93c4d63295 Allow overwriting argv with function -a and -V
Previously, if you called a function parameter 'argv', within the body
of the function, argv would be set to *all* the arguments to the
function, and not the one indicated by the parameter name.
The same behaviour happened if you inherited a variable named 'argv'.
Both behaviours were quite surprising, so this commit makes things more
obvious, although they could alternatively simply be made errors.

Part of #11780
2025-10-11 10:51:36 +02:00
Daniel Rainer
83af5c91bd printf: remove all uses of length modifiers
Length modifiers are useless. This simplifies the code a bit, results in
more consistency, and allows removing a few PO messages which only
differed in the use of length modifiers.

Closes #11878
2025-10-05 15:16:41 +02:00
Peter Ammon
6ad13e35c0 Bravely define PATH_BSHELL
PATH_BSHELL is always "/bin/sh" except on Android where it's "/system/bin/sh".

This isn't exposed by Rust, so just define it ourselves.
2025-10-04 17:27:16 -07:00