mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 09:41:16 -03:00
Compare commits
280 Commits
macos-apro
...
4.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdfc491d56 | ||
|
|
b72127a0b7 | ||
|
|
0ab2a46424 | ||
|
|
5844650881 | ||
|
|
3c77a67668 | ||
|
|
3105f88622 | ||
|
|
5702b26b22 | ||
|
|
60ef7ca210 | ||
|
|
c486c54120 | ||
|
|
6273b9420b | ||
|
|
4bb0d956eb | ||
|
|
92db03ac9f | ||
|
|
0d6aaa36d3 | ||
|
|
88a7888478 | ||
|
|
74cb96d55b | ||
|
|
30942e16dc | ||
|
|
a8ded9cb0d | ||
|
|
4d67678217 | ||
|
|
9460559345 | ||
|
|
74af4f10de | ||
|
|
b2f4befc7e | ||
|
|
771b33b3a3 | ||
|
|
1cf4e191b3 | ||
|
|
b88a5eaad5 | ||
|
|
1c1baddf4f | ||
|
|
107cbaddf0 | ||
|
|
daa554123f | ||
|
|
979320063e | ||
|
|
fed0269762 | ||
|
|
6d68dfe12b | ||
|
|
97c59fa991 | ||
|
|
128fafce1e | ||
|
|
f1c8e6995d | ||
|
|
02061be279 | ||
|
|
c9b30b748d | ||
|
|
167cfd0892 | ||
|
|
5c3941f0dd | ||
|
|
d4745b633b | ||
|
|
dd97842964 | ||
|
|
5715d143a5 | ||
|
|
41571dec0f | ||
|
|
3c7517bf28 | ||
|
|
81fce66269 | ||
|
|
7b8f97c1ff | ||
|
|
9b75b6ee88 | ||
|
|
1ebf750bc0 | ||
|
|
dcd07d754d | ||
|
|
26873d4ad2 | ||
|
|
17c35217b9 | ||
|
|
b62a312cba | ||
|
|
3b976a3364 | ||
|
|
3df88597ca | ||
|
|
3ec603fc55 | ||
|
|
5545c648d9 | ||
|
|
765305d0e4 | ||
|
|
a261ca2aff | ||
|
|
556be5c4a8 | ||
|
|
92c5da1b25 | ||
|
|
fb161e9f4d | ||
|
|
67d78fb258 | ||
|
|
caef2c309d | ||
|
|
2f37eda9d9 | ||
|
|
5a35acf2e7 | ||
|
|
e1a6b7ea5a | ||
|
|
c9fcd31480 | ||
|
|
d6108e5bc0 | ||
|
|
2611646232 | ||
|
|
08600d012f | ||
|
|
16f14f0e89 | ||
|
|
50bcc3cf4f | ||
|
|
ee2d99ecf3 | ||
|
|
81e1f6937f | ||
|
|
03a3a3b52f | ||
|
|
074ab45049 | ||
|
|
aa8f5fc77e | ||
|
|
c0b95a0ee1 | ||
|
|
dd93a7e003 | ||
|
|
8064a13af9 | ||
|
|
ab7b522b64 | ||
|
|
0c9b73e317 | ||
|
|
b29a85f45f | ||
|
|
f0b4921ccf | ||
|
|
1d3aca2b44 | ||
|
|
574a8728af | ||
|
|
e7c1a6a67d | ||
|
|
54127e1028 | ||
|
|
a5330c7ba2 | ||
|
|
377abde112 | ||
|
|
62628f6fb1 | ||
|
|
64da7ca124 | ||
|
|
1db4dc4c3e | ||
|
|
ebc140a3ea | ||
|
|
5e401fc6ea | ||
|
|
608269320e | ||
|
|
c3a9edceac | ||
|
|
32cee9caec | ||
|
|
f417cbc981 | ||
|
|
92c814841a | ||
|
|
bf38e1beca | ||
|
|
17ba602acf | ||
|
|
5d37698ef8 | ||
|
|
7a7c0d6490 | ||
|
|
d88c0674a3 | ||
|
|
0306ec673f | ||
|
|
b14b6c9f42 | ||
|
|
8061c41c9b | ||
|
|
190d367bc4 | ||
|
|
f1f14cc8fa | ||
|
|
707bfe3ce6 | ||
|
|
d8f1a2a24f | ||
|
|
dbdecaba6d | ||
|
|
66f6493fbf | ||
|
|
76e0f9a3e8 | ||
|
|
697afdefeb | ||
|
|
aba89f9088 | ||
|
|
344187e01a | ||
|
|
9f11de24d4 | ||
|
|
7996637db5 | ||
|
|
d67cdf5f6f | ||
|
|
7dd2004da7 | ||
|
|
4000503c03 | ||
|
|
7c994cd784 | ||
|
|
e68ea35f02 | ||
|
|
5cc953b18d | ||
|
|
f264ee0b10 | ||
|
|
3c6978c038 | ||
|
|
d5732b132e | ||
|
|
ae22cc93db | ||
|
|
51e551fe5f | ||
|
|
33cb8679ba | ||
|
|
655b1aa7a1 | ||
|
|
daba5fdbcd | ||
|
|
01bd380d00 | ||
|
|
801c4f8158 | ||
|
|
e331e30e38 | ||
|
|
7bd30ac3c4 | ||
|
|
5631a7ec86 | ||
|
|
a9c43e7396 | ||
|
|
2a6c0e4437 | ||
|
|
7f224d0dfd | ||
|
|
f818002f38 | ||
|
|
6b8e82946a | ||
|
|
faaff2754b | ||
|
|
5c0e72bb89 | ||
|
|
b3b7d2cb00 | ||
|
|
f503dcb92d | ||
|
|
7f1b53a9f1 | ||
|
|
938e780007 | ||
|
|
3e7c5ae399 | ||
|
|
548f37eabb | ||
|
|
135fc73191 | ||
|
|
1fe5497b5d | ||
|
|
6b85450dea | ||
|
|
2309c27a2d | ||
|
|
8b5d66def8 | ||
|
|
27852a6734 | ||
|
|
cc29216ea9 | ||
|
|
831411ddd5 | ||
|
|
ec77c34ebe | ||
|
|
d1c7a4b6e7 | ||
|
|
7fc27e9e54 | ||
|
|
a4b949b0ca | ||
|
|
64196a2a9e | ||
|
|
353ecfadaf | ||
|
|
0e9ceb154e | ||
|
|
baaf06b2c6 | ||
|
|
106f7b86dc | ||
|
|
64e3b419b6 | ||
|
|
3237efc582 | ||
|
|
717d301b7f | ||
|
|
6a36d92173 | ||
|
|
75c005a4d4 | ||
|
|
07389055f1 | ||
|
|
692e6d57cf | ||
|
|
7952545460 | ||
|
|
4aa967cd5d | ||
|
|
3e2336043a | ||
|
|
c1db2744cf | ||
|
|
c6252967ab | ||
|
|
0fb5ab4098 | ||
|
|
de3d390391 | ||
|
|
76b0961e91 | ||
|
|
c0f91a50fa | ||
|
|
77fbd0a005 | ||
|
|
c9ab2c26aa | ||
|
|
b1769658f5 | ||
|
|
3518d4f6ad | ||
|
|
aa4ebd96f9 | ||
|
|
656b39a0b3 | ||
|
|
fceb600be5 | ||
|
|
47c773300a | ||
|
|
2d29749eae | ||
|
|
22a252d064 | ||
|
|
4642b28ea7 | ||
|
|
b8662f9c7f | ||
|
|
9af85f4c3b | ||
|
|
aa742f0b57 | ||
|
|
e648da98da | ||
|
|
94367b08ba | ||
|
|
97b45dc705 | ||
|
|
198768a1c7 | ||
|
|
7c27c1e7d0 | ||
|
|
9f8d8ebc2c | ||
|
|
87a312ccba | ||
|
|
838f48a861 | ||
|
|
52286f087d | ||
|
|
902d4be664 | ||
|
|
16a91f8e3c | ||
|
|
3cac5ff75e | ||
|
|
5210c16bfa | ||
|
|
8a75bccf00 | ||
|
|
5130fc6f17 | ||
|
|
b0a04f8648 | ||
|
|
60f41a738d | ||
|
|
9814bae727 | ||
|
|
63cc800cd1 | ||
|
|
47c139b916 | ||
|
|
107352c000 | ||
|
|
26cb522140 | ||
|
|
7db3009968 | ||
|
|
13e296db76 | ||
|
|
6fa992c8d3 | ||
|
|
7ca78e7178 | ||
|
|
2ee4f239d1 | ||
|
|
4ffa06fb7e | ||
|
|
a1baf97f54 | ||
|
|
2a7c57035e | ||
|
|
19e1ad7cfe | ||
|
|
2ea3da4819 | ||
|
|
3b100fce2d | ||
|
|
0c67d0565a | ||
|
|
95aeb16ca2 | ||
|
|
4770ef2df8 | ||
|
|
0ee0f5df97 | ||
|
|
4f5cad977c | ||
|
|
bed2da9b83 | ||
|
|
462fa9077a | ||
|
|
0f9749c140 | ||
|
|
acae88e618 | ||
|
|
75bf46de70 | ||
|
|
f598186574 | ||
|
|
d99aa696db | ||
|
|
790beedbb0 | ||
|
|
b1e681030b | ||
|
|
5225b477ff | ||
|
|
c53b787339 | ||
|
|
64cb4398c6 | ||
|
|
9165251a0b | ||
|
|
7e86e07fb0 | ||
|
|
02a6afd2b0 | ||
|
|
0b414b9662 | ||
|
|
012007ce7b | ||
|
|
031d501381 | ||
|
|
b0773890ea | ||
|
|
55b3b6af79 | ||
|
|
1bcfc64e13 | ||
|
|
7b4802091a | ||
|
|
7774c74826 | ||
|
|
97e58f381b | ||
|
|
015f247998 | ||
|
|
ef3923c992 | ||
|
|
7fdb1b4d1f | ||
|
|
fb83a86c17 | ||
|
|
289057f981 | ||
|
|
b48106a741 | ||
|
|
fbad0ab50a | ||
|
|
a8bf4db32d | ||
|
|
b33bad1258 | ||
|
|
29024806e5 | ||
|
|
4ef1f993a1 | ||
|
|
7297178091 | ||
|
|
3786c20dcf | ||
|
|
125fc142ba | ||
|
|
d716b32bed | ||
|
|
a56b1099aa | ||
|
|
f3f231cf70 | ||
|
|
c49ff931b1 | ||
|
|
d3c3dfda7d | ||
|
|
302c33e377 | ||
|
|
e77b1c9744 |
@@ -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
|
||||
|
||||
@@ -14,7 +14,6 @@ indent_style = tab
|
||||
|
||||
[*.{md,rst}]
|
||||
max_line_length = unset
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.sh]
|
||||
indent_size = 4
|
||||
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -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
|
||||
|
||||
4
.github/actions/install-sphinx/action.yml
vendored
4
.github/actions/install-sphinx/action.yml
vendored
@@ -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.
|
||||
|
||||
2
.github/actions/rust-toolchain/action.yml
vendored
2
.github/actions/rust-toolchain/action.yml
vendored
@@ -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
24
.github/workflows/lint-dependencies.yml
vendored
Normal 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
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -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" ]
|
||||
|
||||
@@ -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`).
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 don’t 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
139
Cargo.lock
generated
@@ -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",
|
||||
]
|
||||
|
||||
47
Cargo.toml
47
Cargo.toml
@@ -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"
|
||||
|
||||
|
||||
@@ -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
123
build.rs
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>`__'
|
||||
|
||||
@@ -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"
|
||||
|
||||
22
build_tools/supported_ubuntu_versions.py
Executable file
22
build_tools/supported_ubuntu_versions.py
Executable 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")
|
||||
)
|
||||
)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
464
contrib/debian/changelog
Normal 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
|
||||
@@ -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),
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
])
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/help_sections.rs"));
|
||||
|
||||
|
||||
15
crates/common/Cargo.toml
Normal file
15
crates/common/Cargo.toml
Normal 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
60
crates/common/src/lib.rs
Normal 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'-'))
|
||||
})
|
||||
})
|
||||
}
|
||||
22
crates/fallback/Cargo.toml
Normal file
22
crates/fallback/Cargo.toml
Normal 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
5
crates/fallback/build.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
use fish_build_helper::target_os_is_cygwin;
|
||||
|
||||
fn main() {
|
||||
rsconf::declare_cfg("cygwin", target_os_is_cygwin())
|
||||
}
|
||||
@@ -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]
|
||||
@@ -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
|
||||
|
||||
3
crates/gettext-extraction/build.rs
Normal file
3
crates/gettext-extraction/build.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_DIR");
|
||||
}
|
||||
@@ -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:?}");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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
15
crates/gettext/Cargo.toml
Normal 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
268
crates/gettext/src/lib.rs
Normal 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
|
||||
}
|
||||
@@ -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(_)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
14
crates/wchar/Cargo.toml
Normal 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
|
||||
@@ -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() {
|
||||
10
crates/widecharwidth/Cargo.toml
Normal file
10
crates/widecharwidth/Cargo.toml
Normal 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
1
debian/compat
vendored
@@ -1 +0,0 @@
|
||||
12
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
-------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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..."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
--------
|
||||
|
||||
|
||||
@@ -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'.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Synopsis
|
||||
.. synopsis::
|
||||
|
||||
begin
|
||||
[COMMANDS ...]
|
||||
[COMMANDS ...]
|
||||
end
|
||||
|
||||
.. synopsis::
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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**
|
||||
|
||||
@@ -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
|
||||
-------
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,7 +23,7 @@ Example
|
||||
::
|
||||
|
||||
for i in foo bar baz; echo $i; end
|
||||
|
||||
|
||||
# would output:
|
||||
foo
|
||||
bar
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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``
|
||||
|
||||
|
||||
@@ -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``
|
||||
|
||||
@@ -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
|
||||
-----------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
-----------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
-----
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -95,5 +95,5 @@ And here is the full list:
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
|
||||
cmds/*
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user