Compare commits

..

280 Commits

Author SHA1 Message Date
Johannes Altmanninger
bdfc491d56 Release 4.3.0
Created by ./build_tools/release.sh 4.3.0
2025-12-28 10:20:47 +01:00
Johannes Altmanninger
b72127a0b7 build_tools/release-notes.sh: fix RST syntax 2025-12-28 10:03:08 +01:00
Johannes Altmanninger
0ab2a46424 build_tools/release.sh: docs have been removed from tarball
See 135fc73191 (Remove man/HTML docs from tarball, require Sphinx
instead, 2025-11-20).
2025-12-28 10:03:08 +01:00
Johannes Altmanninger
5844650881 Set color theme eagerly again
Now that the default theme no longer contains light/dark sections,
we don't need to wait for $fish_terminal_color_theme to be initialized
before setting it.

Let's set it before loading user config to allow users to do things
like "set -e fish_color_command" in their config.

Fixes #12209
2025-12-28 09:06:16 +01:00
Johannes Altmanninger
3c77a67668 uvar migration: remove extra message if there were no color uvars 2025-12-28 09:06:16 +01:00
Johannes Altmanninger
3105f88622 fish_config choose/save: improve docs 2025-12-28 09:06:16 +01:00
Johannes Altmanninger
5702b26b22 fish_config theme choose: don't add redundant hook
If we're overriding the theme with --color-theme=, we don't need to
register the hook because $fish_terminal_color_theme will be ignored.

Also if the theme is not color-theme aware, there is no need to
register the hook.
2025-12-27 17:28:20 +01:00
Johannes Altmanninger
60ef7ca210 test_complete: improve assertion to track down intermittent failure
The result vector sometimes has three instead of two elements.
See #12184
2025-12-27 13:10:36 +01:00
Johannes Altmanninger
c486c54120 fish_config theme choose: use captured data 2025-12-27 13:10:36 +01:00
Johannes Altmanninger
6273b9420b fish_config theme choose: capture theme by copy
We don't listen for changes to the theme file, so this seems more
appropriate and more robust.
2025-12-27 13:10:36 +01:00
Johannes Altmanninger
4bb0d956eb themes/default: revert to palette colors for now
The readability concern in ed881bcdd8 (Make default theme use named
colors only, 2023-07-25) was no longer relevant, but people might
prefer we use terminal colors by default, because other apps do too,
and because it's a well-known way to make colors look good across
both dark and light mode.

If we revert this, we should make sure fish_default_mode_prompt.fish
and prompt_login.fish also use RGB colors
2025-12-27 12:57:08 +01:00
Nikita COEUR
92db03ac9f feat: aquaproj/aqua completion support
Closes #12213
2025-12-27 12:19:24 +01:00
xtqqczze
0d6aaa36d3 Use mem::take
Closes #12217
2025-12-27 12:19:24 +01:00
Johannes Altmanninger
88a7888478 postfork: remove dead code checking setpgid() error 2025-12-27 12:19:24 +01:00
Nahor
74cb96d55b fd_monitor: add missing EAGAIN check
poll()/select() can return EAGAIN on some systems, which should be
treated like a EINTR according to the man page

Closes #12211
2025-12-27 12:19:24 +01:00
Johannes Altmanninger
30942e16dc Fix prefix/suffix icase comparisons
As reported on Gitter, running "echo İ" makes history autosuggestion
for "echo i" crash.  This is because history search correctly
returns the former, but string_prefixes_string_case_insensitive("i",
"İ") incorrectly returns false.  This is because the prefix check
is implemented by trimming the rhs to the length of the prefix and
checking if the result is equal to the prefix.  This is wrong because
the prefix computation should operate on the canonical lowercase
version, because that's what history search uses.
2025-12-27 12:19:24 +01:00
Johannes Altmanninger
a8ded9cb0d Separate wcscasecmp() concerns better 2025-12-27 09:28:01 +01:00
Johannes Altmanninger
4d67678217 changelog: update, clarify color variable fallback
Do a pass over the changelog and clarify the entry on the breaking
change that sparked #12209.
2025-12-26 18:10:47 +01:00
Johannes Altmanninger
9460559345 fish_config theme save: don't add --theme=$theme marker nor react to colortheme
The theme marker is set by "fish_config theme choose" to allow
us to react to terminal color theme changes, and to tell future
"fish_config theme choose" invocations which variables it should erase
-- it should not erase color variables not set in the theme file,
like Git prompt colors.

I'm not sure if either really makes sense for "fish_config theme save".
Reacting to terminal color theme changes is weird for universals.

I'm not sure if "fish_config theme save" should erase universal
variables that are not defined in the theme.  Historically, it did
so for a hardcoded list of colors, which is hacky. For now let's
err on the side of leaving around color variables.

The "save" subcommand is deprecated; it's possible that this changes
in future (and we add support for "--theme" to it) but I'm not sure
if we have enough need for that.
2025-12-26 18:10:47 +01:00
Johannes Altmanninger
74af4f10de uvar migration: tell users to restart running sessions
Users who run the default theme are silently migrated to global
variables. Universal color variables are deleted, leaving existing
sessions uncolored. Tell the user to restart them, and make some
other improvements; now it looks like:

	fish: upgraded to version 4.3:
	* Color variables are no longer set in universal scope.
	  To restore syntax highlighting in other fish sessions, please restart them.
	* The fish_key_bindings variable is no longer set in universal scope by default.
	  Migrated it to a global variable set in  ~/.config/fish/conf.d/fish_frozen_key_bindings.fish

Same for users who do not use the default theme (who already got a
message before this change). For them, the first bullet point looks
like this:

	[...]
	* Color variables are no longer set in universal scope by default.
	  Migrated them to global variables set in ~/.config/fish/conf.d/fish_frozen_theme.fish
	  To restore syntax highlighting in other fish sessions, please restart them.
	[...]

Closes #12161
2025-12-26 18:10:47 +01:00
Johannes Altmanninger
b2f4befc7e themes: don't define option/keyword colors redundantly
These fall back to param/command roles, so there's no need to
duplicate the value.

Make sure the "set fish_color_o<TAB>" still works if they're not
defined.

Leave it as a comment in theme files I guess, since users copy-pasting
a theme might reasonably want to set it.

Closes #12209
2025-12-26 18:09:15 +01:00
xtqqczze
771b33b3a3 Use Option<OwnedFd> instead of AutoCloseFd
Closes #12199
2025-12-26 18:09:15 +01:00
Johannes Altmanninger
1cf4e191b3 docs syntax-highlighting: show how to restore default theme 2025-12-26 18:09:15 +01:00
Johannes Altmanninger
b88a5eaad5 Allow tracing bindings, event handlers etc. with fish_trace=all
Might have helped with cases like #12209 where an event handler stomps
user preferences.
2025-12-26 18:09:15 +01:00
Johannes Altmanninger
1c1baddf4f docs: one sentence per line 2025-12-26 07:56:52 +01:00
Daniel Rainer
107cbaddf0 strings: take IntoCharIter instead of wstr
Change the input of some functions to take `impl IntoCharIter`, allowing
them to accept more input. Implementing this efficiently means that no
owned types should be passed into these functions, because their
`IntoCharIter` implementation would require unnecessary allocations.
Instead, convert the uses which previously passed `WString` by prefixing
an `&`, so the borrowed `&WString` is passed instead.

To allow for wider use of the modified functions, `IntoCharIter`
implementations are added for `&String`, `&Cow<str>`, and `&Cow<wstr>`.

Closes #12207
2025-12-25 21:52:42 +00:00
Denys Zhak
daa554123f fish_indent: Keep braces on same line after conjunctions, time, not
Closes #12144
2025-12-25 15:22:53 +01:00
Johannes Altmanninger
979320063e readme: remove stale MAC_CODESIGN_ID
Removed in 9edd0cf8ee (Remove some now unused CMake bits, 2024-07-07).
The replacements are not documented in prose but in the GitHub
release workflow.
2025-12-25 15:22:52 +01:00
Johannes Altmanninger
fed0269762 Tweak language in "status language" output
Ref: https://github.com/fish-shell/fish-shell/pull/12106#discussion_r2636320834
2025-12-25 15:22:52 +01:00
Johannes Altmanninger
6d68dfe12b doc terminal-compatibility: clarify 2025-12-25 15:22:52 +01:00
Johannes Altmanninger
97c59fa991 doc terminal-compatibility: fix formatting error 2025-12-25 15:22:52 +01:00
Johannes Altmanninger
128fafce1e uvar migration: improve output on accidental early exit
fish_job_summary shows this as "$sh -c ...".  Make it "/bin/sh -c ...".
2025-12-25 15:22:52 +01: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
02061be279 io: allow unescape+write of str
The existing functionality of converting a `&wstr` to bytes (unescaping
PUA codepoints) and writing these to a file descriptor can be reused for
Rust's built-in strings by making the input type generic. This is
simple, because the only functionality we need is converting the input
into a `char` iterator, which is available for both types.

While at it, rename the functions to have more accurate and informative
names.

Closes #12206
2025-12-25 01:48:02 +00:00
Daniel Rainer
c9b30b748d cleanup: remove duplicate functions
Closes #12205
2025-12-25 01:10:36 +00:00
Daniel Rainer
167cfd0892 gettext-extraction: fix outdated docs
Closes #12204
2025-12-24 01:01:47 +00:00
Daniel Rainer
5c3941f0dd check.sh: rename template to gettext template
This is done in preparation for a second temporary directory used for
Fluent ID extraction.

Closes #12203
2025-12-24 00:47:01 +00:00
Daniel Rainer
d4745b633b check.sh: don't build docs of dependencies
We only run `cargo doc` here to check for issues with fish's
documentation, so there is no need to build docs of dependencies.

Closes #12201
2025-12-24 00:21:41 +00:00
Fabian Boehm
dd97842964 completions/rustc: Don't autoinstall nightly toolchain
Just calling `rustc +nightly` is enough to trigger automatic
installation.

Fixes #12202
2025-12-23 19:49:42 +01:00
Peter Ammon
5715d143a5 Fix some clipplies 2025-12-23 08:44:10 -08:00
Peter Ammon
41571dec0f Minor simplification of history 2025-12-23 08:34:36 -08:00
Nahor
3c7517bf28 tests: disable tmux tests on Cygwin/MSYS
Those tests are unreliable and sometimes even block forever on
Cygwin/MSYS.
2025-12-21 12:21:25 +01:00
Nahor
81fce66269 test_driver: flush output after each test
When the output is redirected, Python buffer its whole output, unlike
a TTY output where only lines are buffered.
In GitHub actions in particular, it means that we can't see any progress
after each test. And if a test blocks forever, there is no output at all.

So flush the output after printing each result to see the progress
being made
2025-12-21 12:21:25 +01:00
Nahor
7b8f97c1ff Run fish_indent on select test scripts
Run fish_indent on test scripts that will be modified in a later
commit

Not running it on all the files because a quarter of them need fixing,
some of which are badly formatted on purpose
2025-12-21 12:21:25 +01:00
Daniel Rainer
9b75b6ee88 l10n: move po/ to localization/po/
This is done in preparation for Fluent's FTL files, which will be placed
in `localization/fluent/`. Having a shared parent reduces top-level
clutter in the repo and makes it easier to find the localization files
for translators, including realizing that both PO and FTL files exist.

We keep PO and FTL files in separate directories because we need to
rebuild on any changes in the PO directory (technically only when there
are changes to `*.po` files, but due to technical limitations we can't
reliably trigger rebuilds only if those changes but not other files in
the same directory.) Changes to FTL files do not require rebuilds for
dev builds, since for these `rust-embed` does not actually embed them
into the binary but rather loads them from the file system at runtime.

Closes #12193
2025-12-21 12:11:49 +01:00
Branch Vincent
1ebf750bc0 completions: add docker
The upstream completions have not been updated for some time, but the
docker binary can generate completions. These include dynamic
completions for image names and so on.

Closes #12197.
2025-12-21 12:57:06 +08:00
Daniel Rainer
dcd07d754d l10n: move wutil/gettext to localization module
Localization deserves its own module. As a first step, this module is
created here. This will be followed up by significant refactoring in
preparation for supporting Fluent alongside gettext.

`localization/mod.rs` is used instead of `localization.rs` because it is
planned to split this module into submodules.

Part of #12190
2025-12-19 19:37:11 +01:00
Johannes Altmanninger
26873d4ad2 Use cfg_if expression syntax to fix let-and-return 2025-12-19 19:37:11 +01:00
Daniel Rainer
17c35217b9 lints: warn on needless_return
The needless_return lint was disabled almost two years ago, alongside
several other lints. It might have been helpful for porting from C++.
Now, I think we can enable that lint again, since omitting the returns
results in equivalent, more concise code, which should not be harder to
read.

The only manual changes in this commit are removing the lint exception
from `Cargo.toml` and removing the unnecessary returns inside `cfg_if!`
macro invocations (in `src/fd_monitor.rs` and `src/proc.rs`).
All other changes were generated by
`cargo clippy --workspace --all-targets --fix && cargo fmt`

Closes #12189
2025-12-19 19:37:11 +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
Asuka Minato
3df88597ca add git shortlog completion
Closes #12186
2025-12-19 19:37:11 +01:00
Johannes Altmanninger
3ec603fc55 Send OSC 7 on fresh prompt (child may have changed it)
After I run a child process like "fish -C 'cd /tmp'", the terminal
will have a stale working directory.

Let's send the OSC 7 notification also once for every fresh prompt
(which is less frequent than the calls to fish_prompt).

This is not fully correct, since it will not work for cases like bind
ctrl-g 'fish -C "cd /tmp"' which allow running external commands
without creating a fresh prompt. We can fix those later, using the
code paths for bracketed paste and friends.
A minor argument for not fixing this just yet is that some people
override "__fish_update_cwd_osc" to work around bugs in their terminal.

Closes #12191
Closes #11778
Closes #11777
2025-12-19 19:36:51 +01:00
Johannes Altmanninger
5545c648d9 builtin read: don't enable TTY protocols while echo is off
When I run "read" and press enter on the foot terminal, I see a "^[[I"
echoed in the TTY.  This is because

1. builtin read creates a TtyHandoff and runs enable_tty_protocols()
2. it runs Reader::readline(), which creates another TtyHandoff.
3. before Reader::readline() returns, it unsets shell modes
   (turning ECHO back on). It also drops its TtyHandoff,
   which enables TTY protocols again.
4. Enabling focus reporting causes this terminal to send
   focus-in event immediately.

This is our fault; we should not have TTY protocols enabled while
ECHO is on.

Fix this by removing the first TtyHandoff (which seems redundant),
meaning that the second one will not try to re-enable protocols.
2025-12-19 19:13:21 +01:00
Johannes Altmanninger
765305d0e4 tty_handoff: remove stale comment
Fixes 1fe5497b5d (Remove redundant saving of TTY flags, 2025-12-14).
2025-12-19 19:13:21 +01:00
Johannes Altmanninger
a261ca2aff Reapply "Refactor common::is_console_session"
This reverts commit 556be5c4a8.

See #12192
2025-12-19 19:13:21 +01:00
Fabian Boehm
556be5c4a8 Revert "Refactor common::is_console_session"
Breaks the build on OpenBSD.

This is another case of a nix feature being unavailable on some platforms,
so start documenting them.

This reverts commit d6108e5bc0.

Fixes #12192
2025-12-19 17:36:47 +01:00
Daniel Rainer
92c5da1b25 contributing: add section about commit history
Adding this info here should hopefully reduce the number of instances
where we need to tell new contributors about it in pull requests.

Closes #12162
2025-12-18 22:22:26 +00:00
Fabian Boehm
fb161e9f4d Fix error squiggles when they run into a newline
Our error marking code:

```
function foobar
^~~~~~~^
```

runs fish_wcswidth to figure out how wide the squiggly line should be.

That function returns -1 when it runs into a codepoint that wcwidth
returns -1 for, so the marking would stop at a single `^`.

In some cases, this happens because the error range includes a
newline.

Since we already find the end of the line, and can only mark one line,
we clamp the squiggles at the end of that line.

This improves some markings.

See discussion in #12171
2025-12-18 17:56:04 +01:00
Daniel Rainer
67d78fb258 fallback: extract into crate
For faster incremental builds and to enable subsequent extraction.

Closes #12183
2025-12-18 15:13:50 +01:00
Daniel Rainer
caef2c309d build: extract some OS detection into build helper
A subsequent commit will need to test for cygwin in a new crate. On
current stable Rust (1.92) this works via `#[cfg(target_os = "cygwin)]`,
but our MSRV (1.85) does not support this. To avoid code duplication,
the OS detection logic is extracted into the build helper crate. For
now, only `detect_cygwin` is needed, but it would be inconsistent to
extract that but not the same functions for other operating systems.

Part of #12183
2025-12-18 15:13:50 +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
Daniel Rainer
5a35acf2e7 crate splitting: create fish-common crate
Dependencies between crates must form a DAG. This means that breaking up
the large library crate requires breaking dependency cycles. The goal of
this commit is creating a crate which contains some of the main crate's
functionality, without depending on the main crate.

To start off, we only move things required for extracting `src/wchar.rs`
and `src/wchar_ext.rs`, which will happen in a subsequent commit.

Part of #12182
2025-12-18 15:13:50 +01:00
phanium
e1a6b7ea5a Support BEL terminator in OSC responses
Needed for NeoVim's :terminal.
Upstream tracking issue: https://github.com/neovim/neovim/issues/37018

Closes #12185
2025-12-18 15:13:50 +01:00
Daniel Rainer
c9fcd31480 widecharwidth: extract into separate crate
This should help with improving incremental build speed. Extracting this
code is easy, since it does not have dependencies. It also unblocks
further extraction of code which depends on widecharwidth.

Closes #12181
2025-12-18 15:13:50 +01:00
xtqqczze
d6108e5bc0 Refactor common::is_console_session
- Use nix::unistd::ttyname
- Simplify logic with pattern matching

Closes #12179
2025-12-18 15:13:50 +01:00
Johannes Altmanninger
2611646232 commandline --cursor: respect transient command line
We have logic to prevent "commandline --cursor 123" inside "complete
-C" from setting the transient commandline's cursor.

But reading this cursor ("commandline --cursor")
is fine and expected to work by completion scripts.

I don't expect there is a use case for setting the cursor while
computing completions, so let's make that an error for now.
Could revisit that.

Closes #11993
2025-12-18 15:13:50 +01:00
Johannes Altmanninger
08600d012f tests/complete: don't remove $PWD
This test removes $PWD which would cause an error if it were to start
a new process.  Normaly we would "cd -" before the removal but later
assertions expect an empty $PWD, so stay there, but don't remove it
to prevent possible surprise.
2025-12-18 15:04:06 +01:00
Johannes Altmanninger
16f14f0e89 test_wwrite_to_fd: test take random bytes, not chars
This function is not passed arbitrary chars.  The only exception is
builtin printf, which we should fix (see parent commit).  Pass random
bytes instead.
2025-12-18 15:04:06 +01:00
Johannes Altmanninger
50bcc3cf4f Isolate hack for skipping internal separator
stage_wildcards has no need for INTERNAL_SEPARATOR. Remove it already
at this stage, to avoid the need to have the workaround in the generic
decoding routine.

Unfortunately we still can't add assert!(!fish_reserved_codepoint(c));
to wcs2bytes_callback, since builtin printf still passes arbitrary
characters. We should fix that later.

Test that printf now behaves correctly for INTERNAL_SEPARATOR.
Also add a regression test for 0c9b73e317.
2025-12-18 15:04:06 +01:00
Johannes Altmanninger
ee2d99ecf3 Fix crash on kitty when clicking in scrolled command line
When the command line occupies the whole screen such that no prompt
line is shown, we crash due to overflow. Fix that.

Fixes #12178
2025-12-18 15:04:06 +01:00
Johannes Altmanninger
81e1f6937f Address some non_upper_case_globals lints 2025-12-18 15:04:06 +01:00
Johannes Altmanninger
03a3a3b52f Silence non_upper_case_globals for log categories
For some reason r-a shows this diagnostic even though we suppress it
in Cargo.toml (I still need to create a bug report).

Making these upper case would be noisy at the call sites, and it
probably doesn't help since we don't think of these identifiers
as global variables (we never access their fields directly).
Silence the r-a warning for now.

See #12156
2025-12-18 15:04:06 +01:00
Daniel Rainer
074ab45049 gettext: move gettext_impl into dedicated crate
This is part of the larger effort of splitting up fish's huge main crate
to improve incremental build speed.

We could extract more logic from `src/wutil/gettext.rs` into the new
crate, but this would require putting wide-string handling into that
crate, which I'm not sure we want. Doing so would have the advantage
that crates which don't depend on fish's main crate (i.e. all crates
other than fish's main crate itself and the binary crates built on top
of it) could then localize messages as well. This will be less relevant
if we replace gettext with Fluent for messages originating from the Rust
sources.

Closes #12108
2025-12-18 15:04:06 +01:00
Daniel Rainer
aa8f5fc77e l10n: implement status language builtin
Based on the discussion in
https://github.com/fish-shell/fish-shell/pull/11967

Introduce a `status language` builtin, which has subcommands for
controlling and inspecting fish's message localization status.

The motivation for this is that using only the established environment
variables `LANGUAGE`, `LC_ALL`, `LC_MESSAGES`, and `LANG` can cause
problems when fish interprets them differently from GNU gettext.
In addition, these are not well-suited for users who want to override
their normal localization settings only for fish, since fish would
propagate the values of these variables to its child processes.

Configuration via these variables still works as before, but now there
is the `status language set` command, which allows overriding the
localization configuration.
If `status language set` is used, the language precedence list will be
taken from its remaining arguments.
Warnings will be shown for invalid arguments.
Once this command was used, the localization related environment
variables are ignored.
To go back to taking the configuration from the environment variables
after `status language set` was executed, users can run `status language
unset`.

Running `status language` without arguments shows information about the
current message localization status, allowing users to better understand
how their settings are interpreted by fish.

The `status language list-available` command shows which languages are
available to choose from, which is used for completions.

This commit eliminates dependencies from the `gettext_impl` module to
code in fish's main crate, allowing for extraction of this module into
its own crate in a future commit.

Closes #12106
2025-12-18 15:04:06 +01:00
Johannes Altmanninger
c0b95a0ee1 readme: fix macOS version requirement 2025-12-17 17:59:24 +01:00
Daniel Rainer
dd93a7e003 test_driver: stop printing tmpdir on failure
We delete the tmpdir unconditionally once all tests are completed, so
there is no point in printing a path which will no longer exist when
analyzing test failures. The paths don't contain any useful information,
so let's delete them to avoid confusion and useless output.
2025-12-17 16:58:07 +01:00
Daniel Rainer
8064a13af9 test_driver: print littlecheck errors after result
Before this, our test driver printed littlecheck's output before the
test result (test name, duration, PASSED/FAILED/SKIPPED).
This makes it harder to read the output and is inconsistent with the way
pexpect test failures are shown.

Starting with this commit, the result is printed first for both test
types, followed by details about failures, if any.
2025-12-17 16:58:07 +01:00
Fabian Boehm
ab7b522b64 tests/tmux: Unset CDPATH
This would fail in tmux_complete
2025-12-17 16:55:58 +01:00
Fabian Boehm
0c9b73e317 Restore ~$foo expansion
This reverts commit 52ea511768 ("cleanup: remove useless `INTERNAL_SEPARATOR` handling").

I don't know how to test this given that we don't know what users exist (maybe "root"?).

Fixes #12175
2025-12-17 16:52:57 +01:00
David Adam
b29a85f45f fish.spec: clean up dependencies 2025-12-17 10:32:20 +08:00
David Adam
f0b4921ccf Fix export test on openSUSE
openSUSE defines a MANPATHSET variable, so make the match a bit tighter
2025-12-17 10:27:24 +08:00
Fabian Boehm
1d3aca2b44 fish_vi_key_bindings: Stop using alias
`alias` is terrible, but the main downside of this is that it shows up
in the output of `alias`, which it shouldn't because the user didn't
define these.
2025-12-16 20:27:47 +01:00
Fabian Boehm
574a8728af cmake: Stop setting RUSTFLAGS
This appends "-g" to RUSTFLAGS if the cmake build type is debug or
RelWithDebInfo.

However, these are already mapped to cargo profiles that enable these
things, see https://doc.rust-lang.org/cargo/reference/profiles.html:

> The debug setting controls the -C debuginfo flag which controls the
amount of debug information included in the compiled binary.

(`rustc -g` is equivalent to `debuginfo=2`)

By setting $RUSTFLAGS in cmake, we bake it into the generated
makefile (/ninja thing), which is surprising.

See #12165
2025-12-16 16:52:25 +01:00
Johannes Altmanninger
e7c1a6a67d Fix build on macOS 2025-12-16 15:36:25 +01:00
David Adam
54127e1028 CMake: stop trying to install groff macros
Dropped in 377abde112.
2025-12-16 22:31:48 +08:00
David Adam
a5330c7ba2 RPM/Debian packaging: add sphinx and man dependencies 2025-12-16 21:49:28 +08:00
David Adam
377abde112 drop obsolete groff macros 2025-12-16 21:43:16 +08:00
Johannes Altmanninger
62628f6fb1 CI: respect dependency cooldown in "uv lock check"
Fixes 1db4dc4c3e (build_tools/update-dependencies.sh: add dependency
cooldown for Python packages, 2025-12-16).
2025-12-16 14:22:24 +01:00
Johannes Altmanninger
64da7ca124 Run build_tools/update-dependencies.sh
Still need to upgrade Cargo deps.
2025-12-16 13:25:27 +01:00
Johannes Altmanninger
1db4dc4c3e build_tools/update-dependencies.sh: add dependency cooldown for Python packages
See
https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
2025-12-16 13:19:16 +01:00
Johannes Altmanninger
ebc140a3ea Hack path component movement to skip escaped spaces
Path component movement is not aware of fish syntax -- and we should
be careful as we teach it some fish syntax, because it is expected
to be used on command lines that have unclosed quotes etc.

Tab completion typically uses backslashes to escape paths with spaces.
Using ctrl-w on such path components doesn't work well because it
stops at the escaped space.

Add a quick hack to change it to skip over backslashed spaces.  Note that
this isn't fully correct because it will treat backslashes inside
quotes the same way.  Not sure what we should do here.  We could have
ctrl-w erase all of this

	"this is"'only\ one 'path component

But that might be surprising.
Regardless of what we end up with, skipping over backslashed whitespace
seems totally fine, so add that now

Closes #2016
2025-12-16 13:16:20 +01:00
Johannes Altmanninger
5e401fc6ea tokenizer test: slim down macro 2025-12-16 13:16:20 +01:00
ELginas
608269320e Added backward-path-component, forward-path-component and kill-path-component
Closes issue #12127

Closes #12147
2025-12-16 13:16:20 +01:00
Johannes Altmanninger
c3a9edceac Truncate autosuggestion lines only at screen edge
From each logical line in the autosuggestion, we show all or nothing.
This means that we may truncate too early -- specifically 1  + the
number of soft-wrappings in this line. Fix that.

See also #12153
2025-12-16 13:16:20 +01:00
Johannes Altmanninger
32cee9caec screen: remove obsolete type 2025-12-16 13:16:20 +01:00
Asuka Minato
f417cbc981 Show soft-wrapped portions in autosuggestions
Co-authored-by: Johannes Altmanninger <aclopte@gmail.com>

Closes #12153
2025-12-16 13:16:20 +01:00
Johannes Altmanninger
92c814841a Work around clippy assertions_on_constants false positive
Upstream issue: https://github.com/rust-lang/rust-clippy/issues/16242

Closes #12159
2025-12-16 13:04:43 +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
チセ
5d37698ef8 fix: __fish_systemctl_services mode handling
Closes #12157
2025-12-16 13:04:16 +01:00
Johannes Altmanninger
7a7c0d6490 __fish_systemctl_services: remove code clone 2025-12-16 13:04:16 +01:00
Johannes Altmanninger
d88c0674a3 __fish_systemctl_services: early return 2025-12-16 13:04:16 +01:00
Johannes Altmanninger
0306ec673f __fish_systemctl_services: remove unused argument 2025-12-16 13:04:16 +01:00
Nahor
b14b6c9f42 fish_git_prompt: fix incorrect variable assignment
The intent was to create two local variables, not to assign one's name
to the other
2025-12-16 08:00:24 +01:00
Fabian Boehm
8061c41c9b docs/math: Clarify what it is for
See #12163
2025-12-15 19:23:01 +01:00
Johannes Altmanninger
190d367bc4 Use globals for color variables, react to light/dark mode
Implicitly-universal variables have some downsides:
- It's surprising that "set fish_color_normal ..."
  and "set fish_key_bindings fish_vi_key_bindings" propagate to other
  shells and persist, especially since all other variables (and other
  shells) would use the global scope.
- they don't play well with tracking configuration in Git.
- we don't know how to roll out updates to the default theme (which is
  problematic since can look bad depending on terminal background
  color scheme).

It's sort of possible to use only globals and unset universal variables
(because fish only sets them at first startup), but that requires
knowledge of fish internals; I don't think many people do that.

So:
- Set all color variables that are not already set as globals.
  - To enable this do the following, once, after upgrading:
    copy any existing universal color variables to globals, and:
    - if existing universal color variables exactly match
      the previous default theme, and pretend they didn't exist.
    - else migrate the universals to ~/.config/fish/conf.d/fish_frozen_theme.fish,
      which is a less surprising way of persisting this.
    - either way, delete all universals to do the right thing for most users.
- Make sure that webconfig's "Set Theme" continues to:
  - instantly update all running shells
    - This is achieved by a new universal variable (but only for
      notifying shells, so this doesn't actually need to be persisted).
      In future, we could use any other IPC mechanism such as "kill -SIGUSR1"
      or if we go for a new feature, "varsave" or "set --broadcast", see
      https://github.com/fish-shell/fish-shell/issues/7317#issuecomment-701165897
      https://github.com/fish-shell/fish-shell/pull/8455#discussion_r757837137.
  - persist the theme updates, completely overriding any previous theme.
    Use the same "fish_frozen_theme.fish" snippet as for migration (see above).
    It's not meant to be edited directly. If people want flexibility
    the should delete it.
    It could be a universal variable instead of a conf snippet file;
    but I figured that the separate file looks nicer
    (we can have better comments etc.)
- Ask the terminal whether it's using dark or light mode, and use an
  optimized default. Add dark/light variants to themes,
  and the "unknown" variant for the default theme.
  Other themes don't need the "unknown" variant;
  webconfig already has a background color in context,
  and CLI can require the user to specify variant explicitly if
  terminal doesn't advertise colors.
- Every variable that is set as part of fish's default behavior
  gets a "--label=default" tacked onto it.

  This is to allow our fish_terminal_color_theme event handler to
  know which variables it is allowed to update. It's also necessary
  until we revert 7e3fac561d (Query terminal only just before reading
  from it, 2025-09-25) because since commit, we need to wait until
  the first reader_push() to get query results.  By this time, the
  user's config.fish may already have set variables.

  If the user sets variables via either webconfig, "fish_config theme
  {choose,save}", or directly via "set fish_color_...", they'd almost
  always remove this label.
- For consistency, make default fish_key_bindings global
  (note that, for better or worse, fish_add_path still remains as
  one place that implicitly sets universal variables, but it's not
  something we inject by default)
- Have "fish_config theme choose" and webconfig equivalents reset
  all color variables. This makes much more sense than keeping a
  hardcoded subset of "known colors"; and now that we don't really
  expect to be deleting universals this way, it's actually possible
  to make this change without much fear.

Should have split this into two commits (the changelog entries are
intertwined though).

Closes #11580
Closes #11435
Closes #7317
Ref: https://github.com/fish-shell/fish-shell/issues/12096#issuecomment-3632065704
2025-12-14 17:03:03 +01:00
Johannes Altmanninger
f1f14cc8fa input: extract function for enqueuing query response 2025-12-14 16:29:14 +01:00
Johannes Altmanninger
707bfe3ce6 fish_config theme show: list default scheme first
Webconfig does the same ("Add the current scheme first, then the
default.").
2025-12-14 16:29:14 +01:00
Johannes Altmanninger
d8f1a2a24f Move sample_prompts/themes to share/
They are used by "fish_config" CLI too, so no need to make them
private to webconfig.  Putting them at top-level seems simpler overall.
2025-12-14 16:29:14 +01:00
Johannes Altmanninger
dbdecaba6d fish_config: remove hardcoded set of colors to erase
This is incomplete, and we'll solve the problem differently. For now,
leave colors that are not mentioned in the theme.  This causes problems
for sparse themes, but a following commit will fix that by making
"fish_config theme choose" erase all variables set by a previous
invocation (but not erase variables set by the user).  Only webconfig
won't do that since it (historically) uses copy semantics, but we
could change that too if needed.

This also breaks the guarantee mentioned by this comment in webconfig:

> Ensure that we have all the color names we know about, so that if the
> user deletes one he can still set it again via the web interface

which should be fine because:
1. a following commit will always set all globals at interactive init,
   so colors should only be missing in edge cases ("fish -c fish_config").
2. it's easy to recover from by setting a default theme.
2025-12-14 16:26:14 +01:00
Johannes Altmanninger
66f6493fbf fish_config theme dump: speed up
For better or worse, "set -L" prints all of $history, which makes
"fish_config theme show" very slow.  Fix this by only printing the
relevant variables.  While at, make the escaping function use the
shared subset of fish and POSIX shell quoting syntax, to allow a
following commit to use shlex.split().
2025-12-14 16:25:14 +01:00
Johannes Altmanninger
76e0f9a3e8 fish_config: extract function for iterating over themes 2025-12-14 16:24:13 +01:00
Johannes Altmanninger
697afdefeb fish_config: extract some functions for reading theme files
A following commit wants to add some more logic and call some of
fish_config's private APIs from webconfig.  We could keep it all in
one file but I'm not sure we should so try the splitting we usually do.
2025-12-14 16:23:53 +01:00
Johannes Altmanninger
aba89f9088 docs: one sentence per line 2025-12-14 16:23:37 +01:00
Johannes Altmanninger
344187e01a fish_config: extract function 2025-12-14 16:23:37 +01:00
Johannes Altmanninger
9f11de24d4 webconfig.py: remove dead code 2025-12-14 16:23:37 +01:00
Johannes Altmanninger
7996637db5 Make fish immediately show color changes again
Historically, fish tried to re-exec the prompt and repaint immediately
when a color variable changed.

Commit f5c6306bde (Do not repaint prompt on universal variable events,
but add event handler for fish_color_cwd, 2006-05-11) restricted this
to only variables used in the prompt like "fish_color_cwd".

Commit 0c9a1a56c2 (Lots of work on web config Change to make fish
immediately show color changes, 2012-03-25) added repainting back
for all colors (except for pager colors).

Commit ff62d172e5 (Stop repainting in C++, 2020-12-11) undid that.

Finally, 69c71052ef (Remove __fish_repaint, 2021-03-04) removed the
--on-variable repaint handlers added by the first commit.

So if color changes via either
1. webconfig
2. an event handler reacting to the terminal switching between light/dark mode
3. a binding etc.

then we fail to redraw. Affects both colors used in prompts and those
not used in prompts.

Fix that by adding back the hack from the second commit.  This is
particularly important for case 2, to be added by a following commit.

In future we can remove this hack by making "--on-variable" take
a wildcard.
2025-12-14 16:23:37 +01:00
Johannes Altmanninger
d67cdf5f6f Update changelog 2025-12-14 16:23:37 +01:00
Johannes Altmanninger
7dd2004da7 Re-enable focus reporting on non-tmux
I can no longer reproduce the issue described in bdd478bbd0 (Disable
focus reporting on non-tmux again for now, 2024-04-18).  Maybe the
TTY handoff changes fixed this.  Let's remove this workaround and
enable focus reporting everywhere.
2025-12-14 16:23:37 +01:00
Johannes Altmanninger
4000503c03 DRY DSR sequences a bit 2025-12-14 16:23:37 +01:00
Johannes Altmanninger
7c994cd784 fish_config: extract some functions for finding theme variables etc.
To be used in a following commit.
2025-12-14 16:23:37 +01:00
Johannes Altmanninger
e68ea35f02 fish_config: improve consistency
The theme variable filter applies to whole lines, so it's weird to
only apply it to the first token, and we don't do that elsewhere.
2025-12-14 16:21:16 +01:00
Johannes Altmanninger
5cc953b18d Default theme variants specialized for light/dark mode
Start by converting the "default" theme's colors to RGB, using
XTerm colors since they are simple, see
https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit.

Then make the following changes:

for both default-light and default-dark:
- Reinstate fish_color_command/fish_color_keyword as blue since one
  of the reasons in 81ff6db62d (default color scheme: Make commands
  "normal" color, 2024-10-02) doesn't hold anymore.
- bravely replace "fish_pager_color_selected_background -r" with
  something that hopefully matches better.
  Note we can't trivially use the fallback to
  "fish_color_search_match", since for unknown reasons,
  "fish_pager_color_selected_background" is only for background and
  the others are for foreground.

for default-light:
- brgreen (00ff00) looks bad on light background, so replace it with green (00cd00).
  This means that we no longer use two different shades of green in the default theme
  (which helps address the "fruit salad" mentioned 81ff6db62d).
- yellow (cdcd00) looks bad on light background, make it darker (a0a000)
- fish_pager_color_progress's --background=cyan (00cdcd) seems a bit too bright, make it darker
  - same for other uses of cyan (also for consistency)
  - this means fish_color_operator / fish_color_escape can use 00cdcd I guess.
for default-dark:
- use bright green (00ff00) for all greens
- use bright blue (5c5cff) instead of regular blue for command/keyword
- make autosuggestions a bit lighter (9f9f9f instead of 7f7f7f) 
- etc.. I think I made the two themes mostly symmetrical.

Part of #11580
2025-12-14 16:21:16 +01:00
Johannes Altmanninger
f264ee0b10 webconfig theme: rename "fish-default" theme
The "fish-" prefix is not needed here and it would add more noise to
a following commit which adds default-{dark,light} variants that use
24 bit RGB colors.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
3c6978c038 webconfig theme: minor changes to default theme
Don't set fish_pager_color_completion,
it already falls back to fish_color_normal.

Also remove a comment, it's obvious and maybe no longer
true, since 8 bit colors are widely available now, see
https://github.com/fish-shell/fish-shell/issues/11344#issuecomment-3568265178

Though we prefer 24 bit colors wherever we can.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
d5732b132e webconfig themes: consistent quoting 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
ae22cc93db webconfig themes: shell-friendly filenames
For historical reasons (namely the webconfig origin), our theme
names contain spaces and uppercase letters which can be inconvenient
when using the "fish_config theme choose" shell command.  Use more
conventional file names.

Web config still uses the pretty names, using the ubiquitous "# name:"
property.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
51e551fe5f doc/fish_config: fix copy-paste errors 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
33cb8679ba fish_config theme show: remove unused argument 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
655b1aa7a1 fish_prompt: remove stray initialization of fish_color_status
I can't reproduce the problem mentioned in 0420901cb2 (default prompt:
Set fish_color_status if unset, 2021-04-11).
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
daba5fdbcd fish_delta: acknowledge workaround for no-stdin-in-cmdsub 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
01bd380d00 webconfig.py: reuse "fish_config theme dump" 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
801c4f8158 webconfig.py: simplify "functions" output parsing
This outputs one-item-per-line if stdout is a terminal.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
e331e30e38 __fish_config_interactive: minor style change 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
7bd30ac3c4 __fish_config_interactive: inline function 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
5631a7ec86 Fix color variable filter regex 2025-12-14 15:44:58 +01:00
Johannes Altmanninger
a9c43e7396 webconfig js: remove redundant code clone
The server side (webconfig.py) will already reset missing colors
to empty.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
2a6c0e4437 webconfig js: remove obsolete workaround
I cannot reproduce.
2025-12-14 15:44:58 +01:00
Johannes Altmanninger
7f224d0dfd DRY color variable names 2025-12-14 15:42:56 +01:00
Johannes Altmanninger
f818002f38 webconfig.py: use full color names
Optimize for ease of maintenance.
2025-12-14 15:42:56 +01:00
Johannes Altmanninger
6b8e82946a webconfig.py: remove dead code
Both descriptions for bindings and color variables are unused.
2025-12-14 15:42:56 +01:00
Johannes Altmanninger
faaff2754b webconfig.py: fix stale return type
This function returns a heterogeneous list (containing dicts/lists)
by accident. Fix that and reduce code duplication.  Fixes c018bfdb4d
(Initial work to add support for angularjs, 2013-08-17).
2025-12-14 15:42:12 +01:00
Johannes Altmanninger
5c0e72bb89 webconfig.py: simplify 2025-12-14 15:40:03 +01:00
Johannes Altmanninger
b3b7d2cb00 webconfig js: remove debug log statement 2025-12-14 15:40:03 +01:00
Johannes Altmanninger
f503dcb92d webconfig js: resolve a comment 2025-12-14 15:37:46 +01:00
Johannes Altmanninger
7f1b53a9f1 webconfig.py: remove a workaround for Python 2 2025-12-14 15:37:46 +01:00
Johannes Altmanninger
938e780007 fish_config theme save: remove dead code 2025-12-14 15:37:46 +01:00
Johannes Altmanninger
3e7c5ae399 __fish_config_interactive: make config file initialization independent of uvars
Helps the following commits.
2025-12-14 15:37:46 +01:00
Johannes Altmanninger
548f37eabb Simplify make_tarball.sh
Note that we don't need to set the mtime anymore -- it was added in
5b5b53872c (tarball generation: include config.h.in, set mode and
ownership, 2013-09-09) for autotools' multi-stage builds.
2025-12-14 15:37:46 +01:00
Johannes Altmanninger
135fc73191 Remove man/HTML docs from tarball, require Sphinx instead
Advantages of prebuilt docs:
- convenient for users who compile the tarball
- convenient for packagers who don't have sphinx-build packaged
  (but packaging/installing that should be easy nowadays?
  see https://github.com/fish-shell/fish-shell/issues/12052#issuecomment-3520336984)

Disadvantages:
- Extra build stage / code path
- Users who switch from building from tarball to building from source
  might be surprised to lose docs.
- People put the [tarballs into Git repositories](https://salsa.debian.org/debian/fish), which seems weird.

Remove the tarball.

Let's hope this is not too annoying to users who build on outdated
distros that don't have sphinx -- but those users can probably use
our static builds, skipping all compilation.

To avoid breaking packagers who use `-DBUILD_DOCS=OFF` (which still
installs prebuilt docs), rename the option.

Closes #12088
2025-12-14 15:37:46 +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
Johannes Altmanninger
6b85450dea Silence error log for legacy escape specifically
This happens after pressing escape while kitty keyboard protocol is
disabled (or not supported).
2025-12-14 15:37:46 +01:00
Johannes Altmanninger
2309c27a2d Replace ifdef with cfg! 2025-12-14 10:24:49 +01:00
exploide
8b5d66def8 completions: added arp-scan
Closes #12158
2025-12-14 08:44:08 +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
xtqqczze
831411ddd5 fix: clippy::ref_as_ptr
https://rust-lang.github.io/rust-clippy/master/index.html#ref_as_ptr

Part of #12136
2025-12-11 17:46:58 +01:00
xtqqczze
ec77c34ebe fix: clippy::borrow_as_ptr
https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr

Part of #12136
2025-12-11 17:46:58 +01:00
Johannes Altmanninger
d1c7a4b6e7 Don't silence errors in fish_key_bindings/fish_user_key_bindings
We silence erros from the key binding function since 2c5151bb78 (Fix
bug in key binding code causing unneeded error messages, 2007-10-31).

Reasons are
1. fish_key_bindings is not a valid function
2. fish_key_bindings runs "bind -k" for things that are not supported (#1155)

Both reasons are obsolete:
1. we already check that earlier
2. "-k" is gone. (Also, we could have silenced "bind -k" invocations instead).
2025-12-11 17:46:58 +01:00
Nahor
7fc27e9e54 cygwin: improve handling of .exe file extension
- Prefer the command name without `.exe` since the extension is optional
when launching application on Windows...
- ... but if the user started to type the extension, then use it.
- If there is no description and/or completion for `foo.exe` then
use those for `foo`

Closes #12100
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
a4b949b0ca Remove uname= prefix from query-os-name
Discussion with terminal authors indicates a slight preference for
removing the prefix.  We don't need it at this point, since we only
use it to detect macOS clients.
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
64196a2a9e complete: fix erasing wrapped functions
Two issues:
1. "complete -e foo" doesn't erase wrap definitions
2. "complete -e foo --wraps" erases things other than the wrap definitions

Fix them.

There's another issue, the second erase command leaves around an
extra complete entry. Let's leave that for later.

Fixes #12150
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
353ecfadaf complete: fix naming convention 2025-12-10 16:15:41 +01:00
Johannes Altmanninger
0e9ceb154e fish_config theme dump: check for extra arguments 2025-12-10 16:15:41 +01:00
Johannes Altmanninger
baaf06b2c6 cmake/Tests: enable Cargo features
For unknown reasons, we don't enable Cargo features on the test target.
Let's try to, simplifying things overall.

Ref: https://github.com/fish-shell/fish-shell/issues/12120#issuecomment-3627842316
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
106f7b86dc cmake/Tests: split long line 2025-12-10 16:15:41 +01:00
Daniel Rainer
64e3b419b6 ci: disable pexpect and tmux tests in sanitizer jobs
These tests are unreliable in CI when running with address sanitiation
enabled, resulting in intermittent CI failures.
Disable them to get rid of the many false positives to reduce annoyance
and to avoid desensitization regarding failures of the asan CI job.

Suggested in
https://github.com/fish-shell/fish-shell/pull/12132#issuecomment-3605639954

Closes #12142
Closes #12132
Closes #12126
2025-12-10 16:15:41 +01:00
Kristof Mattei
3237efc582 fix: invoke the rm command, bypassing custom rm functions which might block
Closes #12141
2025-12-10 16:15:41 +01:00
xtqqczze
717d301b7f refactor: replace addr_of! macros with raw pointer syntax
`addr_of!` and `addr_of_mut!` have been soft-deprecated as of Rust 1.82.0.

Closes #12139
2025-12-10 16:15:41 +01:00
Daniel Rainer
6a36d92173 lint: fix function_casts_as_integer lint in nightly
This lint is intended to make it harder to unintentionally cast a
function to an int. We do want to store function pointers in a usize
here, so add the intermediate cast suggested by the lint.

Closes #12131
2025-12-10 16:15:41 +01:00
Daniel Rainer
75c005a4d4 lint: convert is_some+unwrap into if let
This fixes an `unnecessary_unwrap` lint shown by nightly Clippy.

Closes #12130
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
07389055f1 fish_indent: handle invalid arguments 2025-12-10 16:15:41 +01:00
Johannes Altmanninger
692e6d57cf fish_indent --ansi to emit SGR0 before final newline
Buggy programs parsing "fish_indent --ansi" output break because
we wemit SGR0 after the final newline.  I suppose this is weird,
and there's no need to wait until after the \n to emit SGR0 so let's
move it before that.

Closes #12096
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
7952545460 Prefer cfg! over #[cfg] for embedding
We should isolate conditionally-compiled code as much as possible,
to allow the compiler to do more work, and to simplify code.
Do that for the embedding definition for __fish_build_paths, like we
already do for "Docs".  Duplicate the workaround we use to set the
embedded struct to a "virtually empty" directory.  Don't set it to
"$FISH_RESOLVED_BUILD_DIR", because that directory can contain >50k
files, and in debug mode listing files (even if all are excluded)
would take a second.

Ref: https://github.com/fish-shell/fish-shell/pull/12103#issuecomment-3592280477

This should also fix #12120.
2025-12-10 16:15:41 +01:00
Johannes Altmanninger
4aa967cd5d builtins: extract struct for input value from arg or stdin line 2025-12-10 16:15:07 +01:00
Daniel Rainer
3e2336043a gettext-extract: fix race condition
Multiple gettext-extraction proc macro instances can run at the same
time due to Rust's compilation model. In the previous implementation,
where every instance appended to the same file, this has resulted in
corruption of the file. This was reported and discussed in
https://github.com/fish-shell/fish-shell/pull/11928#discussion_r2488047964
for the equivalent macro for Fluent message ID extraction. The
underlying problem is the same.

The best way we have found to avoid such race condition is to write each
entry to a new file, and concatenate them together before using them.
It's not a beautiful approach, but it should be fairly robust and
portable.

Closes #12125
2025-12-10 16:15:07 +01:00
Johannes Altmanninger
c1db2744cf Revert "translations: Add Spanish translation"
This reverts commit 0fb5ab4098 because
review comments have not yet been addressed.
2025-12-10 16:15:07 +01:00
Daniel Rainer
c6252967ab rust-embed: update to 8.9.0
This eliminates the proc-macro panic occasionally observed in CI,
instead ignoring paths which cannot be canonicalized.
See #12120.

While this does not address the underlying issue of why the proc-macro
fail happens, it should result in builds no longer failing, and since
they failed in the case where no embedding is desired, there should be
no issue with ignoring failed path canonicalization, since we do not
want to embed anything in these cases.
2025-12-09 11:34:08 +08:00
Julio Napurí
0fb5ab4098 translations: Add Spanish translation
Closes #12089
2025-12-08 18:34:15 +01:00
Daniel Rainer
de3d390391 cleanup: remove unused import
Closes #12151
2025-12-08 17:08:51 +00:00
Daniel Rainer
76b0961e91 tempfile: use new logic for uvar tests
The old approach does not properly protect from concurrent tests
accessing the same tempdir. Fix this by moving to the new tempfile
functionality. This also eliminates the need to explicitly create and
delete the directory. There is also no longer a reason to specify names
for the temporary directories, since name collisions are avoided using
more robust means, and there is little benefit to having the names in
the directory name.

Closes #12030
2025-12-08 16:51:20 +00:00
Daniel Rainer
c0f91a50fa fix: avoid race conditions of mkstemp
The `mkstemp` function opens files without setting `O_CLOEXEC`. We could
manually set this using `fnctl` once the file is opened, but that has
the issue of introducing race conditions. If fish `exec`s in another
thread before the `fnctl` call completes, the file would be left open.

One way of mitigating this is `mkostemp`, but that function is not
available on all systems fish supports, so we can't rely on it.

Instead, build our own tempfile creation logic which uses the `rand`
crate for getting entropy and relies on Rust's stdlib for the rest.
The stdlib functions we use set `O_CLOEXEC` by default.

For directory creation we keep using `mkdtemp`, since there we don't
open anything. We could replace this by extending our custom logic a
bit, which would allow us to drop the `nix` dependency for our
`tempfile` crate, but since the code is simpler as it is now and we need
nix in fish's main crate, there is no need to modify the directory
creation code.

Part of #12030
2025-12-08 16:51:20 +00:00
Daniel Rainer
77fbd0a005 rand: use ThreadRng wherever reseeding is ok
`SmallRng` was chosen in part due to limitation of old macOS versions.
This is no longer relevant, since the affected versions are not
supported by Rust anymore.

Switch everything which does not need fixed sequences based on a seed to
`ThreadRng`, which has better cryptographic properties and is
occasionally reseeded. Performance differences should not matter much,
since initialization of `ThreadRng` is not that expensive and it's
generation speed is easily fast enough for our purposes.

In some cases, like tests and the `random` builtin, we want a PRNG which
consistently produces the same sequence of values for a given seed.
`ThreadRng` does not do this, since it is occasionally reseeded
automatically. In these cases, we keep using `SmallRng`.

Part of #12030
2025-12-08 16:51:20 +00:00
Daniel Rainer
c9ab2c26aa Update rand crate to 0.9.2
Function names containing `gen` have been deprecated to avoid conflicts
with the Rust 2024 keyword, so this commit also switches to the new
names.

Part of #12030
2025-12-08 16:51:20 +00:00
Daniel Rainer
b1769658f5 cleanup: remove obsolete comment
Since we changed our MSRV to 1.85, macOS < 10.12 is no longer supported,
so the comment removed here is no longer relevant.

The workaround for old macOS was introduced in
9337c20c2 (Stop using the getrandom feature of the rand crate, 2024-10-07)

We might want to reconsider which RNGs and other features of the `rand`
crate we use, but there is no immediate need to do so, since the current
approach seems to have worked well enough.

Part of #12030
2025-12-08 16:51:20 +00:00
Gleb Smirnov
3518d4f6ad fix: treat run0 and please as a prefix in __fish_man_page
Closes #12145
2025-12-08 21:30:29 +08:00
Jesse Harwin
aa4ebd96f9 Fixed typo
Missed a spot in the first attempt #12135 as pointed out by [xtqqczze](https://github.com/fish-shell/fish-shell/pull/12135#issuecomment-3609441130)

Small typo found in doc_src/cmds/fish_opt.rst and tests/checks/argparse.fish. `valu` to `value`
2025-12-08 21:19:43 +08:00
Asuka Minato
656b39a0b3 Also show case-insensitive prefix matches in completion pager
[ja: made some changes and added commit message]

Fixes #7944
Closes #11910
2025-12-05 16:12:34 +01:00
Johannes Altmanninger
fceb600be5 math: remove logb
As discussed in #12112, this is a false friend (the libc logb()
does something else), and without keyword arguments or at least
function overloading, this is hard to read.
Better use "/ log(base)" trick.
2025-12-05 16:06:22 +01:00
PowerUser64
47c773300a feat(math): add logb function
Closes #12112
2025-11-30 09:20:33 +01:00
Daniel Rainer
2d29749eae printf: improve Unicode escape + PUA handling
The old handling of Unicode escape sequences seems partially obsolete
and unnecessarily complicated. For our purposes, Rust's u32 to char
parsing should be exactly what we want.

Due to fish treating certain code points specially, we need to check
if the provided character is among the special chars, and if so we need
to encode it using our PUA scheme. This was not done in the old code,
but is now.
Add tests for this.
Fixes #12081

Rework the error message for invalid code points.
The old message about invalid code points not yet being supported seems
odd. I don't think we should support this, so stop implying that we
might do so in the future.
In the new code, indicating that a Unicode character is
out of range is also not ideal, since the range is not contiguous.
E.g. `\uD800` is invalid, but \U0010FFFF is valid.
Refrain from referring to a "range" and instead just state that the
character is invalid.

Move formatting of the escape sequence into Rust's `format!` to simplify
porting to Fluent.

Closes #12118
2025-11-30 09:20:33 +01:00
Daniel Rainer
22a252d064 gettext: rebuild extract macro on env var change
While it's not necessary to rebuild the proc macro for extraction when
the env var controlling the output location changes, this way everything
using the macro will automatically be rebuilt when this env var changes,
making it impossible to forget adding this to other `build.rs` files.

For now, keeping the rebuild instructions in fish's main crate's
`build.rs` would be fine as well, but if we start breaking this crate
into smaller parts, it would become annoying to add the rebuild command
in every crate depending on gettext extraction.

Closes #12107
2025-11-30 09:20:33 +01:00
Daniel Rainer
4642b28ea7 gettext: enable default features for extraction
There was a mismatch between the extraction done from
`build_tools/check.sh` and the one done in
`build_tools/fish_xgettext.fish`, resulting in messages guarded by
default features being extracted by the former but not the latter.
This brings them in sync.

Ideally, we would enable all features for extraction, but compiling with
`--all-features` is broken and manually keeping the features lists
updated is tedious and error prone, so we'll settle on only using
default features for now.

Closes #12103
2025-11-30 09:20:33 +01:00
Daniel Rainer
b8662f9c7f cleanup: move use statements to start of module
Closes #12102
2025-11-30 09:20:33 +01:00
Daniel Rainer
9af85f4c3b gettext: separate catalog lookup from interning
Improve separation of concerns by handling catalog lookup in the
`gettext_impl` module, while taking care of string interning and string
type conversion in the outer `gettext` function as before.

This improves isolation, meaning we no longer have to expose the
catalogs from `gettext_impl` to its parent module.

It also helps with readability.

Part of #12102
2025-11-30 09:20:33 +01:00
Daniel Rainer
aa742f0b57 refactor: eliminate duplicate enum variant spec
Modify the `str_enum!` macro to be able to handle multiple strings per
enum variant. This means that no separate step is required for defining
the enum. Instead definition of the enum and implementation of the
string conversion functions is now combined into a single macro
invocation, eliminating code duplication, as well as making it easier to
add and identify aliases for an enum variant.

Closes #12101
2025-11-30 09:20:33 +01:00
Daniel Rainer
e648da98da cleanup: sort StatusCmd variants alphabetically
Part of #12101
2025-11-30 09:20:33 +01:00
Daniel Rainer
94367b08ba cleanup: do not set enum variant to value
This seems to be a left-over detail from the C++ version. Setting the
first element to 0 does not have any effect, since that's the default,
and setting it to 1 seems to serve no purpose in the current code.

Part of #12101
2025-11-30 09:20:33 +01:00
Daniel Rainer
97b45dc705 cleanup: remove duplicate enum variants
There is no difference in how these two variants are treated. Keeping
the old command name around for compatibility is nice, but it does not
need to have its own enum variant.

Part of #12101
2025-11-30 09:20:33 +01:00
Johannes Altmanninger
198768a1c7 CONTRIBUTING: remove -n from sphinx-build, add cmake target
The -n flag adds warnings about preexisting problems because we don't
check it in CI, so let's not recommend that.

Not everyone uses cmake but it's still the source of truth for docs,
so mention the cmake incantation.  Though it seems like the direct
sphinx-build invocation works just fine, so keep it first.
2025-11-30 09:20:33 +01:00
Johannes Altmanninger
7c27c1e7d0 editorconfig / doc_src: trim trailing whitespace
Commit 0893134543 (Added .editorconfig file (#3332) (#3313),
2016-08-25) trimmed trailing whitespace  for Markdown file (which do
have significant trailing whitespace) but ReStructuredText does not,
and none of our Markdown files cares about this, so let's clean up
whitespace always.
2025-11-30 09:20:33 +01:00
Daniel Rainer
9f8d8ebc2c cleanup: remove unused message
This message is no longer used since we unconditionally embed files now.
The `#[allow(dead_code)]` annotation was needed to avoid warnings while
ensuring that message extraction was not broken.

Closes #12099
2025-11-30 09:20:33 +01:00
Johannes Altmanninger
87a312ccba test/tmux-prompt: fix quoting that looks like a bug 2025-11-30 09:20:33 +01:00
Johannes Altmanninger
838f48a861 Show completions from separator only if there are no whole-token ones
Completions for "foo bar=baz" are sourced from
1. file paths (and custom completions) where "bar=baz" is a subsequence.
2. file paths where "baz" is a subsequence.

I'm not sure if there is ever a case where 1 is non-empty and we
still want to show 2.

Bravely include this property in our completion ranking, and only
show the best ones.

This enables us to get rid of the hack added by b6c249be0c (Back out
"Escape : and = in file completions", 2025-01-10).

Closes #5363
2025-11-30 09:20:33 +01:00
Johannes Altmanninger
52286f087d builtins set: only one space between list elements 2025-11-30 09:20:33 +01:00
Johannes Altmanninger
902d4be664 __fish_git_remotes: use POSIX regex syntax
Fixes https://github.com/fish-shell/fish-shell/pull/11941#issuecomment-3574089216
2025-11-30 09:19:03 +01:00
Johannes Altmanninger
16a91f8e3c Fix regression interpreting prompt y on multiline commandlines
Fixes a772470b76 (Multi-line autosuggestions, 2025-05-18)
Fixes #12121
2025-11-30 08:09:28 +01:00
Johannes Altmanninger
3cac5ff75e Fix "cargo-deny" check 2025-11-30 08:09:28 +01:00
Daniel Rainer
5210c16bfa printf: simplify conversion specifiers
This is another case where we can don't need to use complicated
formatting specifiers. There is also no need to use `wgettext_fmt` for
messages which don't contain any localizable parts.

The instances using `sprintf` could be kept as is, but I think it's
better to keep the width computation at the place where it can sensibly
be done, even though it is not done correctly at the moment because it
does not use grapheme widths.

Removing complicated conversion specifiers from localized messages helps
with the transition to Fluent.

Closes #12119
2025-11-30 00:40:52 +00:00
Daniel Rainer
8a75bccf00 printf: simplify conversion specifier
We already compute the length of the substring we want to print in Rust.
Passing that length as the precision to let printf formatting limit the
length is brittle, as it requires that the same semantics for "length"
are used.

Simplifying conversion specifiers also makes the transition to Fluent
easier.

Part of #12119
2025-11-30 00:40:52 +00:00
David Adam
5130fc6f17 build_tools: add script to get supported Ubuntu versions 2025-11-29 00:05:24 +08:00
David Adam
b0a04f8648 release.sh: update Debian changelog as part of release 2025-11-28 21:21:27 +08:00
David Adam
60f41a738d Debian packaging: add historical changelog 2025-11-27 23:39:47 +08:00
David Adam
9814bae727 Debian packaging: upgrade to debhelper compat 13 2025-11-26 22:55:33 +08:00
David Adam
63cc800cd1 Debian packaging: fix variable exports in debian/rules
This ended up setting the variable to "true ", which cargo did not
understand.
2025-11-26 22:05:35 +08:00
David Adam
47c139b916 Debian packaging: drop obsolete dependencies 2025-11-26 21:03:52 +08:00
David Adam
107352c000 Debian packaging: update to Debian policy 4.6.2 2025-11-26 20:58:17 +08:00
David Adam
26cb522140 Debian packaging: move to contrib/debian directory
This is the location requested by Debian's Upstream Guide, and means it
can be included in tarballs, simplifying the build process.
2025-11-25 21:43:36 +08:00
oliwia
7db3009968 docs: typo 2025-11-25 10:30:47 +08:00
Daniel Rainer
13e296db76 license: allow fish's own license identifiers
The newly added `cargo deny check licenses` command complains about the
licenses added in this commit not being explicitly allowed, so add them
to the config here. There is no intended change in semantics.

Closes #12097
2025-11-23 16:25:12 +01:00
Johannes Altmanninger
6fa992c8d3 sphinx: exclude *.inc.rst files
Sections like "Synopsis" wrongly show up in the toctree in
build/user_doc/html/commands.html.  Skip them.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
7ca78e7178 share/functions: fix path to /bin/sh on android
As mentioned in https://github.com/fish-shell/fish-shell/issues/12055#issuecomment-3554869126

> instances of `/bin/sh` as freestanding commands within `.fish`
> files are most likely not automatically handled by `termux-exec`

and

> This topic is complicated by the fact that some Android ROMs _do_
> contain real `/bin/sh` files

Core uses /system/bin/sh on Android.  Let's do the same from script
(even if /bin/sh exists), for consistency.
2025-11-23 12:30:22 +01:00
Daniel Rainer
2ee4f239d1 build_helper: add rebuild function for embedded path change
For paths embedded via `rust-embed`, we only need to rebuild on path
changes if the files are actually embedded.

To avoid having to remember and duplicate this logic for all embedded
paths, extract it into the build helper.

Closes #12083
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
4ffa06fb7e Fix section names in suggested "help" commands
Fixes 2cd60077e6 (help: get section titles from Sphinx, 2025-11-05)
Fixes #12082
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
a1baf97f54 Do not embed man pages in CMake builds
Commit 0709e4be8b (Use standalone code paths by default, 2025-10-26)
mainly wanted to embed internal functions to unbreak upgrade scenarios.

Embedding man pages in CMake has small-ish disadvantages:
1. extra space usage
2. less discoverability
3. a "cyclic" dependency:
   1. "sphinx-docs" depends on "fish_indent"
   2. "fish_indent" via "crates/build-man-pages" depends on "doc_src/".
   So every "touch doc_src/foo.rst && ninja -Cbuild sphinx-docs"
   re-builds fish, just to re-run sphinx-build.

The significant one is number 3.  It can be worked around by running
sphinx-build with stale "fish_indent" but I don't think we want to
do that.

Let's backtrack a little by stopping embedding man pages in CMake
builds; use the on-disk man pages (which we still install).

The remaining "regression" from 0709e4be8b is that "ninja -Cbuild
fish" needs to rebuild whenever anything in "share/" changes.  I don't
know if that's also annoying?

Since man pages for "build/fish" are not in share/, expose the exact
path as $__fish_man_dir.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
2a7c57035e Readme: remove INSTALL_DOCS
As mentioned in b5aea3fd8b (Revert "[cmake] Fix installing docs",
2018-03-13), this should not be set by the user.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
19e1ad7cfe config_paths: don't fall back to compiled-in DOC_DIR from relocatable tree
When $RELOCATED_PREFIX/bin/fish detects that
$RELOCATED_PREFIX/share/fish and $RELOCATED_PREFIX/etc/fish exist,
it uses paths from $RELOCATED_PREFIX (which is determined at runtime,
based on $argv), and not the prefix determined at compile time.

Except we do use DOCDIR (= ${CMAKE_INSTALL_FULL_DOCDIR}). This
seems like a weird side effect of commit b758c0c335 (Relax the
requirement that we find a working 'doc' directory in order for fish
to be relocatable.  2014-01-17) which enabled relocatable logic in
scenarios where $PREFIX/share/doc/fish was not installed.

This is weird; fish's "help" command should not take docs from a
different prefix.

Always use the matching docdir. This shouldn't make any practical
difference because since commit b5aea3fd8b (Revert "[cmake] Fix
installing docs", 2018-03-13), $PREFIX/share/doc/fish/CHANGELOG.rst
is always installed.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
2ea3da4819 config_paths: disable the relocatable tree logic on Cargo builds
This only makes sense for builds that install directories like
$PREFIX/share/fish, $PREFIX/etc/fish.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
3b100fce2d Fix __fish_help_dir when running from build directory
When running fish from a CMake build directory ("build/fish"),
"__fish_help_dir" is wrong because we assume the tarball layout. Fix
that.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
0c67d0565a Commit help_sections data file
The help_sections.rs file was added to the tarball only as a quick hack.
There is a cyclic dependency between docs and fish:

"fish_indent" via "crates/build-man-pages" depends on "doc_src/".
So every "touch doc_src/foo.rst && ninja -Cbuild sphinx-docs"
re-builds fish.

In future "fish_indent" should not depend on "crates/build-man-pages".
Until then, a following commit wants to break this cyclic dependency
in a different way: we won't embed man pages (matching historical
behavior), which means that CMake builds won't need to run
sphinx-build.

But sphinx-build is also used for extracting help sections.

Also, the fix for #12082 will use help sections elsewhere in the code.

Prepare to remove the dependency on doc_src by committing the help
sections (we already do elsewhere).
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
95aeb16ca2 Remove embed-data feature flag
This mode still has some problems (see the next commit) but having
it behind a feature flag doesn't serve us. Let's commit to the parts
we want to keep and drop anything that we don't want.

To reduce diff noise, use "if false" in the code paths used by man
pages; a following commit will use them.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
4770ef2df8 Remove comment
There are lots of places that assume this.
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
0ee0f5df97 Remove stale comment
See e895f96f8a (Do not rely on `fish_indent` for version in Sphinx, 2025-08-19).
2025-11-23 12:30:22 +01:00
Johannes Altmanninger
4f5cad977c release.yml: assert that Sphinx is installed on macOS package builder 2025-11-23 12:30:22 +01:00
Johannes Altmanninger
bed2da9b83 Check license of dependencies in CI 2025-11-23 12:30:22 +01:00
Johannes Altmanninger
462fa9077a Fix wcwidth() on systems without C.UTF-8 locale
macOS has en_US.UTF-8 but not C.UTF-8, which leads to a glitch when
typing "🐟". Fix that by trying the user's locale first, restoring
historical behavior.

Fixes 71a962653d (Be explicit about setlocale() scope, 2025-10-24).

Reported-by: Ilya Grigoriev <ilyagr@users.noreply.github.com>
2025-11-23 12:30:22 +01:00
Fabian Boehm
0f9749c140 docs/set: Try to make it a little clearer that you can also query -x
Fixes #12094
2025-11-23 09:59:52 +01:00
Johannes Altmanninger
acae88e618 test tmux-first-prompt: disable in ASAN
Tracking issue: #11815
Closes #12084
2025-11-21 08:21:11 +01:00
Fabian Boehm
75bf46de70 Disable posix_spawn on android
Apparently it's broken:

9cbb0715a9/packages/fish/0001-build.rs.patch

Part of #12055
2025-11-19 17:42:41 +01:00
Fabian Boehm
f598186574 Move posix_spawn detection to build.rs
This is *simpler*, and would have made us detect the issue with broken
includes before.

Part of #12055
2025-11-19 17:42:35 +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
790beedbb0 Prefer terminal (client) OS for selecting native key bindings
When running fish inside SSH and local and remote OS differ, fish
uses key bindings for the remote OS, which is weird.  Fix that by
asking the terminal for the OS name.

This should be available on foot and kitty soon, see
https://codeberg.org/dnkl/foot/pulls/2217#issuecomment-8249741

Ref: #11107
2025-11-19 17:13:58 +01:00
Johannes Altmanninger
b1e681030b Add OSC 133 prompt end marker
iTerm2 displays commands in other UI widgets such as in Command History
(View → Toolbelt → Command History).  This needs prompt end marker
so the terminal can distinguish prompt from the command line.

Closes #11837
2025-11-19 17:13:58 +01:00
Johannes Altmanninger
5225b477ff io: minor cleanup 2025-11-19 17:13:58 +01:00
Johannes Altmanninger
c53b787339 Don't try to use partially-parsed colors on error
Historically, "fish_color_*" variables used a hand-written option
parser that would try to recover from invalid options.

Commit 037c1896d4 (Reuse wgetopt parsing for set_color for internal
colors, 2025-04-13) tried to preserve this recovering, but that
breaks WGetopter invariants.

I don't think this type of fallback is important, because
there's no reason we can't parse color variables (except maybe
forward-compatibility in future). Let's turn errors into the default
style; this should tell the user that their color is unsupported.

Fixes #12078
2025-11-19 17:13:58 +01:00
Johannes Altmanninger
64cb4398c6 Longer timeout on invalid escape sequences
For historical reasons, fish does not implement the VT state
machine but uses a relatively low timeout when reading
escape sequences.  This might be causing issues like
https://github.com/fish-shell/fish-shell/issues/11841#issuecomment-3544505235
so let's cautiously increase the timeout.

Make it opt-in and print a noisy error when we time out, so we can
find affected terminals.
2025-11-19 17:13:58 +01:00
Johannes Altmanninger
9165251a0b Feature flag for eventually disabling terminal workarounds
We've removed several terminal-specific workarounds but also added
some recently.  Most of the non-Apple issues have been reported
upstream.  Many of our workarounds were only meant to be temporary.
Some workarounds are unreliable and some can cause introduce other
problems.

Add a feature flag we can use later to let users turn off workarounds.

This doesn't disable anything yet, mostly because because despite being
off-by-default, this might surprise people who use "fish_features=all".
The fix would be "fish_features=all,no-omit-term-workarounds".
So we'd want a high degree of confidence.

For now we'll use this only with the next commit.

Closes #11819
2025-11-19 17:06:25 +01:00
Johannes Altmanninger
7e86e07fb0 Rename method for reading trailing escape sequence bytes 2025-11-19 16:42:45 +01:00
Johannes Altmanninger
02a6afd2b0 Link terminal workarounds with comments
It's hard to get rid of these workarounds. Let's at least brand them.

Ref: #11819
2025-11-19 16:42:45 +01:00
Johannes Altmanninger
0b414b9662 __fish_print_help: proper error message when 'man' is missing
Commit 3f2e4b71bc (functions/__fish_print_help: bravely remove
fallback to mandoc/groff, 2025-11-09) savagely made commands like
"abbr -h" require man, or else it prints a noisy stack trace.
Some packages have not yet replaced "nroff/mandoc" with "man"
as dependency, and, independent of that, man is still an optional
dependency.

Make missing "man" a proper error, which is easier to read tan the
stack trace.
2025-11-19 16:40:57 +01:00
Johannes Altmanninger
012007ce7b Test balloon for ST OSC terminator
Use \e\\ as sequence terminator for the first OSC 133 prompt start
marker.  The intention is to find out if a terminal fails to parse
this. If needed, the user can turn it off by adding "no-mark-prompt"
to their feature flags; but the shell is still usable without this.

Part of #12032
2025-11-19 16:40:57 +01:00
Daniel Rainer
031d501381 history: move consts into function
These consts are only used in a single function, so they don't need to
be defined outside of the function.

c323a2d5fe (r170141065)

Closes #12075
2025-11-19 16:40:57 +01:00
Johannes Altmanninger
b0773890ea Fix inconsistent usage of /bin/sh vs. sh
For now, we mostly use "/bin/sh" for background tasks; but sometimes
we call it as "sh". The former does not work on android, but I'm not
yet sure how we should fix that.

Let's make things consistent first, so they are easier to change
(we might remove some background tasks, or reimplement them in fish
script).
2025-11-19 16:40:57 +01:00
Johannes Altmanninger
55b3b6af79 __fish_anypython: remove hardcoded list of minor versions
We always use python3 but don't use, say python3.999 until we update
our hardcoded list.  This is inconsistent (we're careful about the
latter but not the former).  Fix this by always picking the highest
minor version (>= 3.5+) there is. This also reduces maintenance work.

Note that NetBSD is the only OS we know about that doesn't provide
the python3 symlink OOTB.  In future, the NetBSD package should
add a patch to replace "python3" in __fish_anypython.fish
with the correct path.  Downstream discussion is at
https://mail-index.netbsd.org/pkgsrc-users/2025/11/17/msg042205.html
2025-11-19 16:40:57 +01:00
Johannes Altmanninger
1bcfc64e13 status list-files: support multiple arguments
This fixes an issue in fish_config, see
ee94272eaf (commitcomment-170660405)
2025-11-19 16:36:14 +01:00
Johannes Altmanninger
7b4802091a cmake: install fish_{indent,key_reader} as hardlinks to fish
As mentioned in
https://github.com/fish-shell/fish-shell/issues/11921#issuecomment-3540587001,
binaries duplicate a lot of information unnecessarily.

	$ cargo b --release
	$ du -h target/release/fish{,_indent,_key_reader}
	15M	target/release/fish
	15M	target/release/fish_indent
	4.1M	target/release/fish_key_reader
	34M	total

Remove the duplication in CMake-installed builds by creating hard
links. I'm not sure how to do that for Cargo binaries yet (can we
write a portable wrapper script)?

This is still a bit weird because hardlinks are rarely used like
this; but symlinks may cause issues on MSYS2.  Maybe we should write
a /bin/sh wrapper script instead.
2025-11-19 16:36:14 +01:00
Zhizhen He
7774c74826 Fix typos
Closes #12071
2025-11-19 16:36:14 +01:00
Johannes Altmanninger
97e58f381b Fix warning when libc::c_char is unsigned (ARM) 2025-11-19 16:36:14 +01:00
Johannes Altmanninger
015f247998 build.rs: use the correct target OS where easily possible
This might help cross-compilation; even if it doesn't matter in
practice, this is more correct.  While at it, get rid of $TARGET in
favor of the more accurate $CARGO_CFG_TARGET_OS.
Not yet sure how to do it for "has_small_stack".
2025-11-19 16:36:14 +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
7fdb1b4d1f dir_iter: unexport a test-only getter 2025-11-19 16:36:14 +01:00
Juho Kuisma
fb83a86c17 Fix broken translations
Fixes 302c33e377 (Deduplicate and fix broken translations, 2025-11-16)
2025-11-16 19:16:07 +01:00
Johannes Altmanninger
289057f981 reset_abandoning_line: actually clear line on first prompt
Frequently when I launch a new shell and type away, my input is
echoed in the terminal before fish gets a chance to set shell modes
(turn off ECHO and put the terminal into non-canonical mode).

This means that fish assumption about the cursor x=0 is wrong, which
causes the prompt (here '$ ') to be draw at the wrong place, making
it look like this:

	ececho hello

This seems to have been introduced in 4.1.0 in a0e687965e (Fix
unsaved screen modification, 2025-01-14). Not sure how it wasn't a
problem before.

Fix this by clearing to the beginning of the line after turning off
ECHO but before we draw anything to the screen.

This turns this comment in the patch context into a true statement:

> This means that `printf %s foo; fish` will overwrite the `foo`

Note that this currently applies per-reader, so builtin "read" will
also clear the line before doing anything.
We could potentially change this in future, if we both
1. query the cursor x before we output anything
2. refactor the screen module to properly deal with x>0 states.

But even if we did that, it wouldn't change the fact that we want
to force x=0 if the cursor has only been moved due to ECHO, so I'm
not sure.
2025-11-16 11:47:47 +01:00
Johannes Altmanninger
b48106a741 reset_abandoning_line: extract function
Helps the next commit.
2025-11-16 11:33:11 +01:00
Johannes Altmanninger
fbad0ab50a reset_abandoning_line: remove redundant allocations 2025-11-16 11:33:11 +01:00
Johannes Altmanninger
a8bf4db32d release.sh: minor fixes
After pushing to the fish-site repo, make sure to update the local
repo's view of origin/master to what we have successfully pushed.
2025-11-16 11:33:11 +01:00
huaji2369
b33bad1258 add waydroid completions
Closes #12056
2025-11-16 11:27:02 +01:00
seg6
29024806e5 tests: minimum python version validation for user facing scripts
Adds [`Vermin`](https://github.com/netromdk/vermin) to make sure our
user facing Python scripts conform to the proper minimum Python version
requirements.

The tool parses Python code into an AST and checks it against a database
of rules covering Python 2.0-3.13.

Testing Python version compatibility is tricky because most issues only
show up at runtime. Type annotations like `str | None` (Python 3.10+)
compile just fine (under pyc) and they don't throw an exception until
you actually call the relevant function.

This makes it hard to catch compatibility bugs without running the code
(through all possible execution paths) on every Python version.

Signed-off-by: seg6 <hi@seg6.space>

Closes #12044
2025-11-16 11:21:18 +01:00
seg6
4ef1f993a1 share: functions: __fish_anypython: update Python 3 version list
Signed-off-by: seg6 <hi@seg6.space>

Part of #12044
2025-11-16 11:21:18 +01:00
seg6
7297178091 share: tools: create_manpage_completions: drop Python 2 related code
Signed-off-by: seg6 <hi@seg6.space>

Part of #12044
2025-11-16 11:21:18 +01:00
seg6
3786c20dcf share: tools: web_config: drop Python 2 related code
Signed-off-by: seg6 <hi@seg6.space>

Part of #12044
2025-11-16 11:21:18 +01:00
Nahor
125fc142ba Add mutex around flock on Cygwin
Issue #11933 stems from Cygwin's flock implementation not being thread
safe. Previous code fixed the worst behavior (deadlock), at least in
some circumstance but still failed the history tests.

This new workaround correctly make flock usage thread safe by surrounding
it with a mutex lock.
The failing test can now pass and is much faster (5s instead of 15 on
my machine)

Upstream bug report: https://cygwin.com/pipermail/cygwin/2025-November/258963.html

Closes #12068
Closes #11933
2025-11-16 11:21:18 +01:00
exploide
d716b32bed completions/john: updated and improved completions
Closes #12051
2025-11-16 11:21:18 +01:00
Daniel Rainer
a56b1099aa tempfile: use std::env:temp_dir
This is a more robust implementation of our custom `get_tmpdir`.

Closes #12046
2025-11-16 11:21:18 +01:00
Johannes Altmanninger
f3f231cf70 __fish_apropos: assume only /usr/bin/apropos is broken
As discovered in #12062, man-db as installed from brew is not affected
by the "read-only-filesystem" problem what makewhatis suffers from
(though users do need to run "gmandb" once).

Restrict the workaround to the path to macOS's apropos; hopefully
that's stable.

This breaks people who define an alias for apropos; I guess for those
we could check "command -v" instead, but that's weird because the thing
found by type is the actual thing we're gonna execute.  So I'd first
rather want to find out why anyone would override this obscure command.
2025-11-16 11:21:18 +01:00
Johannes Altmanninger
c49ff931b1 __fish_apropos: remove stale version check
Most macOS versions are affeced nowadays.  Let's make this more
predictable by applying the workaround to them all.
2025-11-16 11:12:30 +01:00
Johannes Altmanninger
d3c3dfda7d Extract workaround for calling man/apropos without manpager
See ec939fb22f (Work around BSD man calling pager when stdout is
not a TTY, 2024-10-30).
2025-11-16 11:12:30 +01:00
Juho Kuisma
302c33e377 Deduplicate and fix broken translations
Co-authored-by: Johannes Altmanninger <aclopte@gmail.com>
2025-11-16 11:12:30 +01:00
Johannes Altmanninger
e77b1c9744 __fish_cached: tolerate trailing newline
In POSIX sh, ";" is not a valid statement, leading to errors when the
__fish_cached callback argument has a trailing newline (5c2073135e
(Fix syntax error in __fish_print_port_packages.fish, 2025-11-14)).

Use a newline instead of ";", to avoid this error.

While at it, replace rogue tab characters.
2025-11-16 11:04:23 +01:00
441 changed files with 12396 additions and 6698 deletions

View File

@@ -27,7 +27,7 @@ freebsd_task:
matrix:
- name: FreeBSD Stable
freebsd_instance:
image: freebsd-14-3-release-amd64-ufs # updatecli.d/cirrus-freebsd.yml
image: freebsd-15-0-release-amd64-ufs # updatecli.d/cirrus-freebsd.yml
tests_script:
- pkg install -y cmake-core devel/pcre2 devel/ninja gettext git-lite lang/rust misc/py-pexpect
# libclang.so is a required build dependency for rust-c++ ffi bridge

View File

@@ -14,7 +14,6 @@ indent_style = tab
[*.{md,rst}]
max_line_length = unset
trim_trailing_whitespace = false
[*.sh]
indent_size = 4

2
.gitattributes vendored
View File

@@ -14,8 +14,6 @@
.gitattributes export-ignore
.gitignore export-ignore
/build_tools/make_tarball.sh export-ignore
/debian export-ignore
/debian/* export-ignore
/.github export-ignore
/.github/* export-ignore
/.builds export-ignore

View File

@@ -10,11 +10,13 @@ runs:
run: |
set -x
sudo pip install uv --break-system-packages
command -v uv
command -v uvx
# Check that pyproject.toml and the lock file are in sync.
# TODO Use "uv" to install Python as well.
: 'Note that --no-managed-python below would be implied but be explicit'
uv='env UV_PYTHON=python uv --no-managed-python'
$uv lock --check
$uv lock --check --exclude-newer="$(awk -F'"' <uv.lock '/^exclude-newer[[:space:]]*=/ {print $2}')"
# Install globally.
sudo $uv pip install --group=dev --system --break-system-packages
# Smoke test.

View File

@@ -25,7 +25,7 @@ runs:
set -x
toolchain=$(
case "$toolchain_channel" in
(stable) echo 1.91 ;; # updatecli.d/rust.yml
(stable) echo 1.92 ;; # updatecli.d/rust.yml
(msrv) echo 1.85 ;; # updatecli.d/rust.yml
(*)
printf >&2 "error: unsupported toolchain channel %s" "$toolchain_channel"

24
.github/workflows/lint-dependencies.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Lint Dependencies
on:
push:
paths:
- '.github/workflows/lint-dependencies.yml'
- 'Cargo.lock'
- '**/Cargo.toml'
- 'deny.toml'
pull_request:
paths:
- '.github/workflows/lint-dependencies.yml'
- 'Cargo.lock'
- '**/Cargo.toml'
- 'deny.toml'
jobs:
cargo-deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check licenses
arguments: --all-features --locked --exclude-dev
rust-version: 1.92 # updatecli.d/rust.yml

View File

@@ -172,7 +172,7 @@ jobs:
echo "$MACOS_NOTARIZE_JSON" >/tmp/notarize.json
./build_tools/make_macos_pkg.sh -s -f /tmp/app.p12 \
-i /tmp/installer.p12 -p "$MAC_CODESIGN_PASSWORD" \
-n -j /tmp/notarize.json
-n -j /tmp/notarize.json -- -c "-DWITH_DOCS=ON"
version=$(git describe)
[ -f "${FISH_ARTEFACT_PATH}/fish-$version.app.zip" ]
[ -f "${FISH_ARTEFACT_PATH}/fish-$version.pkg" ]

View File

@@ -1,5 +1,69 @@
fish ?.?.? (released ???)
=========================
fish 4.3.0 (released December 28, 2025)
=======================================
Deprecations and removed features
---------------------------------
- fish no longer sets :ref:`universal variables <variables-universal>` by default, making the configuration easier to understand.
Specifically, the ``fish_color_*``, ``fish_pager_color_*`` and ``fish_key_bindings`` variables are now set in the global scope by default.
After upgrading to 4.3.0, fish will (once and never again) migrate these universals to globals set at startup in the
``~/.config/fish/conf.d/fish_frozen_theme.fish`` and
``~/.config/fish/conf.d/fish_frozen_key_bindings.fish`` files.
We suggest that you delete those files and :ref:`set your theme <syntax-highlighting>` in ``~/.config/fish/config.fish``.
- You can still configure fish to propagate theme changes instantly; see :ref:`here <syntax-highlighting-instant-update>` for an example.
- You can still opt into storing color variables in the universal scope
via ``fish_config theme save`` though unlike ``fish_config theme choose``,
it does not support dynamic theme switching based on the terminal's color theme (see below).
- In addition to setting the variables which are explicitly defined in the given theme,
``fish_config theme choose`` now clears only color variables that were set by earlier invocations of a ``fish_config theme choose`` command
(which is how fish's default theme is set).
Scripting improvements
----------------------
- New :ref:`status language <status-language>` command allows showing and modifying language settings for fish messages without having to modify environment variables.
- When using a noninteractive fish instance to compute completions, ``commandline --cursor`` works as expected instead of throwing an error (:issue:`11993`).
- :envvar:`fish_trace` can now be set to ``all`` to also trace execution of key bindings, event handlers as well as prompt and title functions.
Interactive improvements
------------------------
- When typing immediately after starting fish, the first prompt is now rendered correctly.
- Completion accuracy was improved for file paths containing ``=`` or ``:`` (:issue:`5363`).
- Prefix-matching completions are now shown even if they don't match the case typed by the user (:issue:`7944`).
- On Cygwin/MSYS, command name completion will favor the non-exe name (``foo``) unless the user started typing the extension.
- When using the exe name (``foo.exe``), fish will use to the description and completions for ``foo`` if there are none for ``foo.exe``.
- Autosuggestions now also show soft-wrapped portions (:issue:`12045`).
New or improved bindings
------------------------
- :kbd:`ctrl-w` (``backward-kill-path-component``) also deletes escaped spaces (:issue:`2016`).
- New special input functions ``backward-path-component``, ``forward-path-component`` and ``kill-path-component`` (:issue:`12127`).
Improved terminal support
-------------------------
- Themes can now be made color-theme-aware by including both ``[light]`` and ``[dark]`` sections in the :ref:`theme file <fish-config-theme-files>`.
Some default themes have been made color-theme-aware, meaning they dynamically adjust as your terminal's background color switches between light and dark colors (:issue:`11580`).
- The working directory is now reported on every fresh prompt (via OSC 7), fixing scenarios where a child process (like ``ssh``) left behind a stale working directory (:issue:`12191`).
- OSC 133 prompt markers now also mark the prompt end, which improves shell integration with terminals like iTerm2 (:issue:`11837`).
- Operating-system-specific key bindings are now decided based on the :ref:`terminal's host OS <status-terminal-os>`.
- Focus reporting is enabled unconditionally, not just inside tmux.
To use it, define functions that handle the ``fish_focus_in`` or ``fish_focus_out`` :ref:`events <event>`.
- New :ref:`feature flag <featureflags>` ``omit-term-workarounds`` can be turned on to prevent fish from trying to work around some incompatible terminals.
For distributors and developers
-------------------------------
- Tarballs no longer contain prebuilt documentation,
so building and installing documentation requires Sphinx.
To avoid users accidentally losing docs, the ``BUILD_DOCS`` and ``INSTALL_DOCS`` configuration options have been replaced with a new ``WITH_DOCS`` option.
- ``fish_key_reader`` and ``fish_indent`` are now installed as hardlinks to ``fish``, to save some space.
Regression fixes:
-----------------
- (from 4.1.0) Crash on incorrectly-set color variables (:issue:`12078`).
- (from 4.1.0) Crash when autosuggesting Unicode characters with nontrivial lowercase mapping.
- (from 4.2.0) Incorrect emoji width computation on macOS.
- (from 4.2.0) Mouse clicks and :kbd:`ctrl-l` edge cases in multiline command lines (:issue:`12121`).
- (from 4.2.0) Completions for Git remote names on some non-glibc systems.
- (from 4.2.0) Expansion of ``~$USER``.
fish 4.2.1 (released November 13, 2025)
=======================================
@@ -105,7 +169,7 @@ This release fixes the following regressions identified in 4.1.0:
This will not affect fish's child processes unless ``LC_MESSAGES`` was already exported.
- Some :doc:`fish_config <cmds/fish_config>` subcommands for showing prompts and themes had been broken in standalone Linux builds (those using the ``embed-data`` cargo feature), which has been fixed (:issue:`11832`).
- On Windows Terminal, we observed an issue where fish would fail to read the terminal's response to our new startup queries, causing noticeable lags and a misleading error message. A workaround has been added (:issue:`11841`).
- On Windows Terminal, we observed an issue where fish would fail to read the terminal's response to our new startup queries, causing noticeable lags and a misleading error message. A workaround has been added (:issue:`11841`).
- A WezTerm `issue breaking shifted key input <https://github.com/wezterm/wezterm/issues/6087>`__ has resurfaced on some versions of WezTerm; our workaround has been extended to cover all versions for now (:issue:`11204`).
- Fixed a crash in :doc:`the web-based configuration tool <cmds/fish_config>` when using the new underline styles (:issue:`11840`).

View File

@@ -42,9 +42,7 @@ set(VARS_FOR_CARGO
"CARGO_TARGET_DIR=${FISH_RUST_BUILD_DIR}"
"CARGO_BUILD_RUSTC=${Rust_COMPILER}"
"${FISH_PCRE2_BUILDFLAG}"
"RUSTFLAGS=$ENV{RUSTFLAGS} ${rust_debugflags}"
"FISH_SPHINX=${SPHINX_EXECUTABLE}"
"FISH_USE_PREBUILT_DOCS=${USE_PREBUILT_DOCS}"
)
# Let fish pick up when we're running out of the build directory without installing
@@ -58,37 +56,40 @@ if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST build_types)
message(WARNING "Unsupported build type ${CMAKE_BUILD_TYPE}. If this doesn't build, try one of Release, RelWithDebInfo or Debug")
endif()
# Define a function to build and link dependencies.
function(CREATE_TARGET target)
add_custom_target(
fish ALL
COMMAND
"${CMAKE_COMMAND}" -E
env ${VARS_FOR_CARGO}
${Rust_CARGO}
build --bin fish
$<$<CONFIG:Release>:--release>
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
--target ${Rust_CARGO_TARGET}
--no-default-features
--features=${FISH_CARGO_FEATURES}
${CARGO_FLAGS}
&&
"${CMAKE_COMMAND}" -E
copy "${rust_target_dir}/${rust_profile}/fish" "${CMAKE_CURRENT_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
USES_TERMINAL
)
function(CREATE_LINK target)
add_custom_target(
${target} ALL
COMMAND
"${CMAKE_COMMAND}" -E
env ${VARS_FOR_CARGO}
${Rust_CARGO}
build --bin ${target}
$<$<CONFIG:Release>:--release>
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
--target ${Rust_CARGO_TARGET}
--no-default-features
--features=${FISH_CARGO_FEATURES}
${CARGO_FLAGS}
&&
"${CMAKE_COMMAND}" -E
copy "${rust_target_dir}/${rust_profile}/${target}" "${CMAKE_CURRENT_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
USES_TERMINAL
DEPENDS fish
COMMAND ln -f fish ${target}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
endfunction(CREATE_TARGET)
# Define fish.
create_target(fish)
endfunction(CREATE_LINK)
# Define fish_indent.
create_target(fish_indent)
create_link(fish_indent)
# Define fish_key_reader.
create_target(fish_key_reader)
create_link(fish_key_reader)
# Set up tests.
include(cmake/Tests.cmake)

View File

@@ -21,10 +21,10 @@ Archives are available at https://lists.sr.ht/~krobelus/fish-shell/.
GitHub
======
Fish is available on Github, at https://github.com/fish-shell/fish-shell.
Fish is available on GitHub, at https://github.com/fish-shell/fish-shell.
First, you'll need an account there, and you'll need a git clone of fish.
Fork it on Github and then run::
Fork it on GitHub and then run::
git clone https://github.com/<USERNAME>/fish-shell.git
@@ -52,6 +52,23 @@ In short:
- Be conservative in what you need (keep to the agreed minimum supported Rust version, limit new dependencies)
- Use automated tools to help you (``build_tools/check.sh``)
Commit History
==============
We use a linear, `recipe-style <https://www.bitsnbites.eu/git-history-work-log-vs-recipe/>`__ history.
Every commit should pass our checks.
We do not want "fixup" commits in our history.
If you notice an issue with a commit in a pull request, or get feedback suggesting changes,
you should rewrite the commit history and fix the relevant commits directly,
instead of adding new "fixup" commits.
When a pull request is ready, we rebase it on top of the current master branch,
so don't be shy about rewriting the history of commits which are not on master yet.
Rebasing (not merging) your pull request on the latest version of master is also welcome, especially if it resolves conflicts.
If you're using Git, consider using `jj <https://www.jj-vcs.dev/>`__ to make this easier.
If a commit should close an issue, add a ``Fixes #<issue-number>`` line at the end of the commit description.
Contributing completions
========================
@@ -89,11 +106,18 @@ Contributing documentation
The documentation is stored in ``doc_src/``, and written in ReStructured Text and built with Sphinx.
To build it locally, run from the main fish-shell directory::
To build it locally, run either::
sphinx-build -j 8 -b html -n doc_src/ /tmp/fish-doc/
sphinx-build -j auto -b html doc_src/ /tmp/fish-doc/
which will build the docs as html in /tmp/fish-doc. You can open it in a browser and see that it looks okay.
which will output HTML docs to /tmp/fish-doc.
You can open it in a browser and see that it looks okay.
Alternatively, you can use::
cmake --build build -t sphinx-docs
which outputs to build/user_doc/html/.
The builtins and various functions shipped with fish are documented in doc_src/cmds/.
@@ -175,7 +199,7 @@ The source code for fish includes a large collection of tests. If you
are making any changes to fish, running these tests is a good way to make
sure the behaviour remains consistent and regressions are not
introduced. Even if you dont run the tests on your machine, they will
still be run via Github Actions.
still be run via GitHub Actions.
You are strongly encouraged to add tests when changing the functionality
of fish, especially if you are fixing a bug to help ensure there are no
@@ -233,9 +257,8 @@ It also means that some features are not supported, such as message context and
We also expect all files to be UTF-8-encoded.
In practice, this should not matter much for contributing translations.
Translation sources are
stored in the ``po`` directory, named ``ll_CC.po``, where ``ll`` is the
two (or possibly three) letter ISO 639-1 language code of the target language
Translation sources are stored in the ``localization/po`` directory and named ``ll_CC.po``,
where ``ll`` is the two (or possibly three) letter ISO 639-1 language code of the target language
(e.g. ``pt`` for Portuguese). ``CC`` is an ISO 3166 country/territory code,
(e.g. ``BR`` for Brazil).
An example for a valid name is ``pt_BR.po``, indicating Brazilian Portuguese.
@@ -249,7 +272,7 @@ More specifically, you will need ``msguniq`` and ``msgmerge`` for creating trans
language.
To create a new translation, run::
build_tools/update_translations.fish po/ll_CC.po
build_tools/update_translations.fish localization/po/ll_CC.po
This will create a new PO file containing all messages available for translation.
If the file already exists, it will be updated.
@@ -295,7 +318,7 @@ Editing PO files
Many tools are available for editing translation files, including
command-line and graphical user interface programs. For simple use, you can use your text editor.
Open up the PO file, for example ``po/sv.po``, and you'll see something like::
Open up the PO file, for example ``localization/po/sv.po``, and you'll see something like::
msgid "%s: No suitable job\n"
msgstr ""
@@ -323,7 +346,7 @@ Modifications to strings in source files
If a string changes in the sources, the old translations will no longer work.
They will be preserved in the PO files, but commented-out (starting with ``#~``).
If you add/remove/change a translatable strings in a source file,
run ``build_tools/update_translations.fish`` to propagate this to all translation files (``po/*.po``).
run ``build_tools/update_translations.fish`` to propagate this to all translation files (``localization/po/*.po``).
This is only relevant for developers modifying the source files of fish or fish scripts.
Setting Code Up For Translations

139
Cargo.lock generated
View File

@@ -152,7 +152,7 @@ checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
[[package]]
name = "fish"
version = "4.2.1-snapshot"
version = "4.3.0"
dependencies = [
"bitflags",
"cc",
@@ -160,11 +160,15 @@ dependencies = [
"errno",
"fish-build-helper",
"fish-build-man-pages",
"fish-common",
"fish-fallback",
"fish-gettext",
"fish-gettext-extraction",
"fish-gettext-maps",
"fish-gettext-mo-file-parser",
"fish-printf",
"fish-tempfile",
"fish-wchar",
"fish-widecharwidth",
"libc",
"lru",
"macro_rules_attribute",
@@ -172,16 +176,16 @@ dependencies = [
"num-traits",
"once_cell",
"pcre2",
"phf 0.12.1",
"phf_codegen 0.12.1",
"portable-atomic",
"rand",
"rand 0.9.2",
"rsconf",
"rust-embed",
"serial_test",
"terminfo",
"unix_path",
"widestring",
"xterm-color",
]
[[package]]
@@ -199,11 +203,45 @@ dependencies = [
"rsconf",
]
[[package]]
name = "fish-common"
version = "0.0.0"
dependencies = [
"libc",
"nix",
"once_cell",
]
[[package]]
name = "fish-fallback"
version = "0.0.0"
dependencies = [
"fish-build-helper",
"fish-common",
"fish-wchar",
"fish-widecharwidth",
"libc",
"once_cell",
"rsconf",
"widestring",
]
[[package]]
name = "fish-gettext"
version = "0.0.0"
dependencies = [
"fish-gettext-maps",
"once_cell",
"phf 0.12.1",
]
[[package]]
name = "fish-gettext-extraction"
version = "0.0.0"
dependencies = [
"fish-tempfile",
"proc-macro2",
"rsconf",
]
[[package]]
@@ -236,8 +274,21 @@ name = "fish-tempfile"
version = "0.0.0"
dependencies = [
"nix",
"rand 0.9.2",
]
[[package]]
name = "fish-wchar"
version = "0.0.0"
dependencies = [
"fish-common",
"widestring",
]
[[package]]
name = "fish-widecharwidth"
version = "0.0.0"
[[package]]
name = "fnv"
version = "1.0.7"
@@ -522,7 +573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared 0.11.3",
"rand",
"rand 0.8.5",
]
[[package]]
@@ -565,6 +616,15 @@ version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
@@ -595,7 +655,27 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha",
"rand_core 0.9.3",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@@ -604,6 +684,15 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.4",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
@@ -652,9 +741,9 @@ dependencies = [
[[package]]
name = "rust-embed"
version = "8.8.0"
version = "8.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb44e1917075637ee8c7bcb865cf8830e3a92b5b1189e44e3a0ab5a0d5be314b"
checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
@@ -663,9 +752,9 @@ dependencies = [
[[package]]
name = "rust-embed-impl"
version = "8.8.0"
version = "8.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382499b49db77a7c19abd2a574f85ada7e9dbe125d5d1160fa5cad7c4cf71fc9"
checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2"
dependencies = [
"proc-macro2",
"quote",
@@ -677,9 +766,9 @@ dependencies = [
[[package]]
name = "rust-embed-utils"
version = "8.8.0"
version = "8.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21fcbee55c2458836bcdbfffb6ec9ba74bbc23ca7aa6816015a3dd2c4d8fc185"
checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475"
dependencies = [
"globset",
"sha2",
@@ -954,3 +1043,29 @@ name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
[[package]]
name = "xterm-color"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4de5f056fb9dc8b7908754867544e26145767187aaac5a98495e88ad7cb8a80f"
[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -6,6 +6,9 @@ members = ["crates/*"]
rust-version = "1.85"
edition = "2024"
repository = "https://github.com/fish-shell/fish-shell"
# see doc_src/license.rst for details
# don't forget to update COPYING and debian/copyright too
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
[workspace.dependencies]
bitflags = "2.5.0"
@@ -14,11 +17,16 @@ cfg-if = "1.0.3"
errno = "0.3.0"
fish-build-helper = { path = "crates/build-helper" }
fish-build-man-pages = { path = "crates/build-man-pages" }
fish-common = { path = "crates/common" }
fish-fallback = { path = "crates/fallback" }
fish-gettext = { path = "crates/gettext" }
fish-gettext-extraction = { path = "crates/gettext-extraction" }
fish-gettext-maps = { path = "crates/gettext-maps" }
fish-gettext-mo-file-parser = { path = "crates/gettext-mo-file-parser" }
fish-printf = { path = "crates/printf", features = ["widestring"] }
fish-tempfile = { path = "crates/tempfile" }
fish-wchar = { path = "crates/wchar" }
fish-widecharwidth = { path = "crates/widecharwidth" }
libc = "0.2.177"
# lru pulls in hashbrown by default, which uses a faster (though less DoS resistant) hashing algo.
# disabling default features uses the stdlib instead, but it doubles the time to rewrite the history
@@ -29,6 +37,7 @@ nix = { version = "0.30.1", default-features = false, features = [
"inotify",
"resource",
"fs",
"term",
] }
num-traits = "0.2.19"
once_cell = "1.19.0"
@@ -41,17 +50,16 @@ portable-atomic = { version = "1", default-features = false, features = [
"fallback",
] }
proc-macro2 = "1.0"
# Don't use the "getrandom" feature as it requires "getentropy" which was not
# available on macOS < 10.12. We can enable "getrandom" when we raise the
# minimum supported version to 10.12.
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
rand = { version = "0.9.2", default-features = false, features = [
"small_rng",
"thread_rng",
] }
rsconf = "0.2.2"
rust-embed = { version = "8.7.2", features = [
rust-embed = { version = "8.9.0", features = [
"deterministic-timestamps",
"include-exclude",
"interpolate-folder-path",
] }
serial_test = { version = "3", default-features = false }
# We need 0.9.0 specifically for some crash fixes.
terminfo = "0.9.0"
@@ -59,6 +67,7 @@ widestring = "1.2.0"
unicode-segmentation = "1.12.0"
unicode-width = "0.2.0"
unix_path = "1.0.1"
xterm-color = "1.0.1"
[profile.release]
overflow-checks = true
@@ -70,13 +79,11 @@ debug = true
[package]
name = "fish"
version = "4.2.1-snapshot"
version = "4.3.0"
edition.workspace = true
rust-version.workspace = true
default-run = "fish"
# see doc_src/license.rst for details
# don't forget to update COPYING and debian/copyright too
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
license.workspace = true
homepage = "https://fishshell.com"
readme = "README.rst"
@@ -86,10 +93,14 @@ cfg-if.workspace = true
errno.workspace = true
fish-build-helper.workspace = true
fish-build-man-pages = { workspace = true, optional = true }
fish-common.workspace = true
fish-fallback.workspace = true
fish-gettext = { workspace = true, optional = true }
fish-gettext-extraction = { workspace = true, optional = true }
fish-gettext-maps = { workspace = true, optional = true }
fish-printf.workspace = true
fish-tempfile.workspace = true
fish-wchar.workspace = true
fish-widecharwidth.workspace = true
libc.workspace = true
lru.workspace = true
macro_rules_attribute = "0.2.2"
@@ -97,23 +108,23 @@ nix.workspace = true
num-traits.workspace = true
once_cell.workspace = true
pcre2.workspace = true
phf = { workspace = true, optional = true }
rand.workspace = true
terminfo.workspace = true
xterm-color.workspace = true
widestring.workspace = true
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
portable-atomic.workspace = true
[target.'cfg(windows)'.dependencies]
rust-embed = { workspace = true, optional = true, features = [
rust-embed = { workspace = true, features = [
"deterministic-timestamps",
"debug-embed",
"include-exclude",
"interpolate-folder-path",
] }
[target.'cfg(not(windows))'.dependencies]
rust-embed = { workspace = true, optional = true, features = [
rust-embed = { workspace = true, features = [
"deterministic-timestamps",
"include-exclude",
"interpolate-folder-path",
@@ -149,12 +160,12 @@ name = "fish_key_reader"
path = "src/bin/fish_key_reader.rs"
[features]
default = ["embed-data", "localize-messages"]
default = ["embed-manpages", "localize-messages"]
benchmark = []
embed-data = ["dep:rust-embed", "dep:fish-build-man-pages"]
embed-manpages = ["dep:fish-build-man-pages"]
# Enable gettext localization at runtime. Requires the `msgfmt` tool to generate catalog data at
# build time.
localize-messages = ["dep:phf", "dep:fish-gettext-maps"]
localize-messages = ["dep:fish-gettext"]
# This feature is used to enable extracting messages from the source code for localization.
# It only needs to be enabled if updating these messages (and the corresponding PO files) is
# desired. This happens when running tests via `build_tools/check.sh` and when calling
@@ -174,8 +185,8 @@ rustdoc.private_intra_doc_links = "allow"
clippy.len_without_is_empty = "allow" # we're not a library crate
clippy.let_and_return = "allow"
clippy.manual_range_contains = "allow"
clippy.map_unwrap_or = "warn"
clippy.needless_lifetimes = "allow"
clippy.needless_return = "allow"
clippy.new_without_default = "allow"
clippy.option_map_unit_fn = "allow"

View File

@@ -37,7 +37,7 @@ fish can be installed:
- using the `installer from fishshell.com <https://fishshell.com/>`__
- as a `standalone app from fishshell.com <https://fishshell.com/>`__
Note: The minimum supported macOS version is 10.10 "Yosemite".
Note: The minimum supported macOS version is 10.12.
Packages for Linux
~~~~~~~~~~~~~~~~~~
@@ -157,10 +157,8 @@ In addition to the normal CMake build options (like ``CMAKE_INSTALL_PREFIX``), f
- Rust_COMPILER=path - the path to rustc. If not set, cmake will check $PATH and ~/.cargo/bin
- Rust_CARGO=path - the path to cargo. If not set, cmake will check $PATH and ~/.cargo/bin
- Rust_CARGO_TARGET=target - the target to pass to cargo. Set this for cross-compilation.
- BUILD_DOCS=ON|OFF - whether to build the documentation. This is automatically set to OFF when Sphinx isn't installed.
- INSTALL_DOCS=ON|OFF - whether to install the docs. This is automatically set to on when BUILD_DOCS is or prebuilt documentation is available (like when building in-tree from a tarball).
- WITH_DOCS=ON|OFF - whether to build the documentation. By default, this is ON when Sphinx is installed.
- FISH_USE_SYSTEM_PCRE2=ON|OFF - whether to use an installed pcre2. This is normally autodetected.
- MAC_CODESIGN_ID=String|OFF - the codesign ID to use on Mac, or "OFF" to disable codesigning.
- WITH_GETTEXT=ON|OFF - whether to include translations.
- extra_functionsdir, extra_completionsdir and extra_confdir - to compile in an additional directory to be searched for functions, completions and configuration snippets
@@ -185,13 +183,14 @@ You can also install Sphinx another way and drop the ``uv run --no-managed-pytho
This will place standalone binaries in ``~/.cargo/bin/``, but you can move them wherever you want.
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features --features=embed-data`` to cargo.
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features --features=embed-manpages`` to cargo.
You can also link this build statically (but not against glibc) and move it to other computers.
Here are the remaining advantages of a full installation, as currently done by CMake:
- Man pages like ``fish(1)`` installed in standard locations, easily accessible from outside fish.
- Separate files for builtins (e.g. ``$PREFIX/share/fish/man/man1/abbr.1``).
- A local copy of the HTML documentation, typically accessed via the ``help`` fish function.
In Cargo builds, ``help`` will redirect to `<https://fishshell.com/docs/current/>`__
- Ability to use our CMake options extra_functionsdir, extra_completionsdir and extra_confdir,

123
build.rs
View File

@@ -1,4 +1,7 @@
use fish_build_helper::{env_var, fish_build_dir, workspace_root};
use fish_build_helper::{
env_var, fish_build_dir, target_os, target_os_is_apple, target_os_is_bsd, target_os_is_cygwin,
workspace_root,
};
use rsconf::Target;
use std::env;
use std::path::{Path, PathBuf};
@@ -40,14 +43,7 @@ fn main() {
// safety: single-threaded code.
unsafe { std::env::set_var("FISH_BUILD_VERSION", version) };
// These are necessary if built with embedded functions,
// but only in release builds (because rust-embed in debug builds reads from the filesystem).
#[cfg(feature = "embed-data")]
#[cfg(any(windows, not(debug_assertions)))]
rsconf::rebuild_if_path_changed("share");
#[cfg(feature = "gettext-extract")]
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_FILE");
fish_build_helper::rebuild_if_embedded_path_changed("share");
let build = cc::Build::new();
let mut target = Target::new_from(build).unwrap();
@@ -73,37 +69,41 @@ fn main() {
/// `Cargo.toml`) behind a feature we just enabled.
///
/// [0]: https://github.com/rust-lang/cargo/issues/5499
#[rustfmt::skip]
fn detect_cfgs(target: &mut Target) {
for (name, handler) in [
// Ignore the first entry, it just sets up the type inference. Model new entries after the
// second line.
// Ignore the first entry, it just sets up the type inference.
("", &(|_: &Target| false) as &dyn Fn(&Target) -> bool),
("apple", &detect_apple),
("bsd", &detect_bsd),
("using_cmake", &|_| option_env!("FISH_CMAKE_BINARY_DIR").is_some()),
("use_prebuilt_docs", &|_| env_var("FISH_USE_PREBUILT_DOCS").is_some_and(|v| v == "TRUE") ),
("cygwin", &detect_cygwin),
("small_main_stack", &has_small_stack),
// See if libc supports the thread-safe localeconv_l(3) alternative to localeconv(3).
("localeconv_l", &|target| {
target.has_symbol("localeconv_l")
}),
("FISH_USE_POSIX_SPAWN", &|target| {
target.has_header("spawn.h")
}),
("HAVE_PIPE2", &|target| {
target.has_symbol("pipe2")
}),
("HAVE_EVENTFD", &|target| {
("apple", &(|_| target_os_is_apple())),
("bsd", &(|_| target_os_is_bsd())),
("cygwin", &(|_| target_os_is_cygwin())),
("have_eventfd", &|target| {
// FIXME: NetBSD 10 has eventfd, but the libc crate does not expose it.
if cfg!(target_os = "netbsd") {
false
} else {
target.has_header("sys/eventfd.h")
if target_os() == "netbsd" {
false
} else {
target.has_header("sys/eventfd.h")
}
}),
("HAVE_WAITSTATUS_SIGNAL_RET", &|target| {
("have_localeconv_l", &|target| {
target.has_symbol("localeconv_l")
}),
("have_pipe2", &|target| target.has_symbol("pipe2")),
("have_posix_spawn", &|target| {
if matches!(target_os().as_str(), "openbsd" | "android") {
// OpenBSD's posix_spawn returns status 127 instead of erroring with ENOEXEC when faced with a
// shebang-less script. Disable posix_spawn on OpenBSD.
//
// Android is broken for unclear reasons
false
} else {
target.has_header("spawn.h")
}
}),
("small_main_stack", &has_small_stack),
("using_cmake", &|_| {
option_env!("FISH_CMAKE_BINARY_DIR").is_some()
}),
("waitstatus_signal_ret", &|target| {
target.r#if("WEXITSTATUS(0x007f) == 0x7f", &["sys/wait.h"])
}),
] {
@@ -111,39 +111,6 @@ fn detect_cfgs(target: &mut Target) {
}
}
fn detect_apple(_: &Target) -> bool {
cfg!(any(target_os = "ios", target_os = "macos"))
}
fn detect_cygwin(_: &Target) -> bool {
// Cygwin target is usually cross-compiled.
env_var("CARGO_CFG_TARGET_OS").unwrap() == "cygwin"
}
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
/// `#[cfg(bsd)]`.
///
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
/// doesn't necessarily include less-popular forks nor does it group them into families more
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
fn detect_bsd(_: &Target) -> bool {
// Instead of using `uname`, we can inspect the TARGET env variable set by Cargo. This lets us
// support cross-compilation scenarios.
let mut target = env_var("TARGET").unwrap();
if !target.chars().all(|c| c.is_ascii_lowercase()) {
target = target.to_ascii_lowercase();
}
let is_bsd = target.ends_with("bsd") || target.ends_with("dragonfly");
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
assert!(is_bsd, "Target incorrectly detected as not BSD!");
is_bsd
}
/// Rust sets the stack size of newly created threads to a sane value, but is at at the mercy of the
/// OS when it comes to the size of the main stack. Some platforms we support default to a tiny
/// 0.5 MiB main stack, which is insufficient for fish's MAX_EVAL_DEPTH/MAX_STACK_DEPTH values.
@@ -210,32 +177,18 @@ fn join_if_relative(parent_if_relative: &Path, path: String) -> PathBuf {
overridable_path("SYSCONFDIR", |env_sysconfdir| {
Some(join_if_relative(
&prefix,
env_sysconfdir.unwrap_or(
// Embedded builds use "/etc," not "$PREFIX/etc".
if cfg!(feature = "embed-data") {
"/etc/"
} else {
"etc/"
}
.to_string(),
),
env_sysconfdir.unwrap_or("/etc/".to_string()),
))
});
let default_ok = !cfg!(feature = "embed-data");
let datadir = overridable_path("DATADIR", |env_datadir| {
let default = default_ok.then_some("share/".to_string());
env_datadir
.or(default)
.map(|p| join_if_relative(&prefix, p))
env_datadir.map(|p| join_if_relative(&prefix, p))
});
overridable_path("BINDIR", |env_bindir| {
let default = default_ok.then_some("bin/".to_string());
env_bindir.or(default).map(|p| join_if_relative(&prefix, p))
env_bindir.map(|p| join_if_relative(&prefix, p))
});
overridable_path("DOCDIR", |env_docdir| {
let default = default_ok.then_some("doc/fish".to_string());
env_docdir.or(default).map(|p| {
env_docdir.map(|p| {
join_if_relative(
&datadir
.expect("Setting DOCDIR without setting DATADIR is not currently supported"),

View File

@@ -38,8 +38,8 @@ cargo() {
}
cleanup () {
if [ -n "$template_file" ] && [ -e "$template_file" ]; then
rm "$template_file"
if [ -n "$gettext_template_dir" ] && [ -e "$gettext_template_dir" ]; then
rm -r "$gettext_template_dir"
fi
}
@@ -64,12 +64,15 @@ if [ -n "$FISH_TEST_MAX_CONCURRENCY" ]; then
export CARGO_BUILD_JOBS="$FISH_TEST_MAX_CONCURRENCY"
fi
template_file=$(mktemp)
gettext_template_dir=$(mktemp -d)
(
export FISH_GETTEXT_EXTRACTION_FILE="$template_file"
export FISH_GETTEXT_EXTRACTION_DIR="$gettext_template_dir"
cargo build --workspace --all-targets --features=gettext-extract
)
if $lint; then
if command -v cargo-deny >/dev/null; then
cargo deny --all-features --locked --exclude-dev check licenses
fi
PATH="$build_dir:$PATH" "$workspace_root/build_tools/style.fish" --all --check
for features in "" --no-default-features; do
cargo clippy --workspace --all-targets $features
@@ -78,9 +81,9 @@ fi
cargo test --no-default-features --workspace --all-targets
cargo test --doc --workspace
if $lint; then
cargo doc --workspace
cargo doc --workspace --no-deps
fi
FISH_GETTEXT_EXTRACTION_FILE=$template_file "$workspace_root/tests/test_driver.py" "$build_dir"
FISH_GETTEXT_EXTRACTION_DIR=$gettext_template_dir "$workspace_root/tests/test_driver.py" "$build_dir"
exit
}

View File

@@ -21,13 +21,13 @@ begin
set -g workspace_root (path resolve (status dirname)/..)
set -l rust_extraction_file
set -l rust_extraction_dir
if set -l --query _flag_use_existing_template
set rust_extraction_file $_flag_use_existing_template
set rust_extraction_dir $_flag_use_existing_template
else
set rust_extraction_file (mktemp)
set rust_extraction_dir (mktemp -d)
# We need to build to ensure that the proc macro for extracting strings runs.
FISH_GETTEXT_EXTRACTION_FILE=$rust_extraction_file cargo check --no-default-features --features=gettext-extract
FISH_GETTEXT_EXTRACTION_DIR=$rust_extraction_dir cargo check --features=gettext-extract
or exit 1
end
@@ -41,11 +41,11 @@ begin
mark_section tier1-from-rust
# Get rid of duplicates and sort.
msguniq --no-wrap --sort-output $rust_extraction_file
find $rust_extraction_dir -type f -exec cat {} + | msguniq --no-wrap --sort-output
or exit 1
if not set -l --query _flag_use_existing_template
rm $rust_extraction_file
rm -r $rust_extraction_dir
end
function extract_fish_script_messages_impl

View File

@@ -25,9 +25,11 @@ NOTARIZE=
ARM64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=11.0'
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.12'
cmake_args=
while getopts "sf:i:p:e:nj:" opt; do
while getopts "c:sf:i:p:e:nj:" opt; do
case $opt in
c) cmake_args+=("$OPTARG");;
s) SIGN=1;;
f) P12_APP_FILE=$(realpath "$OPTARG");;
i) P12_INSTALL_FILE=$(realpath "$OPTARG");;
@@ -65,6 +67,7 @@ do_cmake() {
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
-DFISH_USE_SYSTEM_PCRE2=OFF \
"${cmake_args[@]}" \
"$@" \
"$SRC_DIR"
}

View File

@@ -1,88 +1,23 @@
#!/bin/sh
# Script to generate a tarball
# We use git to output a tree. But we also want to build the user documentation
# and put that in the tarball, so that nobody needs to have sphinx installed
# to build it.
# Outputs to $FISH_ARTEFACT_PATH or ~/fish_built by default
# Exit on error
set -e
# We will generate a tarball with a prefix "fish-VERSION"
# git can do that automatically for us via git-archive
# but to get the documentation in, we need to make a symlink called "fish-VERSION"
# and tar from that, so that the documentation gets the right prefix
# Use Ninja if available, as it automatically parallelises
BUILD_TOOL="make"
BUILD_GENERATOR="Unix Makefiles"
if command -v ninja >/dev/null; then
BUILD_TOOL="ninja"
BUILD_GENERATOR="Ninja"
fi
# We need GNU tar as that supports the --mtime and --transform options
TAR=notfound
for try in tar gtar gnutar; do
if $try -Pcf /dev/null --mtime now /dev/null >/dev/null 2>&1; then
TAR=$try
break
fi
done
if [ "$TAR" = "notfound" ]; then
echo 'No suitable tar (supporting --mtime) found as tar/gtar/gnutar in PATH'
exit 1
fi
# Get the current directory, which we'll use for symlinks
wd="$PWD"
# Get the version
VERSION=$(build_tools/git_version_gen.sh --stdout 2>/dev/null)
tag_creation_date=$(
# If not dirty (i.e. we're building an immutable tag), pin the build date.
if [ "$VERSION" = "$(git describe)" ]; then
git log --format=%ad '--date=format:%b %d, %Y' -1
fi
)
# The name of the prefix, which is the directory that you get when you untar
prefix="fish-$VERSION"
prefix=fish-$VERSION
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix.tar.xz
# The path where we will output the tar file
# Defaults to ~/fish_built
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix.tar
# Clean up stuff we've written before
rm -f "$path" "$path".xz
# git starts the archive
git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
# tarball out the documentation, generate a version file
PREFIX_TMPDIR=$(mktemp -d)
cd "$PREFIX_TMPDIR"
echo "$VERSION" > version
cmake -G "$BUILD_GENERATOR" -DCMAKE_BUILD_TYPE=Debug "$wd"
mkdir $PWD/user_doc/src
FISH_SPHINX_BUILD_DATE=$tag_creation_date \
FISH_SPHINX_HELP_SECTIONS_OUTPUT=$PWD/user_doc/src/help_sections.rs \
$BUILD_TOOL doc
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
--mode=g+w,a+rX --transform s/^/$prefix\//"
$TAR_APPEND --no-recursion user_doc
$TAR_APPEND user_doc/html user_doc/man user_doc/src/help_sections.rs
$TAR_APPEND version
cd -
rm -r "$PREFIX_TMPDIR"
# xz it
xz "$path"
git archive \
--prefix="$prefix/" \
--add-virtual-file="$prefix/version:$VERSION" \
HEAD |
xz >"$path"
# Output what we did, and the sha256 hash
echo "Tarball written to $path".xz
openssl dgst -sha256 "$path".xz
echo "Tarball written to $path"
openssl dgst -sha256 "$path"

View File

@@ -87,7 +87,7 @@ if test -z "$CI" || [ "$(git -C "$workspace_root" tag | wc -l)" -gt 1 ]; then {
echo 'Download links:'
echo 'To download the source code for fish, we suggest the file named ``fish-'"$version"'.tar.xz``.'
echo 'The file downloaded from ``Source code (tar.gz)`` will not build correctly.'
echo 'A GPG signature using the key published at '"${FISH_GPG_PUBLIC_KEY_URL:-???}"' is available as ``fish-'"$version"'.tar.xz.asc``.'
echo 'A GPG signature using `this key <'"${FISH_GPG_PUBLIC_KEY_URL:-???}"'>`__ is available as ``fish-'"$version"'.tar.xz.asc``.'
echo
echo 'The files called ``fish-'"$version"'-linux-*.tar.xz`` contain'
echo '`standalone fish binaries <https://github.com/fish-shell/fish-shell/?tab=readme-ov-file#building-fish-with-cargo>`__'

View File

@@ -18,15 +18,18 @@ fi
[ -n "$version" ]
for tool in \
cmake \
bundle \
diff \
gh \
gpg \
jq \
ninja \
ruby \
tar \
timeout \
uv \
xz \
; do
if ! command -v "$tool" >/dev/null; then
echo >&2 "$0: missing command: $1"
@@ -83,7 +86,20 @@ sed -i \
CommitVersion() {
sed -i "s/^version = \".*\"/version = \"$1\"/g" Cargo.toml
cargo fetch --offline
git add CHANGELOG.rst Cargo.toml Cargo.lock
# debchange is a Debian script to manage the Debian changelog, but
# it's too annoying to install everywhere. Just do it by hand.
cat - contrib/debian/changelog > contrib/debian/changelog.new <<EOF
fish (${version}-1) stable; urgency=medium
* Release of new version $version.
See https://github.com/fish-shell/fish-shell/releases/tag/$version for details.
-- $committer $(date -R)
EOF
mv contrib/debian/changelog.new contrib/debian/changelog
git add CHANGELOG.rst Cargo.toml Cargo.lock contrib/debian/changelog
git commit -m "$2
Created by ./build_tools/release.sh $version"
@@ -121,7 +137,7 @@ fish_tar_xz=fish-$version.tar.xz
(
local_tarball=$tmpdir/local-tarball
mkdir "$local_tarball"
FISH_ARTEFACT_PATH=$local_tarball uv run ./build_tools/make_tarball.sh
FISH_ARTEFACT_PATH=$local_tarball ./build_tools/make_tarball.sh
cd "$local_tarball"
tar xf "$fish_tar_xz"
)
@@ -149,9 +165,16 @@ actual_tag_oid=$(git ls-remote "$remote" |
gh release upload "$version" "$fish_tar_xz.asc"
)
(
cd "$tmpdir/local-tarball/fish-$version"
uv --no-managed-python venv
. .venv/bin/activate
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug .
ninja doc
)
CopyDocs() {
rm -rf "$fish_site/site/docs/$1"
cp -r "$tmpdir/fish-$version/user_doc/html" "$fish_site/site/docs/$1"
cp -r "$tmpdir/local-tarball/fish-$version/user_doc/html" "$fish_site/site/docs/$1"
git -C $fish_site add "site/docs/$1"
}
minor_version=${version%.*}
@@ -239,6 +262,8 @@ done
# This takes care to support remote names that are different from
# fish-shell remote name. Also, support detached HEAD state.
git push "$fish_site_repo" HEAD:master
git fetch "$fish_site_repo" \
"$(git rev-parse HEAD):refs/remotes/origin/master"
)
if [ -n "$integration_branch" ]; then {
@@ -262,17 +287,15 @@ milestone_version="$(
echo "$version"
fi
)"
milestone_number=$(
milestone_number() {
gh_api_repo milestones?state=open |
jq --arg name "fish $1" '
.[] | select(.title == $name) | .number
'
)
gh_api_repo milestones/"$milestone_number" --method PATCH \
--raw-field state=closed
}
gh_api_repo milestones/"$(milestone_number "$milestone_version")" \
--method PATCH --raw-field state=closed
next_minor_version=$(echo "$minor_version" |
awk -F. '{ printf "%s.%s", $1, $2+1 }')
if [ -z "$(milestone_number "$next_minor_version")" ]; then
gh_api_repo milestones --method POST \
--raw-field title="fish $next_minor_version"

View File

@@ -0,0 +1,22 @@
# /// script
# requires-python = ">=3.5"
# dependencies = [
# "launchpadlib",
# ]
# ///
from launchpadlib.launchpad import Launchpad
if __name__ == "__main__":
launchpad = Launchpad.login_anonymously(
"fish shell build script", "production", "~/.cache", version="devel"
)
ubu = launchpad.projects("ubuntu")
print(
"\n".join(
x["name"]
for x in ubu.series.entries
if x["supported"] == True
and x["name"] not in ("trusty", "xenial", "bionic", "focal")
)
)

View File

@@ -15,7 +15,7 @@ uv lock --check
updatecli "${@:-apply}"
uv lock # Python version constraints may have changed.
uv lock --upgrade
uv lock --upgrade --exclude-newer="$(date --date='7 days ago' --iso-8601)"
from_gh() {
repo=$1
@@ -24,7 +24,7 @@ from_gh() {
contents=$(curl -fsS https://raw.githubusercontent.com/"${repo}"/refs/heads/master/"${path}")
printf '%s\n' >"$out_dir/$(basename "$path")" "$contents"
}
from_gh ridiculousfish/widecharwidth widechar_width.rs src/widecharwidth/
from_gh ridiculousfish/widecharwidth widechar_width.rs crates/widecharwidth/src/
from_gh ridiculousfish/littlecheck littlecheck/littlecheck.py tests/
# Update Cargo.lock

View File

@@ -9,29 +9,30 @@
# For developers:
# - Run with no args to update all PO files after making changes to Rust/fish sources.
# For translators:
# - Specify the language you want to work on as an argument, which must be a file in the po/
# directory. You can specify a language which does not have translations yet by specifying the
# name of a file which does not yet exist. Make sure to follow the naming convention.
# - Specify the language you want to work on as an argument, which must be a file in the
# localization/po/ directory. You can specify a language which does not have translations
# yet by specifying the name of a file which does not yet exist.
# Make sure to follow the naming convention.
# For testing:
# - Specify `--dry-run` to see if any updates to the PO files would by applied by this script.
# If this flag is specified, the script will exit with an error if there are outstanding
# changes, and will display the diff. Do not specify other flags if `--dry-run` is specified.
#
# Specify `--use-existing-template=FILE` to prevent running cargo for extracting an up-to-date
# Specify `--use-existing-template=DIR` to prevent running cargo for extracting an up-to-date
# version of the localized strings. This flag is intended for testing setups which make it
# inconvenient to run cargo here, but run it in an earlier step to ensure up-to-date values.
# This argument is passed on to the `fish_xgettext.fish` script and has no other uses.
# `FILE` must be the path to a gettext template file generated from our compilation process.
# `DIR` must be the path to a gettext template file generated from our compilation process.
# It can be obtained by running:
# set -l FILE (mktemp)
# FISH_GETTEXT_EXTRACTION_FILE=$FILE cargo check --features=gettext-extract
# set -l DIR (mktemp -d)
# FISH_GETTEXT_EXTRACTION_DIR=$DIR cargo check --features=gettext-extract
# The sort utility is locale-sensitive.
# Ensure that sorting output is consistent by setting LC_ALL here.
set -gx LC_ALL C.UTF-8
set -l build_tools (status dirname)
set -l po_dir $build_tools/../po
set -l po_dir $build_tools/../localization/po
set -l extract
@@ -89,8 +90,9 @@ if set -l --query extract
end
if set -l --query _flag_dry_run
# On a dry run, we do not modify po/ but write to a temporary directory instead and check if
# there is a difference between po/ and the tmpdir after re-generating the PO files.
# On a dry run, we do not modify localization/po/ but write to a temporary directory instead
# and check if there is a difference between localization/po/ and the tmpdir after re-generating
# the PO files.
set -g tmpdir (mktemp -d)
# Ensure tmpdir has the same initial state as the po dir.
@@ -146,7 +148,7 @@ end
if set -g --query tmpdir[1]
diff -ur $po_dir $tmpdir
or begin
echo ERROR: translations in ./po/ are stale. Try running build_tools/update_translations.fish
echo ERROR: translations in localization/po/ are stale. Try running build_tools/update_translations.fish
cleanup_exit
end
end

View File

@@ -27,7 +27,6 @@ add_custom_target(sphinx-docs
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
COMMENT "Building HTML documentation with Sphinx")
# sphinx-manpages needs the fish_indent binary for the version number
add_custom_target(sphinx-manpages
env FISH_BUILD_VERSION_FILE=${CMAKE_CURRENT_BINARY_DIR}/${FBVF}
${SPHINX_EXECUTABLE}
@@ -36,53 +35,36 @@ add_custom_target(sphinx-manpages
-c "${SPHINX_SRC_DIR}"
-d "${SPHINX_ROOT_DIR}/.doctrees-man"
"${SPHINX_SRC_DIR}"
# TODO: This only works if we only have section 1 manpages.
"${SPHINX_MANPAGE_DIR}/man1"
DEPENDS CHECK-FISH-BUILD-VERSION-FILE
COMMENT "Building man pages with Sphinx")
if(SPHINX_EXECUTABLE)
option(BUILD_DOCS "build documentation (requires Sphinx)" ON)
else(SPHINX_EXECUTABLE)
option(BUILD_DOCS "build documentation (requires Sphinx)" OFF)
endif(SPHINX_EXECUTABLE)
if(NOT DEFINED WITH_DOCS) # Don't check for legacy options if the new one is defined, to help bisecting.
if(DEFINED BUILD_DOCS)
message(FATAL_ERROR "the BUILD_DOCS option is no longer supported, use -DWITH_DOCS=ON|OFF")
endif()
if(DEFINED INSTALL_DOCS)
message(FATAL_ERROR "the INSTALL_DOCS option is no longer supported, use -DWITH_DOCS=ON|OFF")
endif()
endif()
if(BUILD_DOCS AND NOT SPHINX_EXECUTABLE)
if(SPHINX_EXECUTABLE)
option(WITH_DOCS "build documentation (requires Sphinx)" ON)
else()
option(WITH_DOCS "build documentation (requires Sphinx)" OFF)
endif()
if(WITH_DOCS AND NOT SPHINX_EXECUTABLE)
message(FATAL_ERROR "build documentation selected, but sphinx-build could not be found")
endif()
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/html
AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/man)
set(HAVE_PREBUILT_DOCS TRUE)
else()
set(HAVE_PREBUILT_DOCS FALSE)
endif()
add_feature_info(Documentation WITH_DOCS "user manual and documentation")
if(BUILD_DOCS OR HAVE_PREBUILT_DOCS)
set(INSTALL_DOCS ON)
else()
set(INSTALL_DOCS OFF)
endif()
add_feature_info(Documentation INSTALL_DOCS "user manual and documentation")
set(USE_PREBUILT_DOCS FALSE)
if(BUILD_DOCS)
if(WITH_DOCS)
configure_file("${SPHINX_SRC_DIR}/conf.py" "${SPHINX_BUILD_DIR}/conf.py" @ONLY)
add_custom_target(doc ALL
DEPENDS sphinx-docs sphinx-manpages)
# Group docs targets into a DocsTargets folder
set_property(TARGET doc sphinx-docs sphinx-manpages
PROPERTY FOLDER cmake/DocTargets)
elseif(HAVE_PREBUILT_DOCS)
set(USE_PREBUILT_DOCS TRUE)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
# Out of tree build - link the prebuilt documentation to the build tree
add_custom_target(link_doc ALL)
add_custom_command(TARGET link_doc
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/user_doc ${CMAKE_CURRENT_BINARY_DIR}/user_doc
POST_BUILD)
endif()
endif(BUILD_DOCS)
endif()

View File

@@ -1,7 +1,5 @@
set(CMAKE_INSTALL_MESSAGE NEVER)
set(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fish ${CMAKE_CURRENT_BINARY_DIR}/fish_indent ${CMAKE_CURRENT_BINARY_DIR}/fish_key_reader)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(bindir ${CMAKE_INSTALL_BINDIR})
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
@@ -75,22 +73,30 @@ function(FISH_TRY_CREATE_DIRS)
endforeach()
endfunction(FISH_TRY_CREATE_DIRS)
install(PROGRAMS ${PROGRAMS}
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fish
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${bindir})
if(NOT IS_ABSOLUTE ${bindir})
set(abs_bindir "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${bindir}")
else()
set(abs_bindir "\$ENV{DESTDIR}${bindir}")
endif()
install(CODE "file(CREATE_LINK ${abs_bindir}/fish ${abs_bindir}/fish_indent)")
install(CODE "file(CREATE_LINK ${abs_bindir}/fish ${abs_bindir}/fish_key_reader)")
fish_create_dirs(${sysconfdir}/fish/conf.d ${sysconfdir}/fish/completions
${sysconfdir}/fish/functions)
install(FILES etc/config.fish DESTINATION ${sysconfdir}/fish/)
fish_create_dirs(${rel_datadir}/fish ${rel_datadir}/fish/completions
${rel_datadir}/fish/functions ${rel_datadir}/fish/groff
${rel_datadir}/fish/functions
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
${rel_datadir}/fish/tools/web_config
${rel_datadir}/fish/tools/web_config/js
${rel_datadir}/fish/tools/web_config/sample_prompts
${rel_datadir}/fish/tools/web_config/themes
${rel_datadir}/fish/prompts
${rel_datadir}/fish/themes
)
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
@@ -125,9 +131,6 @@ install(DIRECTORY share/functions/
DESTINATION ${rel_datadir}/fish/functions
FILES_MATCHING PATTERN "*.fish")
install(DIRECTORY share/groff
DESTINATION ${rel_datadir}/fish)
# CONDEMNED_PAGE is managed by the conditional above
# Building the man pages is optional: if sphinx isn't installed, they're not built
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/

View File

@@ -3,8 +3,6 @@ find_package(Rust REQUIRED)
set(FISH_RUST_BUILD_DIR "${CMAKE_BINARY_DIR}/cargo/build")
list(APPEND FISH_CARGO_FEATURES_LIST "embed-data")
if(DEFINED ASAN)
list(APPEND CARGO_FLAGS "-Z" "build-std")
list(APPEND FISH_CARGO_FEATURES_LIST "asan")
@@ -21,7 +19,6 @@ else()
endif()
set(rust_profile $<IF:$<CONFIG:Debug>,debug,$<IF:$<CONFIG:RelWithDebInfo>,release-with-debug,release>>)
set(rust_debugflags "$<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g>")
option(WITH_GETTEXT "Build with gettext localization support. Requires `msgfmt` to work." ON)
# Enable gettext feature unless explicitly disabled.

View File

@@ -57,7 +57,15 @@ endif()
add_custom_target(fish_run_tests
# TODO: This should be replaced with a unified solution, possibly build_tools/check.sh.
COMMAND ${CMAKE_SOURCE_DIR}/tests/test_driver.py ${max_concurrency_flag} ${CMAKE_CURRENT_BINARY_DIR}
COMMAND env ${VARS_FOR_CARGO} ${Rust_CARGO} test --no-default-features ${CARGO_FLAGS} --workspace --target-dir ${rust_target_dir} ${cargo_test_flags}
COMMAND env ${VARS_FOR_CARGO}
${Rust_CARGO}
test
--no-default-features
--features=${FISH_CARGO_FEATURES}
${CARGO_FLAGS}
--workspace
--target-dir ${rust_target_dir}
${cargo_test_flags}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
DEPENDS fish fish_indent fish_key_reader fish_test_helper
USES_TERMINAL

464
contrib/debian/changelog Normal file
View File

@@ -0,0 +1,464 @@
fish (4.3.0-1) stable; urgency=medium
* Release of new version 4.3.0.
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.0 for details.
-- Johannes Altmanninger <aclopte@gmail.com> Sun, 28 Dec 2025 10:20:47 +0100
fish (4.2.1-1) testing; urgency=medium
* Release of new version 4.2.1.
See https://github.com/fish-shell/fish-shell/releases/tag/4.2.1 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 13 Nov 2025 20:42:43 +0800
fish (4.2.0-1) testing; urgency=medium
* Release of new version 4.2.0.
See https://github.com/fish-shell/fish-shell/releases/tag/4.2.0 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 10 Nov 2025 19:29:03 +0800
fish (4.1.2-1) testing; urgency=medium
* Release of new version 4.1.2.
See https://github.com/fish-shell/fish-shell/releases/tag/4.1.2 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 08 Oct 2025 13:46:45 +0800
fish (4.1.1-1) testing; urgency=medium
* Release of new version 4.1.1.
See https://github.com/fish-shell/fish-shell/releases/tag/4.1.1 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 03 Oct 2025 16:43:43 +0800
fish (4.0.8-1) testing; urgency=medium
* Release of new version 4.0.8.
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.8 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 18 Sep 2025 22:17:43 +0800
fish (4.0.6-1) testing; urgency=medium
* Release of new version 4.0.6.
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.6 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 17 Sep 2025 12:27:09 +0800
fish (4.0.2-2) testing; urgency=medium
* Fix tests on Debian.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 20 Apr 2025 23:08:14 +0800
fish (4.0.2-1) testing; urgency=medium
* Release of new version 4.0.2.
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.2 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 20 Apr 2025 21:24:18 +0800
fish (4.0.1-1) testing; urgency=medium
* Release of new version 4.0.1.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 13 Mar 2025 11:30:21 +0800
fish (4.0.0-2) testing; urgency=medium
* Fix tests on Debian.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 27 Feb 2025 21:50:33 +0800
fish (4.0.0-1) testing; urgency=medium
* Release of new version 4.0.0.
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.0 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 27 Feb 2025 19:22:30 +0800
fish (4.0.1-1) testing; urgency=medium
* Release of new beta version 4.0b1.
See https://github.com/fish-shell/fish-shell/releases/tag/4.0b1 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 17 Dec 2024 23:42:25 +0800
fish (3.7.1-1) testing; urgency=medium
* Release of new version 3.7.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.7.1 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Mar 2024 13:26:22 +0800
fish (3.7.0-1) testing; urgency=medium
* Release of new version 3.7.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.7.0 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 01 Jan 2024 23:32:55 +0800
fish (3.6.4-1) testing; urgency=medium
* Release of new version 3.6.4.
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.4 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 05 Dec 2023 22:34:09 +0800
fish (3.6.3-1) testing; urgency=medium
* Release of new version 3.6.3.
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.3 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 05 Dec 2023 00:11:12 +0800
fish (3.6.2-1) testing; urgency=medium
* Release of new version 3.6.2.
* Includes a fix for CVE-2023-49284.
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.2 for details.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 04 Dec 2023 23:16:42 +0800
fish (3.6.1-1) testing; urgency=medium
* Release of new version 3.6.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 25 Mar 2023 17:22:12 +0800
fish (3.6.0-1) testing; urgency=medium
* Release of new version 3.6.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 07 Jan 2023 22:41:32 +0800
fish (3.5.1-1) testing; urgency=medium
* Release of new version 3.5.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.5.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 20 Jul 2022 21:54:09 +0800
fish (3.5.0-1) testing; urgency=medium
* Release of new version 3.5.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.5.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 16 Jun 2022 19:45:33 +0800
fish (3.4.0-1) testing; urgency=medium
* Release of new version 3.4.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.4.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 12 Mar 2022 23:24:22 +0800
fish (3.3.1-1) testing; urgency=medium
* Release of new version 3.3.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.3.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 06 Jul 2021 23:22:36 +0800
fish (3.3.0-1) testing; urgency=medium
* Release of new version 3.3.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.3.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 28 Jun 2021 23:06:36 +0800
fish (3.2.2-1) testing; urgency=medium
* Release of new version 3.2.2.
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.2 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 07 Apr 2021 21:10:54 +0800
fish (3.2.1-1) testing; urgency=medium
* Release of new version 3.2.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 18 Mar 2021 12:08:13 +0800
fish (3.2.0-1) testing; urgency=medium
* Release of new version 3.2.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 01 Mar 2021 21:22:39 +0800
fish (3.1.2-1) testing; urgency=medium
* Release of new version 3.1.2.
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.2 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 29 Apr 2020 11:22:35 +0800
fish (3.1.1-1) testing; urgency=medium
* Release of new version 3.1.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 27 Apr 2020 22:45:35 +0800
fish (3.1.0-1) testing; urgency=medium
* Release of new version 3.1.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 12 Feb 2020 22:34:53 +0800
fish (3.1.1-1) testing; urgency=medium
* Release of new beta version 3.1b1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.1b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 26 Jan 2020 21:42:46 +0800
fish (3.0.2-1) testing; urgency=medium
* Release of new version 3.0.2.
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.2 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Feb 2019 21:45:05 +0800
fish (3.0.1-1) testing; urgency=medium
* Release of new version 3.0.1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 11 Feb 2019 20:23:55 +0800
fish (3.0.0-1) testing; urgency=medium
* Release of new version 3.0.0.
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 28 Dec 2018 21:10:28 +0800
fish (3.0.1-1) testing; urgency=medium
* Release of new beta version 3.0b1.
See https://github.com/fish-shell/fish-shell/releases/tag/3.0b1 for
significant changes, which includes backward incompatibility.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 11 Dec 2018 22:59:15 +0800
fish (2.7.1-1) testing; urgency=medium
* Release of new bug fix version 2.7.1. On all Linux platforms, this is
release will behave identically to 2.7.0.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 23 Dec 2017 00:43:12 +0800
fish (2.7.0-1) testing; urgency=medium
* Release of new version 2.7.0.
See https://github.com/fish-shell/fish-shell/releases/tag/2.7.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 23 Nov 2017 18:38:21 +0800
fish (2.7.1-1) testing; urgency=medium
* Release of new beta version 2.7b1.
See https://github.com/fish-shell/fish-shell/releases/tag/2.7b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 31 Oct 2017 20:32:29 +0800
fish (2.6.0-1) testing; urgency=medium
* Relase of new version 2.6.0.
See https://github.com/fish-shell/fish-shell/releases/tag/2.6.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 03 Jun 2017 20:51:50 +0800
fish (2.6b1-1) testing; urgency=medium
* Release of new beta version 2.6b1.
See https://github.com/fish-shell/fish-shell/releases/tag/2.6b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 14 May 2017 10:47:39 +0800
fish (2.5.0-1) testing; urgency=medium
* Release of new version 2.5.0.
See https://github.com/fish-shell/fish-shell/releases/tag/2.5.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 03 Feb 2017 09:52:57 +0800
fish (2.5b1-1) testing; urgency=medium
* Release of new beta version 2.5b1.
See https://github.com/fish-shell/fish-shell/releases/tag/2.5b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 14 Jan 2017 08:49:34 +0800
fish (2.4.0-2) testing; urgency=medium
* Change recommendation of xdg-utils to suggestion (closes
https://github.com/fish-shell/fish-shell/issues/3534).
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 09 Nov 2016 22:56:16 +0800
fish (2.4.0-1) testing; urgency=medium
* Release of new version 2.4.0.
See https://github.com/fish-shell/fish-shell/releases/tag/2.4.0 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 08 Nov 2016 11:29:57 +0800
fish (2.4b1-1) testing; urgency=medium
* Release of new beta version 2.4b1.
See https://github.com/fish-shell/fish-shell/releases/tag/2.4b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 18 Oct 2016 22:25:26 +0800
fish (2.3.1-1) testing; urgency=medium
* Release of new version 2.3.1.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 03 Jul 2016 21:21:51 +0800
fish (2.3.0-1) testing; urgency=medium
* Release of new version 2.3.0.
See http://fishshell.com/release_notes.html for significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 21 May 2016 06:59:54 +0800
fish (2.3b2-1) testing; urgency=medium
* Release of new beta version 2.3b2.
See https://github.com/fish-shell/fish-shell/releases/tag/2.3b2 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 05 May 2016 06:22:37 +0800
fish (2.3.1-1) testing; urgency=medium
* Release of new beta version 2.3b1.
See http://github.com/fish-shell/fish-shell/releases/tag/2.3b1 for
significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Apr 2016 21:07:17 +0800
fish (2.2.0-2) testing; urgency=medium
* Binary rebuild only to resynchronise repository state.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 15 Feb 2016 22:45:05 +0800
fish (2.2.0-1) testing; urgency=medium
* Release of new version 2.2.0.
See http://fishshell.com/release_notes.html for significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 12 Jul 2015 18:52:29 +0800
fish (2.2b1-1) testing; urgency=low
* Release of new beta version 2.2b1.
See http://fishshell.com/staging/release_notes.html for significant
changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 07 May 2015 14:48:21 +0800
fish (2.1.1-1) unstable; urgency=high
* Release of new version 2.1.1.
See http://fishshell.com/release_notes.html for significant changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 07 Sep 2014 17:06:31 +0800
fish (2.1.0-1) unstable; urgency=low
* Release of new version 2.1.0.
See http://fishshell.com/staging/release_notes.html for significant
changes.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 19 Oct 2013 14:35:23 +0800
fish (2.0.0-0) unstable; urgency=low
* Initial release of fish 2.0.0.
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 19 Jul 2012 23:17:58 +0800

View File

@@ -3,33 +3,31 @@ Section: shells
Priority: optional
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
Build-Depends: debhelper (>= 12),
Build-Depends: debhelper-compat (= 13),
# -web is for Debian's updated version, -X.Y is for Ubuntu's backported versions
cargo (>= 1.85) | cargo-web (>= 1.85) | cargo-1.85,
cmake (>= 3.15.0),
gettext,
libpcre2-dev,
rustc (>= 1.85) | rustc-web (>= 1.85) | rustc-1.85,
sphinx-doc,
# Test dependencies
locales-all,
ncurses-base,
man-db,
python3
Standards-Version: 4.1.5
# 4.6.2 is Debian 12/Ubuntu Noble 24.04; Ubuntu Jammy is 4.6.0.1
Standards-Version: 4.6.2
Homepage: https://fishshell.com/
Vcs-Git: https://github.com/fish-shell/fish-shell.git
Vcs-Browser: https://github.com/fish-shell/fish-shell
Package: fish
Architecture: any
# for col and lock - bsdmainutils is required in Ubuntu focal
Depends: bsdextrautils | bsdmainutils,
# for col and lock
Depends: bsdextrautils,
file,
# for the msgfmt command
gettext-base,
# for man
man-db,
# for terminal definitions
ncurses-base,
# for kill
procps,
python3 (>=3.5),

View File

@@ -17,11 +17,11 @@ Files: share/tools/web_config/js/alpine.js
Copyright: 2019-2021 Caleb Porzio and contributors
License: MIT
Files: share/tools/web_config/themes/Dracula.theme
Files: share/themes/Dracula.theme
Copyright: 2018 Dracula Team
License: MIT
Files: share/tools/web_config/themes/Nord.theme
Files: share/themes/Nord.theme
Copyright: 2016-2024 Sven Greb
License: MIT

View File

@@ -1,8 +1,11 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
ifeq (,$(filter terse,$(DEB_BUILD_OPTIONS)))
export DH_VERBOSE=1
# VERBOSE to satisfy Debian policy 4.9, introduced in version 4.2.0
export CARGO_TERM_VERBOSE=true
endif
# The LTO profile sets CFLAGS/CXXFLAGS which confuse the compilation process; disable it
# LTO is still performed by rustc based on Cargo.toml
export DEB_BUILD_MAINT_OPTIONS=optimize=-lto

View File

@@ -4,6 +4,7 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
rsconf.workspace = true

View File

@@ -45,3 +45,41 @@ pub fn rebuild_if_paths_changed<P: AsRef<Path>, I: IntoIterator<Item = P>>(paths
rsconf::rebuild_if_path_changed(path.as_ref().to_str().unwrap());
}
}
pub fn rebuild_if_embedded_path_changed<P: AsRef<Path>>(path: P) {
// Not necessary in debug builds, where rust-embed reads from the filesystem.
if cfg!(any(not(debug_assertions), windows)) {
rebuild_if_path_changed(path);
}
}
// Target OS for compiling our crates, as opposed to the build script.
pub fn target_os() -> String {
env_var("CARGO_CFG_TARGET_OS").unwrap()
}
pub fn target_os_is_apple() -> bool {
matches!(target_os().as_str(), "ios" | "macos")
}
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
/// `#[cfg(bsd)]`.
///
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
/// doesn't necessarily include less-popular forks nor does it group them into families more
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
pub fn target_os_is_bsd() -> bool {
let target_os = target_os();
let is_bsd = target_os.ends_with("bsd") || target_os == "dragonfly";
if matches!(
target_os.as_str(),
"dragonfly" | "freebsd" | "netbsd" | "openbsd"
) {
assert!(is_bsd, "Target incorrectly detected as not BSD!");
}
is_bsd
}
pub fn target_os_is_cygwin() -> bool {
target_os() == "cygwin"
}

View File

@@ -4,6 +4,7 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[build-dependencies]
fish-build-helper.workspace = true

View File

@@ -1,36 +1,18 @@
use fish_build_helper::{env_var, workspace_root};
use std::path::Path;
fn main() {
let man_dir = fish_build_helper::fish_build_dir().join("fish-man");
let sec1_dir = man_dir.join("man1");
// Running `cargo clippy` on a clean build directory panics, because when rust-embed tries to
// embed a directory which does not exist it will panic.
// Running `cargo clippy` on a clean build directory panics, because when rust-embed
// tries to embed a directory which does not exist it will panic.
let _ = std::fs::create_dir_all(&sec1_dir);
let help_sections_path = Path::new(&env_var("OUT_DIR").unwrap()).join("help_sections.rs");
if env_var("FISH_USE_PREBUILT_DOCS").is_some_and(|v| v == "TRUE") {
std::fs::copy(
workspace_root().join("user_doc/src/help_sections.rs"),
help_sections_path,
)
.unwrap();
return;
if !cfg!(clippy) {
build_man(&man_dir, &sec1_dir);
}
std::fs::write(
help_sections_path.clone(),
r#"pub static HELP_SECTIONS: &str = "";"#,
)
.unwrap();
#[cfg(not(clippy))]
build_man(&man_dir, &sec1_dir, &help_sections_path);
}
#[cfg(not(clippy))]
fn build_man(man_dir: &Path, sec1_dir: &Path, help_sections_path: &Path) {
fn build_man(man_dir: &Path, sec1_dir: &Path) {
use fish_build_helper::{env_var, workspace_root};
use std::{
ffi::OsStr,
process::{Command, Stdio},
@@ -45,7 +27,6 @@ fn build_man(man_dir: &Path, sec1_dir: &Path, help_sections_path: &Path) {
&doc_src_dir,
]);
let help_sections_arg = format!("fish_help_sections_output={}", help_sections_path.display());
let args: &[&OsStr] = {
fn as_os_str<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
s.as_ref()
@@ -71,8 +52,6 @@ macro_rules! as_os_strs {
&man_dir,
&doc_src_dir,
&sec1_dir,
"-D",
&help_sections_arg,
])
};

View File

@@ -1 +1 @@
include!(concat!(env!("OUT_DIR"), "/help_sections.rs"));

15
crates/common/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "fish-common"
edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
libc.workspace = true
nix.workspace = true
once_cell.workspace = true
[lints]
workspace = true

60
crates/common/src/lib.rs Normal file
View File

@@ -0,0 +1,60 @@
use libc::STDIN_FILENO;
use once_cell::sync::OnceCell;
use std::env;
use std::os::unix::ffi::OsStrExt;
// These are in the Unicode private-use range. We really shouldn't use this
// range but have little choice in the matter given how our lexer/parser works.
// We can't use non-characters for these two ranges because there are only 66 of
// them and we need at least 256 + 64.
//
// If sizeof(wchar_t))==4 we could avoid using private-use chars; however, that
// would result in fish having different behavior on machines with 16 versus 32
// bit wchar_t. It's better that fish behave the same on both types of systems.
//
// Note: We don't use the highest 8 bit range (0xF800 - 0xF8FF) because we know
// of at least one use of a codepoint in that range: the Apple symbol (0xF8FF)
// on Mac OS X. See http://www.unicode.org/faq/private_use.html.
pub const ENCODE_DIRECT_BASE: char = '\u{F600}';
pub const ENCODE_DIRECT_END: char = char_offset(ENCODE_DIRECT_BASE, 256);
pub const fn char_offset(base: char, offset: u32) -> char {
match char::from_u32(base as u32 + offset) {
Some(c) => c,
None => panic!("not a valid char"),
}
}
pub fn subslice_position<T: Eq>(a: &[T], b: &[T]) -> Option<usize> {
if b.is_empty() {
return Some(0);
}
a.windows(b.len()).position(|aw| aw == b)
}
/// This function attempts to distinguish between a console session (at the actual login vty) and a
/// session within a terminal emulator inside a desktop environment or over SSH. Unfortunately
/// there are few values of $TERM that we can interpret as being exclusively console sessions, and
/// most common operating systems do not use them. The value is cached for the duration of the fish
/// session. We err on the side of assuming it's not a console session. This approach isn't
/// bullet-proof and that's OK.
pub fn is_console_session() -> bool {
static IS_CONSOLE_SESSION: OnceCell<bool> = OnceCell::new();
// TODO(terminal-workaround)
*IS_CONSOLE_SESSION.get_or_init(|| {
nix::unistd::ttyname(unsafe { std::os::fd::BorrowedFd::borrow_raw(STDIN_FILENO) })
.is_ok_and(|buf| {
// Check if the tty matches /dev/(console|dcons|tty[uv\d])
let is_console_tty = match buf.as_os_str().as_bytes() {
b"/dev/console" => true,
b"/dev/dcons" => true,
bytes => bytes.strip_prefix(b"/dev/tty").is_some_and(|rest| {
matches!(rest.first(), Some(b'u' | b'v' | b'0'..=b'9'))
}),
};
// and that $TERM is simple, e.g. `xterm` or `vt100`, not `xterm-something` or `sun-color`.
is_console_tty && env::var_os("TERM").is_none_or(|t| !t.as_bytes().contains(&b'-'))
})
})
}

View File

@@ -0,0 +1,22 @@
[package]
name = "fish-fallback"
edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
fish-common.workspace = true
fish-wchar.workspace = true
fish-widecharwidth.workspace = true
libc.workspace = true
once_cell.workspace = true
widestring.workspace = true
[build-dependencies]
fish-build-helper.workspace = true
rsconf.workspace = true
[lints]
workspace = true

5
crates/fallback/build.rs Normal file
View File

@@ -0,0 +1,5 @@
use fish_build_helper::target_os_is_cygwin;
fn main() {
rsconf::declare_cfg("cygwin", target_os_is_cygwin())
}

View File

@@ -3,8 +3,8 @@
//!
//! Many of these functions are more or less broken and incomplete.
use crate::wchar::prelude::*;
use crate::widecharwidth::{WcLookupTable, WcWidth};
use fish_wchar::prelude::*;
use fish_widecharwidth::{WcLookupTable, WcWidth};
use once_cell::sync::Lazy;
use std::cmp;
use std::sync::atomic::{AtomicIsize, Ordering};
@@ -46,7 +46,7 @@ pub fn fish_wcwidth(c: char) -> isize {
// in the console session, but knows nothing about the capabilities of other terminal emulators
// or ttys. Use it from the start only if we are logged in to the physical console.
#[cfg(not(cygwin))]
if crate::common::is_console_session() {
if fish_common::is_console_session() {
return wcwidth(c);
}
@@ -116,21 +116,36 @@ pub fn wcscasecmp(lhs: &wstr, rhs: &wstr) -> cmp::Ordering {
}
/// Compare two wide strings in a case-insensitive fashion
pub fn wcscasecmp_fuzzy(lhs: &wstr, rhs: &wstr, canonicalize: fn(char) -> char) -> cmp::Ordering {
use std::char::ToLowercase;
use widestring::utfstr::CharsUtf32;
pub fn wcscasecmp_fuzzy(
lhs: &wstr,
rhs: &wstr,
extra_canonicalization: fn(char) -> char,
) -> cmp::Ordering {
lowercase(lhs.chars())
.map(extra_canonicalization)
.cmp(lowercase(rhs.chars()).map(extra_canonicalization))
}
/// This struct streams the underlying lowercase chars of a `UTF32String` without allocating.
///
/// `char::to_lowercase()` returns an iterator of chars and we sometimes need to cmp the last
/// char of one char's `to_lowercase()` with the first char of the other char's
/// `to_lowercase()`. This makes that possible.
struct ToLowerBuffer<'a, Canonicalize: Fn(char) -> char> {
pub fn lowercase(chars: impl Iterator<Item = char>) -> impl Iterator<Item = char> {
lowercase_impl(chars, |c| c.to_lowercase())
}
pub fn lowercase_rev(chars: impl DoubleEndedIterator<Item = char>) -> impl Iterator<Item = char> {
lowercase_impl(chars.rev(), |c| c.to_lowercase().rev())
}
fn lowercase_impl<ToLowercase: Iterator<Item = char>>(
chars: impl Iterator<Item = char>,
to_lowercase: fn(char) -> ToLowercase,
) -> impl Iterator<Item = char> {
/// This struct streams the underlying lowercase chars of a string without allocating.
struct ToLowerBuffer<Chars: Iterator<Item = char>, ToLowercase: Iterator<Item = char>> {
to_lowercase: fn(char) -> ToLowercase,
current: ToLowercase,
chars: std::iter::Map<CharsUtf32<'a>, Canonicalize>,
chars: Chars,
}
impl<'a, Canonicalize: Fn(char) -> char> Iterator for ToLowerBuffer<'a, Canonicalize> {
impl<Chars: Iterator<Item = char>, ToLowercase: Iterator<Item = char>> Iterator
for ToLowerBuffer<Chars, ToLowercase>
{
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
@@ -138,34 +153,37 @@ fn next(&mut self) -> Option<Self::Item> {
return Some(c);
}
self.current = self.chars.next()?.to_lowercase();
self.current = (self.to_lowercase)(self.chars.next()?);
self.current.next()
}
}
impl<'a, Canonicalize: Fn(char) -> char> ToLowerBuffer<'a, Canonicalize> {
pub fn new(mut chars: std::iter::Map<CharsUtf32<'a>, Canonicalize>) -> Self {
impl<Chars: Iterator<Item = char>, ToLowercase: Iterator<Item = char>>
ToLowerBuffer<Chars, ToLowercase>
{
pub fn new(mut chars: Chars, to_lowercase: fn(char) -> ToLowercase) -> Self {
Self {
current: chars.next().map(|c| c.to_lowercase()).unwrap_or_else(|| {
let mut empty = 'a'.to_lowercase();
let _ = empty.next();
debug_assert!(empty.next().is_none());
empty
}),
to_lowercase,
current: chars.next().map_or_else(
|| {
let mut empty = to_lowercase('a');
let _ = empty.next();
debug_assert!(empty.next().is_none());
empty
},
to_lowercase,
),
chars,
}
}
}
let lhs = ToLowerBuffer::new(lhs.chars().map(canonicalize));
let rhs = ToLowerBuffer::new(rhs.chars().map(canonicalize));
lhs.cmp(rhs)
ToLowerBuffer::new(chars, to_lowercase)
}
#[cfg(test)]
mod tests {
use super::wcscasecmp;
use crate::wchar::prelude::*;
use fish_wchar::prelude::*;
use std::cmp::Ordering;
#[test]

View File

@@ -4,13 +4,18 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
description = "proc-macro for extracting strings for gettext translation"
[lib]
proc-macro = true
[dependencies]
fish-tempfile.workspace = true
proc-macro2.workspace = true
[build-dependencies]
rsconf.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,3 @@
fn main() {
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_DIR");
}

View File

@@ -1,6 +1,7 @@
extern crate proc_macro;
use fish_tempfile::random_filename;
use proc_macro::TokenStream;
use std::{ffi::OsString, fs::OpenOptions, io::Write};
use std::{ffi::OsString, io::Write, path::PathBuf};
fn unescape_multiline_rust_string(s: String) -> String {
if !s.contains('\n') {
@@ -42,12 +43,9 @@ enum State {
unescaped
}
fn append_po_entry_to_file(message: &TokenStream, file_name: &OsString) {
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open(file_name)
.unwrap_or_else(|e| panic!("Could not open file {file_name:?}: {e}"));
// Each entry is written to a fresh file to avoid race conditions arising when there are multiple
// unsynchronized writers to the same file.
fn write_po_entry_to_file(message: &TokenStream, dir: &OsString) {
let message_string = unescape_multiline_rust_string(message.to_string());
if message_string.contains('\n') {
panic!(
@@ -61,25 +59,32 @@ fn append_po_entry_to_file(message: &TokenStream, file_name: &OsString) {
""
};
let po_entry = format!("{format_string_annotation}msgid {message_string}\nmsgstr \"\"\n\n");
let dir = PathBuf::from(dir);
let (path, result) =
fish_tempfile::create_file_with_retry(|| dir.join(random_filename(OsString::new())));
let mut file = result.unwrap_or_else(|e| {
panic!("Failed to create temporary file {path:?}:\n{e}");
});
file.write_all(po_entry.as_bytes()).unwrap();
}
/// The `message` is passed through unmodified.
/// If `FISH_GETTEXT_EXTRACTION_FILE` is defined in the environment,
/// this file is used to write the message,
/// If `FISH_GETTEXT_EXTRACTION_DIR` is defined in the environment,
/// the message ID is written into a new file in this directory,
/// so that it can then be used for generating gettext PO files.
/// The `message` must be a string literal.
///
/// # Panics
///
/// This macro panics if the `FISH_GETTEXT_EXTRACTION_FILE` variable is set and `message` has an
/// This macro panics if the `FISH_GETTEXT_EXTRACTION_DIR` variable is set and `message` has an
/// unexpected format.
/// Note that for example `concat!(...)` cannot be passed to this macro, because expansion works
/// outside in, meaning this macro would still see the `concat!` macro invocation, instead of a
/// string literal.
#[proc_macro]
pub fn gettext_extract(message: TokenStream) -> TokenStream {
if let Some(file_path) = std::env::var_os("FISH_GETTEXT_EXTRACTION_FILE") {
if let Some(dir_path) = std::env::var_os("FISH_GETTEXT_EXTRACTION_DIR") {
let pm2_message = proc_macro2::TokenStream::from(message.clone());
let mut token_trees = pm2_message.into_iter();
let first_token = token_trees
@@ -103,7 +108,7 @@ pub fn gettext_extract(message: TokenStream) -> TokenStream {
)
}
if let proc_macro2::TokenTree::Literal(_) = first_group_token {
append_po_entry_to_file(&message, &file_path);
write_po_entry_to_file(&message, &dir_path);
} else {
panic!("Expected literal in gettext_extract, but got: {first_group_token:?}");
}

View File

@@ -4,6 +4,7 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
phf.workspace = true

View File

@@ -11,7 +11,11 @@ fn main() {
PathBuf::from(fish_build_helper::fish_build_dir()).join("fish-localization-map-cache");
embed_localizations(&cache_dir);
fish_build_helper::rebuild_if_path_changed(fish_build_helper::workspace_root().join("po"));
fish_build_helper::rebuild_if_path_changed(
fish_build_helper::workspace_root()
.join("localization")
.join("po"),
);
}
fn embed_localizations(cache_dir: &Path) {
@@ -21,7 +25,9 @@ fn embed_localizations(cache_dir: &Path) {
io::{BufWriter, Write},
};
let po_dir = fish_build_helper::workspace_root().join("po");
let po_dir = fish_build_helper::workspace_root()
.join("localization")
.join("po");
// Ensure that the directory is created, because clippy cannot compile the code if the
// directory does not exist.
@@ -41,7 +47,7 @@ fn embed_localizations(cache_dir: &Path) {
"Could not find msgfmt required to build message catalogs. \
Localization will not work. \
If you install gettext now, you need to trigger a rebuild to include localization support. \
For example by running `touch po` followed by the build command."
For example by running `touch localization/po` followed by the build command."
);
}
Err(e) => {

View File

@@ -4,6 +4,7 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[lints]
workspace = true

15
crates/gettext/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "fish-gettext"
edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
fish-gettext-maps.workspace = true
once_cell.workspace = true
phf.workspace = true
[lints]
workspace = true

268
crates/gettext/src/lib.rs Normal file
View File

@@ -0,0 +1,268 @@
use fish_gettext_maps::CATALOGS;
use once_cell::sync::Lazy;
use std::{collections::HashSet, sync::Mutex};
type Catalog = &'static phf::Map<&'static str, &'static str>;
pub struct SetLanguageLints<'a> {
pub duplicates: Vec<&'a str>,
pub non_existing: Vec<&'a str>,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum LanguagePrecedenceOrigin {
Default,
LocaleVariable(LocaleVariable),
LanguageEnvVar,
StatusLanguage,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum LocaleVariable {
#[allow(clippy::upper_case_acronyms)]
LANG,
#[allow(non_camel_case_types)]
LC_MESSAGES,
#[allow(non_camel_case_types)]
LC_ALL,
}
impl LocaleVariable {
fn as_language_precedence_origin(&self) -> LanguagePrecedenceOrigin {
LanguagePrecedenceOrigin::LocaleVariable(*self)
}
pub fn as_str(&self) -> &'static str {
match self {
Self::LANG => "LANG",
Self::LC_MESSAGES => "LC_MESSAGES",
Self::LC_ALL => "LC_ALL",
}
}
}
impl std::fmt::Display for LocaleVariable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
struct InternalLocalizationState {
precedence_origin: LanguagePrecedenceOrigin,
language_precedence: Vec<(String, Catalog)>,
}
pub struct PublicLocalizationState {
pub precedence_origin: LanguagePrecedenceOrigin,
pub language_precedence: Vec<String>,
}
/// Stores the current localization status.
/// `is_active` indicates whether localization is currently active, and the reason if it is
/// not.
/// The `origin` indicates where the values in `language_precedence` were taken from.
/// `language_precedence` stores the catalogs in the order they should be used.
///
/// This struct should be updated when the relevant variables change or `status language` is used
/// to modify the localization state.
static LOCALIZATION_STATE: Lazy<Mutex<InternalLocalizationState>> =
Lazy::new(|| Mutex::new(InternalLocalizationState::new()));
impl InternalLocalizationState {
fn new() -> Self {
Self {
precedence_origin: LanguagePrecedenceOrigin::Default,
language_precedence: vec![],
}
}
fn to_public(&self) -> PublicLocalizationState {
PublicLocalizationState {
precedence_origin: self.precedence_origin,
language_precedence: self
.language_precedence
.iter()
.map(|(lang, _)| lang.to_owned())
.collect(),
}
}
fn update_from_env(
&mut self,
message_locale: Option<(LocaleVariable, String)>,
language_var: Option<Vec<String>>,
) {
// Do not override values set via `status language`.
if self.precedence_origin == LanguagePrecedenceOrigin::StatusLanguage {
return;
}
if let Some((precedence_origin, locale)) = &message_locale {
// Regular locale names start with lowercase letters (`ll_CC`, followed by some suffix).
// The C or POSIX locale is special, and often used to disable localization.
// Their names are upper-case, but variants with suffixes (`C.UTF-8`) exist.
// To ensure that such variants are accounted for, we match on prefixes of the
// locale name.
// https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html#tag_07_02
fn is_c_locale(locale: &str) -> bool {
locale.starts_with('C') || locale.starts_with("POSIX")
}
if is_c_locale(locale) {
self.precedence_origin =
LanguagePrecedenceOrigin::LocaleVariable(*precedence_origin);
self.language_precedence.clear();
return;
}
}
let (precedence_origin, language_list) = if let Some(list) = language_var {
(LanguagePrecedenceOrigin::LanguageEnvVar, list)
} else if let Some((precedence_origin, locale)) = message_locale {
let mut normalized_name = String::new();
// Strip off encoding and modifier. (We always expect UTF-8 and don't support modifiers.)
for c in locale.chars() {
if c.is_alphabetic() || c == '_' {
normalized_name.push(c);
} else {
break;
}
}
// At this point, the normalized_name should have the shape `ll` or `ll_CC`.
(
precedence_origin.as_language_precedence_origin(),
vec![normalized_name],
)
} else {
(LanguagePrecedenceOrigin::Default, vec![])
};
let mut seen_languages = HashSet::new();
self.language_precedence = language_list
.into_iter()
.flat_map(|lang| find_existing_catalogs(&lang))
.filter(|(lang, _)| seen_languages.insert(lang.to_owned()))
.collect();
self.precedence_origin = precedence_origin;
}
fn update_from_status_language_builtin<'a, 'b: 'a, S: AsRef<str> + 'a>(
&mut self,
langs: &'b [S],
) -> SetLanguageLints<'a> {
let mut seen = HashSet::new();
let mut duplicates = vec![];
for lang in langs {
let lang = lang.as_ref();
if !seen.insert(lang) {
duplicates.push(lang)
}
}
let mut existing_langs = vec![];
let mut non_existing = vec![];
for lang in langs {
let lang = lang.as_ref();
if let Some(catalog) = CATALOGS.get(lang) {
existing_langs.push((lang.to_owned(), *catalog));
} else {
non_existing.push(lang);
}
}
let mut seen = HashSet::new();
let unique_langs = existing_langs
.into_iter()
.filter(|(lang, _)| seen.insert(lang.to_owned()))
.collect();
self.language_precedence = unique_langs;
self.precedence_origin = LanguagePrecedenceOrigin::StatusLanguage;
SetLanguageLints {
duplicates,
non_existing,
}
}
}
/// Tries to find catalogs for `language`.
/// `language` must be an ISO 639 language code, optionally followed by an underscore and an ISO
/// 3166 country/territory code.
/// Uses the catalog with the exact same name as `language` if it exists.
/// If a country code is present (`ll_CC`), only the catalog named `ll` will be considered as a fallback.
/// If no country code is present (`ll`), all catalogs whose names start with `ll_` will be used in
/// arbitrary order.
fn find_existing_catalogs(language: &str) -> Vec<(String, Catalog)> {
// Try the exact name first.
// If there already is a corresponding catalog return the language.
if let Some(catalog) = CATALOGS.get(language) {
return vec![(language.to_owned(), catalog)];
}
let language_without_country_code = language.split_once('_').map_or(language, |(ll, _cc)| ll);
if language == language_without_country_code {
// We have `ll` format. In this case, try to find any catalog whose name starts with `ll_`.
// Note that it is important to include the underscore in the pattern, otherwise `ll` might
// fall back to `llx_CC`, where `llx` is a 3-letter language identifier.
let ll_prefix = format!("{language}_");
let mut lang_catalogs = vec![];
for (&lang_name, &catalog) in CATALOGS.entries() {
if lang_name.starts_with(&ll_prefix) {
lang_catalogs.push((lang_name.to_owned(), catalog));
}
}
lang_catalogs
} else {
// If `language` contained a country code, we only try to fall back to a catalog
// without a country code.
if let Some(catalog) = CATALOGS.get(language_without_country_code) {
vec![(language_without_country_code.to_owned(), catalog)]
} else {
vec![]
}
}
}
pub fn update_from_env(
locale: Option<(LocaleVariable, String)>,
language_var: Option<Vec<String>>,
) {
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
localization_state.update_from_env(locale, language_var);
}
pub fn update_from_status_language_builtin<'a, 'b: 'a, S: AsRef<str> + 'a>(
langs: &'b [S],
) -> SetLanguageLints<'a> {
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
localization_state.update_from_status_language_builtin(langs)
}
pub fn unset_from_status_language_builtin(
locale: Option<(LocaleVariable, String)>,
language_var: Option<Vec<String>>,
) {
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
localization_state.precedence_origin = LanguagePrecedenceOrigin::Default;
localization_state.update_from_env(locale, language_var);
}
pub fn status_language() -> PublicLocalizationState {
let localization_state = LOCALIZATION_STATE.lock().unwrap();
localization_state.to_public()
}
pub fn gettext(message_str: &'static str) -> Option<&'static str> {
let localization_state = LOCALIZATION_STATE.lock().unwrap();
// Use the localization from the highest-precedence language that has one available.
for (_, catalog) in localization_state.language_precedence.iter() {
if let Some(localized_str) = catalog.get(message_str) {
return Some(localized_str);
}
}
None
}
pub fn list_available_languages() -> Vec<&'static str> {
let mut langs: Vec<_> = CATALOGS.entries().map(|(&lang, _)| lang).collect();
langs.sort();
langs
}

View File

@@ -233,7 +233,7 @@ fn test_to_arg() {
assert!(matches!(42u64.to_arg(), Arg::UInt(42)));
assert!(matches!(42usize.to_arg(), Arg::UInt(42)));
let ptr = &42f32 as *const f32;
let ptr = std::ptr::from_ref(&42f32);
assert!(matches!(ptr.to_arg(), Arg::UInt(_)));
}

View File

@@ -1,7 +1,6 @@
use crate::arg::ToArg;
use crate::locale::{C_LOCALE, EN_US_LOCALE, Locale};
use crate::{Error, FormatString, sprintf_locale};
use libc::c_char;
use std::f64::consts::{E, PI, TAU};
use std::ffi::CStr;
use std::fmt;
@@ -890,10 +889,16 @@ fn libc_sprintf_one_float_with_precision<'a>(
fmt: &'a CStr,
) -> impl FnMut(usize, f64) -> &'a str {
|preci, float_val| unsafe {
let storage_ptr = storage.as_mut_ptr() as *mut c_char;
let len = libc::snprintf(storage_ptr, storage.len(), fmt.as_ptr(), preci, float_val);
let storage_ptr = storage.as_mut_ptr();
let len = libc::snprintf(
storage_ptr.cast(),
storage.len(),
fmt.as_ptr(),
preci,
float_val,
);
assert!(len >= 0);
let sl = std::slice::from_raw_parts(storage_ptr as *const u8, len as usize);
let sl = std::slice::from_raw_parts(storage_ptr, len as usize);
std::str::from_utf8(sl).unwrap()
}
}

View File

@@ -4,9 +4,11 @@ edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
nix = { workspace = true, features = ["fs", "feature"] }
rand.workspace = true
[lints]
workspace = true

View File

@@ -1,4 +1,11 @@
use std::{fs::File, path::PathBuf};
use std::{
ffi::OsString,
fs::{File, OpenOptions},
io::ErrorKind,
path::PathBuf,
};
use rand::distr::{Alphanumeric, Distribution};
pub struct TempFile {
file: File,
@@ -41,20 +48,56 @@ fn drop(&mut self) {
}
}
fn get_tmpdir() -> PathBuf {
PathBuf::from(std::env::var_os("TMPDIR").unwrap_or("/tmp".into()))
/// Creates a random filename with the given prefix.
/// Appends a random sequence of alphanumeric ASCII characters.
pub fn random_filename(mut prefix: OsString) -> OsString {
let mut rng = rand::rng();
let suffix_length = 10;
let random_part: String = Alphanumeric
.sample_iter(&mut rng)
.take(suffix_length)
.map(char::from)
.collect();
assert_eq!(random_part.len(), suffix_length);
prefix.push(random_part);
prefix
}
fn get_template() -> PathBuf {
get_tmpdir().join("fish_tmp_XXXXXX")
/// Tries to create a new file at the path returned by `generate_path`.
/// If a file already exists at this path, `generate_path` will be called again and file creation
/// will be retried. This is repeated until a new file is created, or an error occurs.
pub fn create_file_with_retry(
generate_path: impl Fn() -> PathBuf,
) -> (PathBuf, std::io::Result<File>) {
loop {
let path = generate_path();
match OpenOptions::new()
.read(true)
.write(true)
.create_new(true)
.open(&path)
{
Ok(file) => {
return (path, Ok(file));
}
Err(e) => {
if e.kind() != ErrorKind::AlreadyExists {
return (path, Err(e));
}
}
}
}
}
/// Tries to create a new temporary file using `mkstemp`.
/// Tries to create a new temporary file in the operating system's default location for temporary
/// files.
/// On success, a [`TempFile`] is returned.
/// When this struct is dropped, the backing file will be deleted.
pub fn new_file() -> std::io::Result<TempFile> {
let (fd, path) = nix::unistd::mkstemp(&get_template())?;
let file = File::from(fd);
let (path, result) = create_file_with_retry(|| {
std::env::temp_dir().join(random_filename(OsString::from("fish_tmp_")))
});
let file = result?;
Ok(TempFile { file, path })
}
@@ -62,7 +105,8 @@ pub fn new_file() -> std::io::Result<TempFile> {
/// On success, a [`TempDir`] is returned.
/// When this struct is dropped, the backing directory, including all its contents, will be deleted.
pub fn new_dir() -> std::io::Result<TempDir> {
let path = nix::unistd::mkdtemp(&get_template())?;
let template = std::env::temp_dir().join("fish_tmp_XXXXXX");
let path = nix::unistd::mkdtemp(&template)?;
Ok(TempDir { path })
}

14
crates/wchar/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "fish-wchar"
edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license.workspace = true
[dependencies]
fish-common.workspace = true
widestring.workspace = true
[lints]
workspace = true

View File

@@ -1,11 +1,51 @@
use std::{iter, slice};
//! Support for wide strings.
//!
//! There are two wide string types that are commonly used:
//! - wstr: a string slice without a nul terminator. Like `&str` but wide chars.
//! - WString: an owning string without a nul terminator. Like `String` but wide chars.
use crate::{
L,
common::subslice_position,
wchar::{WString, wstr},
};
use widestring::utfstr::CharsUtf32;
use fish_common::{ENCODE_DIRECT_BASE, ENCODE_DIRECT_END, subslice_position};
use std::{iter, slice};
pub use widestring::{Utf32Str as wstr, Utf32String as WString, utfstr::CharsUtf32};
pub mod prelude {
pub use crate::{IntoCharIter, L, ToWString, WExt, WString, wstr};
}
/// Creates a wstr string slice, like the "L" prefix of C++.
/// The result is of type wstr.
/// It is NOT nul-terminated.
#[macro_export]
macro_rules! L {
($string:expr) => {
widestring::utf32str!($string)
};
}
/// Encode a literal byte in a UTF-32 character. This is required for e.g. the echo builtin, whose
/// escape sequences can be used to construct raw byte sequences which are then interpreted as e.g.
/// UTF-8 by the terminal. If we were to interpret each of those bytes as a codepoint and encode it
/// as a UTF-32 character, printing them would result in several characters instead of one UTF-8
/// character.
///
/// See <https://github.com/fish-shell/fish-shell/issues/1894>.
pub fn encode_byte_to_char(byte: u8) -> char {
char::from_u32(u32::from(ENCODE_DIRECT_BASE) + u32::from(byte))
.expect("private-use codepoint should be valid char")
}
/// Decode a literal byte from a UTF-32 character.
pub fn decode_byte_from_char(c: char) -> Option<u8> {
if c >= ENCODE_DIRECT_BASE && c < ENCODE_DIRECT_END {
Some(
(u32::from(c) - u32::from(ENCODE_DIRECT_BASE))
.try_into()
.unwrap(),
)
} else {
None
}
}
/// Helpers to convert things to widestring.
/// This is like std::string::ToString.
@@ -73,6 +113,9 @@ fn to_wstring(&self) -> WString {
pub trait IntoCharIter {
type Iter: DoubleEndedIterator<Item = char> + Clone;
fn chars(self) -> Self::Iter;
fn extend_wstring(&self, _out: &mut WString) -> bool {
false
}
}
impl IntoCharIter for char {
@@ -89,12 +132,23 @@ fn chars(self) -> Self::Iter {
}
}
impl<'a> IntoCharIter for &'a String {
type Iter = std::str::Chars<'a>;
fn chars(self) -> Self::Iter {
str::chars(self)
}
}
impl<'a> IntoCharIter for &'a [char] {
type Iter = iter::Copied<slice::Iter<'a, char>>;
fn chars(self) -> Self::Iter {
self.iter().copied()
}
fn extend_wstring(&self, out: &mut WString) -> bool {
out.push_utfstr(wstr::from_char_slice(self));
true
}
}
impl<'a> IntoCharIter for &'a wstr {
@@ -102,6 +156,9 @@ impl<'a> IntoCharIter for &'a wstr {
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
impl<'a> IntoCharIter for &'a WString {
@@ -109,6 +166,9 @@ impl<'a> IntoCharIter for &'a WString {
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
// Also support `str.chars()` itself.
@@ -127,6 +187,23 @@ fn chars(self) -> Self::Iter {
}
}
impl<'a: 'b, 'b> IntoCharIter for &'b std::borrow::Cow<'a, str> {
type Iter = std::str::Chars<'b>;
fn chars(self) -> Self::Iter {
str::chars(self)
}
}
impl<'a: 'b, 'b> IntoCharIter for &'b std::borrow::Cow<'a, wstr> {
type Iter = CharsUtf32<'b>;
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
/// Return true if `prefix` is a prefix of `contents`.
fn iter_prefixes_iter<Prefix, Contents>(prefix: Prefix, mut contents: Contents) -> bool
where
@@ -157,10 +234,10 @@ fn next(&mut self) -> Option<Self::Item> {
if let Some(idx) = chars.iter().position(|c| *c == self.split) {
let (prefix, rest) = chars.split_at(idx);
self.chars = Some(&rest[1..]);
return Some(wstr::from_char_slice(prefix));
Some(wstr::from_char_slice(prefix))
} else {
self.chars = None;
return Some(wstr::from_char_slice(chars));
Some(wstr::from_char_slice(chars))
}
}
}
@@ -303,7 +380,6 @@ fn as_char_slice(&self) -> &[char] {
#[cfg(test)]
mod tests {
use super::*;
use crate::wchar::L;
#[test]
fn test_to_wstring() {

View File

@@ -0,0 +1,10 @@
[package]
name = "fish-widecharwidth"
edition.workspace = true
rust-version.workspace = true
version = "0.0.0"
repository.workspace = true
license = "CC0-1.0"
[lints]
workspace = true

1
debian/compat vendored
View File

@@ -1 +0,0 @@
12

View File

@@ -6,9 +6,12 @@ allow = [
"BSD-2-Clause",
"BSD-3-Clause",
"BSL-1.0",
"CC0-1.0",
"GPL-2.0",
"GPL-2.0-only",
"ISC",
"LGPL-2.0",
"LGPL-2.0-or-later",
"MIT",
"MPL-2.0",
"PSF-2.0",

View File

@@ -31,7 +31,7 @@ The work will **proceed on master**: no long-lived branches. Tests and CI contin
The Rust code will initially resemble the replaced C++. Fidelity to existing code is more important than Rust idiomaticity, to aid review and bisecting. But don't take this to extremes - use judgement.
The port will proceed "outside in." We'll start with leaf components (e.g. builtins) and proceed towards the core. Some components will have both a Rust and C++ implementation (e.g. FLOG), in other cases we'll change the existing C++ to invoke the new Rust implementations (builtins).
The port will proceed "outside in." We'll start with leaf components (e.g. builtins) and proceed towards the core. Some components will have both a Rust and C++ implementation (e.g. flog), in other cases we'll change the existing C++ to invoke the new Rust implementations (builtins).
After porting the C++, we'll replace CMake.

View File

@@ -58,7 +58,7 @@ The basic development loop for this port:
- Do this even if it results in less idiomatic Rust, but avoid being super-dogmatic either way.
- One technique is to paste the C++ into the Rust code, commented out, and go line by line.
4. Decide whether any existing C++ callers should invoke the Rust implementation, or whether we should keep the C++ one.
- Utility functions may have both a Rust and C++ implementation. An example is `FLOG` where interop is too hard.
- Utility functions may have both a Rust and C++ implementation. An example is `flog` where interop is too hard.
- Major components (e.g. builtin implementations) should _not_ be duplicated; instead the Rust should call C++ or vice-versa.
5. Remember to run `cargo fmt` and `cargo clippy` to keep the codebase somewhat clean (otherwise CI will fail). If you use rust-analyzer, you can run clippy automatically by setting `rust-analyzer.checkOnSave.command = "clippy"`.
@@ -93,7 +93,7 @@ None of the Rust string types are nul-terminated. We're taking this opportunity
One may create a `&wstr` from a string literal using the `wchar::L!` macro:
```rust
use crate::wchar::prelude::*;
use crate::prelude::*;
// This imports wstr, the L! macro, WString, a ToWString trait that supplies .to_wstring() along with other things
fn get_shell_name() -> &'static wstr {
@@ -116,7 +116,7 @@ fn get_shell_name() -> &'static wstr {
#### The wchar prelude
We have a prelude to make working with these string types a whole lot more ergonomic. In particular `WExt` supplies the null-terminated-compatible `.char_at(usize)`,
and a whole lot more methods that makes porting C++ code easier. It is also preferred to use char-based-methods like `.char_count()` and `.slice_{from,to}()`
and a whole lot more methods that makes porting C++ code easier. It is also preferred to use char-based-methods like `.char_count()` and `.slice_{from,to}()`
of the `WExt` trait over directly calling `.len()` and `[usize..]/[..usize]`, as that makes the code compatible with a potential future change to UTF8-strings.
```rust
@@ -144,7 +144,7 @@ These types should be confined to the FFI modules, in particular `wchar_ffi`. Th
### Format strings
Rust's builtin `std::fmt` modules do not accept runtime-provided format strings, so we mostly won't use them, except perhaps for FLOG / other non-translated text.
Rust's builtin `std::fmt` modules do not accept runtime-provided format strings, so we mostly won't use them, except perhaps for flog / other non-translated text.
Instead we'll continue to use printf-style strings, with a Rust printf implementation.

View File

@@ -23,6 +23,8 @@ If other programs launched via fish should respect these locale variables they h
For :envvar:`LANGUAGE` you can use a list, or use colons to separate multiple languages.
If the :ref:`status language set <status-language>` command was used, its arguments specify the language precedence, and the environment variables are ignored.
Options
-------

View File

@@ -46,7 +46,7 @@ Combining these features, it is possible to create custom syntaxes, where a regu
> abbr >> ~/.config/fish/config.fish
> abbr --erase (abbr --list)
Alternatively you can keep them in a separate :ref:`configuration file <configuration>` by doing something like the following::
> abbr > ~/.config/fish/conf.d/myabbrs.fish

View File

@@ -46,12 +46,12 @@ The following code will create ``rmi``, which runs ``rm`` with additional argume
::
alias rmi="rm -i"
# This is equivalent to entering the following function:
function rmi --wraps rm --description 'alias rmi=rm -i'
rm -i $argv
end
``alias`` sometimes requires escaping, as you can see here::
# This needs to have the spaces escaped or "Chrome.app..."

View File

@@ -33,10 +33,10 @@ The following code sets a number of variables inside of a block scope. Since the
begin
set -l PIRATE Yarrr
...
end
echo $PIRATE
# This will not output anything, since the PIRATE variable
# went out of scope at the end of the block

View File

@@ -145,12 +145,17 @@ The following special input functions are available:
``backward-kill-line``
move everything from the beginning of the line to the cursor to the killring
.. _cmd-bind-backward-kill-path-component:
``backward-kill-path-component``
move one path component to the left of the cursor to the killring. A path component is everything likely to belong to a path component, i.e. not any of the following: `/={,}'\":@ |;<>&`, plus newlines and tabs.
``backward-kill-word``
move the word to the left of the cursor to the killring. The "word" here is everything up to punctuation or whitespace.
``backward-path-component``
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the left.
``backward-word``
move one word to the left
@@ -241,6 +246,9 @@ The following special input functions are available:
commandline, does not accept the current autosuggestion (if any). Does not change the selected item in the completion pager,
if shown.
``forward-path-component``
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the right; or if at the end of the commandline, accept a path component from the current autosuggestion.
``forward-single-char``
move one character to the right; or if at the end of the commandline, accept a single char from the current autosuggestion.
@@ -308,6 +316,9 @@ The following special input functions are available:
``kill-line``
move everything from the cursor to the end of the line to the killring
``kill-path-component``
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the killring.
``kill-selection``
move the selected text to the killring

View File

@@ -41,7 +41,7 @@ Examples
cd
# changes the working directory to your home directory.
cd /usr/src/fish-shell
# changes the working directory to /usr/src/fish-shell

View File

@@ -103,6 +103,31 @@ When erasing completions, it is possible to either erase all completions for a s
When ``complete`` is called without anything that would define or erase completions (options, arguments, wrapping, ...), it shows matching completions instead. So ``complete`` without any arguments shows all loaded completions, ``complete -c foo`` shows all loaded completions for ``foo``. Since completions are :ref:`autoloaded <syntax-function-autoloading>`, you will have to trigger them first.
.. _completions-cygwin:
Cygwin / MSYS2 / Windows
------------------------
On Windows, binary executables have a ``.exe`` extension, but this extension is not required when calling an application (and if the name is not ambiguous, i.e. there isn't also a script called ``myprog`` in the same directory as ``myprog.exe``).
To unify completions between Windows and other OSes, on Cygwin/MSYS2/Windows, *COMMAND* does not require the ``.exe`` extension.
Completions for ``myprog`` will also be used for ``myprog.exe`` if there are no ambiguities, i.e. if there are no completions for ``myprog.exe`` specifically.
However, completions for ``myprog.exe`` will only be used when also using the ``.exe`` extension on the command line.
In other words:
::
complete -c myprog.exe ... #1
will only work for ``myprog.exe``
::
complete -c myprog ... #2
can work for both ``myprog`` and ``myprog.exe``. But if both completions exist, #2 will only be used for ``myprog`` while ``myprog.exe`` will use #1.
Examples
--------

View File

@@ -30,7 +30,7 @@ Example
count $PATH
# Returns the number of directories in the users PATH variable.
count *.txt
# Returns the number of files in the current working directory
# ending with the suffix '.txt'.

View File

@@ -27,7 +27,7 @@ The following code first defines an event handler for the generic event named 't
function event_test --on-event test_event
echo event test: $argv
end
emit test_event something

View File

@@ -7,7 +7,7 @@ Synopsis
.. synopsis::
begin
[COMMANDS ...]
[COMMANDS ...]
end
.. synopsis::

View File

@@ -13,7 +13,7 @@ Synopsis
Description
-----------
``export`` is a function included for compatibility with POSIX shells. In general, the :doc:`set <set>`
``export`` is a function included for compatibility with POSIX shells. In general, the :doc:`set <set>`
builtin should be used instead.
When called without arguments, ``export`` prints a list of currently-exported variables, like ``set

View File

@@ -51,7 +51,7 @@ The following options are available:
when :command:`fish` exits, output timing information on all executed commands to the specified file.
This excludes time spent starting up and reading the configuration.
**--profile-startup=PROFILE_FILE**
**--profile-startup=PROFILE_FILE**
Will write timing for ``fish`` startup to specified file.
**-P** or **--private**

View File

@@ -8,7 +8,12 @@ Synopsis
fish_config [browse]
fish_config prompt (choose | list | save | show)
fish_config theme (choose | demo | dump | list | save | show)
fish_config theme
fish_config theme choose THEME [ --color-theme=(dark | light) ]
fish_config theme demo
fish_config theme dump
fish_config theme list
fish_config theme show [THEME...]
Description
-----------
@@ -32,15 +37,20 @@ With the ``theme`` command ``fish_config`` can be used to view and choose a them
Available subcommands for the ``theme`` command:
- ``choose`` loads a sample theme in the current session.
- ``choose`` loads a theme in the current session.
If the theme has light and dark variants (see below), the one matching :envvar:`fish_terminal_color_theme` will be applied (also whenever that variable changes).
To override :envvar:`fish_terminal_color_theme`, pass the ``--color-theme`` argument.
- ``demo`` displays some sample text in the current theme.
- ``dump`` prints the current theme in a loadable format.
- ``list`` lists the names of the available sample themes.
- ``save`` saves the given theme to :ref:`universal variables <variables-universal>`.
- ``show`` shows what the given sample theme (or all) would look like.
- ``list`` lists the names of the available themes.
- ``show`` shows what the given themes (or all) would look like.
- *(not recommended)* ``save`` saves the given theme to :ref:`universal variables <variables-universal>`.
A theme set this way will not update as :envvar:`fish_terminal_color_theme` changes.
The **-h** or **--help** option displays help about using this command.
.. _fish-config-theme-files:
Theme Files
-----------
@@ -60,24 +70,38 @@ The format looks like this:
::
# name: 'Cool Beans'
# preferred_background: black
# name: 'My Theme'
fish_color_autosuggestion 666
fish_color_cancel -r
fish_color_command normal
fish_color_comment '888' '--italics'
fish_color_cwd 0A0
fish_color_cwd_root A00
fish_color_end 009900
[light]
# preferred_background: ffffff
fish_color_normal 000000
fish_color_autosuggestion 7f7f7f
fish_color_command 0000ee
The two comments at the beginning are the name and background that the web config tool shows.
[dark]
# preferred_background: 000000
fish_color_normal ffffff
fish_color_autosuggestion 7f7f7f
fish_color_command 5c5cff
[unknown]
fish_color_normal normal
fish_color_autosuggestion brblack
fish_color_cancel -r
fish_color_command normal
The comments provide name and background color to the web config tool.
Themes can have three variants,
one for light mode,
one for dark mode,
and one for terminals that don't :ref:`report colors <term-compat-query-background-color>` (where :envvar:`fish_terminal_color_theme` is set to ``unknown``).
The other lines are just like ``set variable value``, except that no expansions are allowed. Quotes are, but aren't necessary.
Any color variable fish knows about that the theme doesn't set will be set to empty when it is loaded, so the old theme is completely overwritten.
.. _fish_config-color-variables:
Other than that, .theme files can contain any variable with a name that matches the regular expression ``'^fish_(?:pager_)?color.*$'`` - starts with ``fish_``, an optional ``pager_``, then ``color`` and then anything.
Other than that, .theme files can contain any variable with a name that matches the regular expression ``'^fish_(?:pager_)?color_.*$'`` - starts with ``fish_``, an optional ``pager_``, then ``color_`` and then anything.
Example
-------

View File

@@ -23,7 +23,7 @@ The fish_hg_prompt function displays information about the current Mercurial rep
By default, only the current branch is shown because ``hg status`` can be slow on a large repository. You can enable a more informative prompt by setting the variable ``$fish_prompt_hg_show_informative_status``, for example::
set --universal fish_prompt_hg_show_informative_status
set fish_prompt_hg_show_informative_status
If you enabled the informative status, there are numerous customization options, which can be controlled with fish variables.

View File

@@ -72,7 +72,7 @@ Same as above but the value of the second flag cannot be the empty string:
::
set -l options (fish_opt -s h -l help)
set options $options (fish_opt -s m -l max -rv test \$_flag_valu != "''")
set options $options (fish_opt -s m -l max -rv test \$_flag_value != "''")
argparse $options -- $argv
Same as above but with a third flag that can be given multiple times saving the value of each instance seen and only a long flag name (``--token``) is defined:
@@ -82,7 +82,7 @@ Same as above but with a third flag that can be given multiple times saving the
::
set -l options (fish_opt --short=h --long=help)
set options $options (fish_opt --short=m --long=max --required-val --validate test \$_flag_valu != "''")
set options $options (fish_opt --short=m --long=max --required-val --validate test \$_flag_value != "''")
set options $options (fish_opt --long=token --multiple-vals)
argparse $options -- $argv

View File

@@ -50,6 +50,6 @@ This refuses to store any immediate "vault", "mysql" or "ls" calls. Commands sta
and string match -qr "^/home/me/my-secret-project/" -- (pwd -P)
return 1
end
return 0
end

View File

@@ -23,7 +23,7 @@ Example
::
for i in foo bar baz; echo $i; end
# would output:
foo
bar

View File

@@ -85,7 +85,7 @@ will run the ``ls`` command, using the ``-l`` option, while passing on any addit
# prints: [DEBUG] foo: bar
# OR
function debug2 -a var
echo [DEBUG] $var: $$var >&2
end
@@ -106,7 +106,7 @@ will create a ``debug`` command to print chosen variables to `stderr`.
if test $status = 0
switch $argv[(count $argv)]
case '-*'
case '*'
cd $argv[(count $argv)]
return
@@ -124,7 +124,7 @@ This will run the ``mkdir`` command, and if it is successful, change the current
function notify
set -l job (jobs -l -g)
or begin; echo "There are no jobs" >&2; return 1; end
function _notify_job_$job --on-job-exit $job --inherit-variable job
echo -n \a # beep
functions -e _notify_job_$job

View File

@@ -82,10 +82,10 @@ Examples
functions -n
# Displays a list of currently-defined functions
functions -c foo bar
# Copies the 'foo' function to a new function called 'bar'
functions -e bar
# Erases the function ``bar``

View File

@@ -29,6 +29,11 @@ When in doubt, use parentheses.
``math`` ignores whitespace between arguments and takes its input as multiple arguments (internally joined with a space), so ``math 2 +2`` and ``math "2 + 2"`` work the same.
``math 2 2`` is an error.
.. note::
math is a simple tool for simple uses, provided for convenience. It internally works with floats for simplicity of implementation and can't do a number of things real calculators can.
If you find yourself limited by that, use a more full-featured tool.
The following options are available:
**-s** *N* or **--scale** *N*
@@ -153,7 +158,7 @@ Functions
``ln``
the base-e logarithm
``log`` or ``log10``
the base-10 logarithm
the base-10 logarithm. To compute the logarithm for an arbitrary base ``b``, use ``log(x) / log(b)``.
``log2``
the base-2 logarithm
``max``

View File

@@ -209,7 +209,7 @@ Examples
# This is the same as above: "-f" is "--type=file", "-d" is "--type=dir",
# "-x" is short for "--perm=exec" and "-w" short for "--perm=write"!
/home/me
>_ path filter -fx $PATH/*
# Prints all possible commands - the first entry of each name is what fish would execute!
@@ -306,7 +306,7 @@ Examples
>_ path normalize /bin//bash
# The "//" is squashed, but /bin isn't resolved even if your system links it to /usr/bin.
/bin/bash
>_ path normalize ./my/subdirs/../sub2
my/sub2
@@ -337,7 +337,7 @@ Examples
# The "//" is squashed, and /bin is resolved if your system links it to /usr/bin.
# sh here is bash (this is common on linux systems)
/usr/bin/bash
>_ path resolve /bin/foo///bar/../baz
# Assuming /bin exists and is a symlink to /usr/bin, but /bin/foo doesn't.
# This resolves the /bin/ and normalizes the nonexistent rest:
@@ -381,7 +381,7 @@ Examples
>_ path change-extension '' ~/.config.
/home/alfa/.config
"sort" subcommand
-----------------------------

View File

@@ -22,7 +22,7 @@ The *FORMAT* argument is re-used as many times as necessary to convert all of th
Unlike :doc:`echo <echo>`, ``printf`` does not append a new line unless it is specified as part of the string.
It doesn't support any options, so there is no need for a ``--`` separator, which makes it easier to use for arbitrary input than ``echo``. [#]_
It doesn't support any options, so there is no need for a ``--`` separator, which makes it easier to use for arbitrary input than ``echo``. [#]_
Format Specifiers
-----------------

View File

@@ -44,7 +44,7 @@ Example
The following code will count down from a random even number between 10 and 20 to 1:
::
for i in (seq (random 10 2 20) -1 1)
echo $i
end
@@ -62,5 +62,5 @@ Or, to only get even numbers from 2 to 20::
random 2 2 20
Or odd numbers from 1 to 3::
random 1 2 3 # or 1 2 4

View File

@@ -12,7 +12,8 @@ Synopsis
set [-Uflg] NAME[[INDEX ...]] [VALUE ...]
set (-x | --export) (-u | --unexport) [-Uflg] NAME [VALUE ...]
set (-a | --append) (-p | --prepend) [-Uflg] NAME VALUE ...
set (-q | --query) (-e | --erase) [-Uflg] [NAME][[INDEX]] ...]
set (-e | --erase) [-Uflg] [-xu] [NAME][[INDEX]] ...]
set (-q | --query) [-Uflg] [-xu] [NAME][[INDEX]] ...]
set (-S | --show) (-L | --long) [NAME ...]
Description
@@ -88,6 +89,7 @@ Further options:
**-q** or **--query** *NAME*\[*INDEX*\]
Test if the specified variable names are defined.
If an *INDEX* is provided, check for items at that slot.
With a given scope (like **--global**) or attribute (like **--exported** or **--path**) check only variables that match.
Does not output anything, but the shell status is set to the number of variables specified that were not defined, up to a maximum of 255.
If no variable was given, it also returns 255.

View File

@@ -57,6 +57,15 @@ The following options are available:
**-u** or **--underline**, or **-uSTYLE** or **--underline=STYLE**
Set the underline mode; supported styles are **single** (default), **double**, **curly**, **dotted** and **dashed**.
**--theme=THEME**
Ignored.
:ref:`Color variables <variables-color>` that contain only this option are treated like missing / empty color variables,
i.e. fish will use the fallback color instead.
:doc:`fish_config theme choose <fish_config>` erases all :ref:`color variable <fish_config-color-variables>`
whose value includes this option, and adds this option to all color variables it sets.
This allows identifying variables set by a theme,
and it allows fish to update color variables whenever :envvar:`fish_terminal_color_theme` changes.
**-h** or **--help**
Displays help about using this command.

View File

@@ -30,10 +30,10 @@ Synopsis
status test-feature FEATURE
status build-info
status get-file FILE
status list-files [PATH]
status help-sections
status list-files [PATH ...]
status terminal
status test-terminal-feature FEATURE
status language [list-available|set [LANGUAGE ...]|unset]
Description
-----------
@@ -118,19 +118,12 @@ The following operations (subcommands) are available:
as well as the man pages and themes. Which files are included depends on build settings.
Returns 0 if the file was included, 1 otherwise.
**list-files** *FILE*
**list-files** *FILE...*
NOTE: this subcommand is mainly intended for fish's internal use; let us know if you want to use it elsewhere.
This lists the files embedded in the fish binary at compile time. Only files where the path starts with the optional *FILE* argument are shown.
Returns 0 if something was printed, 1 otherwise.
**help-sections**
NOTE: this subcommand is intended for fish's internal use.
List section arguments for the :doc:`help <help>` command.
If you have the latest version of fish, these URL fragments are valid on `<https://fishshell.com/docs/current/>`__.
Always returns 0.
.. _status-terminal:
**terminal**
@@ -138,6 +131,13 @@ The following operations (subcommands) are available:
This is not available during early startup but only starting from when the first interactive prompt is shown, possibly via builtin :doc:`read <read>`,
so before the first ``fish_prompt`` or ``fish_read`` :ref:`event <event>`.
.. _status-terminal-os:
**terminal-os**
Prints the name of the operating system (OS) the terminal is running on, as reported via :ref:`XTGETTCAP query-os-name <term-compat-xtgettcap>`.
Like :ref:`status terminal <status-terminal>`, this only works once the first interactive prompt is shown.
Returns 1 if the OS name is not available.
.. _status-test-terminal-features:
**test-terminal-feature** *FEATURE*
@@ -147,6 +147,32 @@ The following operations (subcommands) are available:
Currently the only available *FEATURE* is :ref:`scroll-content-up <term-compat-indn>`.
An error will be printed when passed an unrecognized feature.
.. _status-language:
**language**
Show or modify message localization settings.
When invoked without arguments, the current language settings are shown.
Available subcommands:
**list-available**
prints the language names for which fish has translations.
These names can be used with the **set** subcommand.
**set**
sets the language precedence for fish's messages.
Overrides language settings configured via :ref:`environment variables <variables-locale>`, but only applies to fish itself, not to any child processes.
Takes a list of language names from the set shown by the **list-available** subcommand.
For some languages, fish's translation catalogs are incomplete, meaning not all messages can be shown in these languages.
Therefore, we allow specifying a list here, with translations taken from the first specified language which has a translation available for a message.
For example, after running ``status language set pt_BR fr``, all messages which have a translation into Brazilian Portuguese will be shown in that language.
The remaining messages will be shown in French, if a French translation is available.
If none of the specified languages have a translation available for a message, the message will be shown in English.
**unset**
undoes the effects of the **set** subcommand.
Language settings will be taken from environment variables again.
Notes
-----

View File

@@ -46,7 +46,7 @@ Examples
# depending on $fish_emoji_width, this is either 4 or 8
# in new terminals it should be
8
>_ string length --visible abcdef\r123
# this displays as "123def", so the width is 6
6

View File

@@ -89,7 +89,7 @@ See Also
.. BEGIN SEEALSO
- :doc:`string pad <string-pad>` does the inverse of this command, adding padding to a specific width instead.
- The :doc:`printf <printf>` command can do simple padding, for example ``printf %10s\n`` works like ``string pad -w10``.
- :doc:`string length <string-length>` with the ``--visible`` option can be used to show what fish thinks the width is.

View File

@@ -55,7 +55,7 @@ Example
::
>_ time sleep 1s
________________________________________________________
Executed in 1,01 secs fish external
usr time 2,32 millis 0,00 micros 2,32 millis

View File

@@ -95,5 +95,5 @@ And here is the full list:
.. toctree::
:glob:
:maxdepth: 1
cmds/*

View File

@@ -1,7 +1,7 @@
Writing your own completions
============================
To specify a completion, use the ``complete`` command. ``complete`` takes as a parameter the name of the command to specify a completion for. For example, to add a completion for the program ``myprog``, start the completion command with ``complete -c myprog ...``
To specify a completion, use the ``complete`` command. ``complete`` takes as a parameter the name of the command to specify a completion for. For example, to add a completion for the program ``myprog`` (or ``myprog.exe`` on :ref:`Cygwin/MSYS2 <completions-cygwin>`), start the completion command with ``complete -c myprog ...``
For a complete description of the various switches accepted by the ``complete`` command, see the documentation for the :doc:`complete <cmds/complete>` builtin, or write ``complete --help`` inside the ``fish`` shell.
@@ -160,4 +160,3 @@ This wide search may be confusing. If you are unsure, your completions probably
If you have written new completions for a common Unix command, please consider sharing your work by submitting it via the instructions in :ref:`Further help and development <more-help>`.
If you are developing another program and would like to ship completions with your program, install them to the "vendor" completions directory. As this path may vary from system to system, the ``pkgconfig`` framework should be used to discover this path with the output of ``pkg-config --variable completionsdir fish``.

Some files were not shown because too many files have changed in this diff Show More