mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 01:21:16 -03:00
Compare commits
330 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5bc7bd5f9 | ||
|
|
2b3bd29588 | ||
|
|
0be3f9e57e | ||
|
|
2524ece2cc | ||
|
|
b975472828 | ||
|
|
20427ff1f6 | ||
|
|
5b3b825ab2 | ||
|
|
ccd3348eed | ||
|
|
845b9be1f5 | ||
|
|
400f2b130a | ||
|
|
362f7cedf6 | ||
|
|
2c959469f0 | ||
|
|
6c34bcf8f6 | ||
|
|
f510b62b7f | ||
|
|
b31387416d | ||
|
|
941a6cb434 | ||
|
|
931072f5d1 | ||
|
|
f4f9db73da | ||
|
|
9ef3f30c56 | ||
|
|
d19c927760 | ||
|
|
22e5b21f10 | ||
|
|
f0d2444769 | ||
|
|
7975060e4a | ||
|
|
354dc3d272 | ||
|
|
7640e95bd7 | ||
|
|
767115a93d | ||
|
|
f0c8788a52 | ||
|
|
a3cbb01b27 | ||
|
|
d630b4ae8a | ||
|
|
a2c5b2a567 | ||
|
|
18295f4402 | ||
|
|
443fd604cc | ||
|
|
9e022ff7cf | ||
|
|
aba927054f | ||
|
|
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 | ||
|
|
5c2073135e | ||
|
|
58cc0ad760 | ||
|
|
41387a6a3a | ||
|
|
ee94272eaf | ||
|
|
dd6000f1fd | ||
|
|
3bc896bd89 | ||
|
|
80b46fbc28 | ||
|
|
b9af3eca9f | ||
|
|
840efb76d0 | ||
|
|
8a845861f3 | ||
|
|
39d6443b6b | ||
|
|
1c9d4e77df | ||
|
|
15f9d6d279 | ||
|
|
cf2f7eb785 | ||
|
|
e7d740785d | ||
|
|
8cc25fe772 |
@@ -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
|
||||
|
||||
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
github:
|
||||
- krobelus
|
||||
7
.github/actions/install-sphinx/action.yml
vendored
7
.github/actions/install-sphinx/action.yml
vendored
@@ -9,13 +9,14 @@ runs:
|
||||
- shell: bash
|
||||
run: |
|
||||
set -x
|
||||
pip=$(command -v pip pip3 | head -1)
|
||||
sudo "$pip" install uv --break-system-packages
|
||||
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" ]
|
||||
|
||||
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -148,9 +148,6 @@ jobs:
|
||||
- name: make fish_run_tests
|
||||
run: |
|
||||
make -C build VERBOSE=1 fish_run_tests
|
||||
- name: Setup tmate session
|
||||
if: ${{ failure() }}
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
@@ -1,3 +1,97 @@
|
||||
fish 4.3.2 (released December 30, 2025)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problems identified in 4.3.0:
|
||||
|
||||
- Pre-built macOS packages failed to start due to a ``Malformed Mach-O file`` error (:issue:`12224`).
|
||||
- ``extra_functionsdir`` (usually ``vendor_functions.d``) and friends were not used (:issue:`12226`).
|
||||
- Sample config file ``~/.config/fish/config.fish/`` and config directories ``~/.config/fish/conf.d/``, ``~/.config/fish/completions/`` and ``~/.config/fish/functions/`` were recreated on every startup instead of only the first time fish runs on a system (:issue:`12230`).
|
||||
- Spurious echo of ``^[[I`` in some scenarios (:issue:`12232`).
|
||||
- Infinite prompt redraw loop on some prompts (:issue:`12233`).
|
||||
- The removal of pre-built HTML docs from tarballs revealed that cross compilation is broken because we use ``${CMAKE_BINARY_DIR}/fish_indent`` for building HTML docs.
|
||||
As a workaround, the new CMake build option ``FISH_INDENT_FOR_BUILDING_DOCS`` can be set to the path of a runnable ``fish_indent`` binary.
|
||||
|
||||
fish 4.3.1 (released December 28, 2025)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problem identified in 4.3.0:
|
||||
|
||||
- Possible crash after expanding an abbreviation (:issue:`12223`).
|
||||
|
||||
fish 4.3.0 (released December 28, 2025)
|
||||
=======================================
|
||||
|
||||
Deprecations and removed features
|
||||
---------------------------------
|
||||
- fish no longer sets user-facing :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 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>`.
|
||||
- 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)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problems identified in 4.2.0:
|
||||
|
||||
- When building from a tarball without Sphinx (that is, with ``-DBUILD_DOCS=OFF`` or when ``sphinx-build`` is not found),
|
||||
builtin man pages and help files were missing, which has been fixed (:issue:`12052`).
|
||||
- ``fish_config``'s theme selector (the "colors" tab) was broken, which has been fixed (:issue:`12053`).
|
||||
|
||||
fish 4.2.0 (released November 10, 2025)
|
||||
=======================================
|
||||
|
||||
@@ -93,7 +187,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,7 +42,6 @@ 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}"
|
||||
)
|
||||
|
||||
@@ -57,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.0"
|
||||
version = "4.3.2"
|
||||
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.0"
|
||||
version = "4.3.2"
|
||||
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"
|
||||
|
||||
|
||||
14
README.rst
14
README.rst
@@ -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,13 @@ 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_INDENT_FOR_BUILDING_DOCS - useful for cross-compilation.
|
||||
Set this to the path to the ``fish_indent`` executable to use for building HTML docs.
|
||||
By default, ``${CMAKE_BINARY_DIR}/fish_indent`` will be used.
|
||||
If that's not runnable on the compile host,
|
||||
you can build a native one with ``cargo build --bin fish_indent`` and set this to ``$PWD/target/debug/fish_indent``.
|
||||
- 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 +188,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,
|
||||
|
||||
125
build.rs
125
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};
|
||||
@@ -37,17 +40,7 @@ fn main() {
|
||||
// the source directory is the current working directory of the build script
|
||||
rsconf::set_env_value("FISH_BUILD_VERSION", version);
|
||||
|
||||
// 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,36 +66,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()),
|
||||
("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"])
|
||||
}),
|
||||
] {
|
||||
@@ -110,39 +108,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.
|
||||
@@ -209,32 +174,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
|
||||
|
||||
@@ -13,9 +13,9 @@ git_permission_failed=0
|
||||
|
||||
# First see if there is a version file (included in release tarballs),
|
||||
# then try git-describe, then default.
|
||||
if test -f version
|
||||
if test -f "$FISH_BASE_DIR"/version
|
||||
then
|
||||
VN=$(cat version) || VN="$DEF_VER"
|
||||
VN=$(cat "$FISH_BASE_DIR"/version) || VN="$DEF_VER"
|
||||
else
|
||||
if VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
||||
:
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -79,17 +82,16 @@ do_cmake() {
|
||||
&& env DESTDIR="$PKGDIR/root/" $ARM64_DEPLOY_TARGET make install;
|
||||
}
|
||||
|
||||
# Build for x86-64 but do not install; instead we will make some fat binaries inside the root.
|
||||
# Build for x86-64 but do not install; instead we will make a fat binary inside the root.
|
||||
{ cd "$PKGDIR/build_x86_64" \
|
||||
&& do_cmake -DRust_CARGO_TARGET=x86_64-apple-darwin \
|
||||
&& env $X86_64_DEPLOY_TARGET make VERBOSE=1 -j 12; }
|
||||
|
||||
# Fatten them up.
|
||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
||||
X86_FILE="$PKGDIR/build_x86_64/$(basename "$FILE")"
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
chmod 755 "$FILE"
|
||||
done
|
||||
# Fatten it up.
|
||||
FILE=$PKGDIR/root/usr/local/bin/fish
|
||||
X86_FILE=$PKGDIR/build_x86_64/$(basename "$FILE")
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
chmod 755 "$FILE"
|
||||
|
||||
if test -n "$SIGN"; then
|
||||
echo "Signing executables"
|
||||
@@ -102,9 +104,7 @@ if test -n "$SIGN"; then
|
||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
||||
fi
|
||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
||||
(set +x; rcodesign sign "${ARGS[@]}" "$FILE")
|
||||
done
|
||||
(set +x; rcodesign sign "${ARGS[@]}" "$PKGDIR"/root/usr/local/bin/fish)
|
||||
fi
|
||||
|
||||
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
|
||||
@@ -125,15 +125,13 @@ fi
|
||||
(cd "$PKGDIR/build_arm64" && env $ARM64_DEPLOY_TARGET make -j 12 fish_macapp)
|
||||
(cd "$PKGDIR/build_x86_64" && env $X86_64_DEPLOY_TARGET make -j 12 fish_macapp)
|
||||
|
||||
# Make the app's /usr/local/bin binaries universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
||||
# Make the app's /usr/local/bin/fish binary universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
||||
cd "$PKGDIR/build_arm64"
|
||||
for FILE in fish.app/Contents/Resources/base/usr/local/bin/*; do
|
||||
X86_FILE="$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")"
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
|
||||
# macho-universal-create screws up the permissions.
|
||||
chmod 755 "$FILE"
|
||||
done
|
||||
FILE=fish.app/Contents/Resources/base/usr/local/bin/fish
|
||||
X86_FILE=$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
# macho-universal-create screws up the permissions.
|
||||
chmod 755 "$FILE"
|
||||
|
||||
if test -n "$SIGN"; then
|
||||
echo "Signing app"
|
||||
|
||||
@@ -1,86 +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"
|
||||
FISH_SPHINX_BUILD_DATE=$tag_creation_date \
|
||||
$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
|
||||
$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,6 +86,22 @@ sed -i \
|
||||
CommitVersion() {
|
||||
sed -i "s/^version = \".*\"/version = \"$1\"/g" Cargo.toml
|
||||
cargo fetch --offline
|
||||
if [ "$1" = "$version" ]; then
|
||||
# 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 contrib/debian/changelog
|
||||
fi
|
||||
git add CHANGELOG.rst Cargo.toml Cargo.lock
|
||||
git commit -m "$2
|
||||
|
||||
@@ -121,7 +140,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 +168,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 +265,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 {
|
||||
@@ -255,23 +283,27 @@ EOF
|
||||
git push $remote HEAD:master
|
||||
} fi
|
||||
|
||||
milestone_number=$(
|
||||
milestone_version="$(
|
||||
if echo "$version" | grep -q '\.0$'; then
|
||||
echo "$minor_version"
|
||||
else
|
||||
echo "$version"
|
||||
fi
|
||||
)"
|
||||
milestone_number() {
|
||||
gh_api_repo milestones?state=open |
|
||||
jq '.[] | select(.title == "fish '"$version"'") | .number'
|
||||
)
|
||||
gh_api_repo milestones/$milestone_number --method PATCH \
|
||||
--raw-field state=closed
|
||||
jq --arg name "fish $1" '
|
||||
.[] | select(.title == $name) | .number
|
||||
'
|
||||
}
|
||||
gh_api_repo milestones/"$(milestone_number "$milestone_version")" \
|
||||
--method PATCH --raw-field state=closed
|
||||
|
||||
next_patch_version=$(
|
||||
echo "$version" | awk -F. '
|
||||
NF == 3 && $3 ~ /[0-9]+/ {
|
||||
printf "%s.%s.%s", $1, $2, $3+1
|
||||
}
|
||||
'
|
||||
)
|
||||
if [ -n "$next_patch_version" ]; then
|
||||
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_patch_version"
|
||||
--raw-field title="fish $next_minor_version"
|
||||
fi
|
||||
|
||||
exit
|
||||
|
||||
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
|
||||
|
||||
@@ -12,11 +12,21 @@ set(SPHINX_BUILD_DIR "${SPHINX_ROOT_DIR}/build")
|
||||
set(SPHINX_HTML_DIR "${SPHINX_ROOT_DIR}/html")
|
||||
set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
|
||||
|
||||
# sphinx-docs uses fish_indent for highlighting.
|
||||
# Prepend the output dir of fish_indent to PATH.
|
||||
set(FISH_INDENT_FOR_BUILDING_DOCS "" CACHE FILEPATH "Path to fish_indent executable for building HTML docs")
|
||||
|
||||
if(FISH_INDENT_FOR_BUILDING_DOCS)
|
||||
get_filename_component(FISH_INDENT_DIR "${FISH_INDENT_FOR_BUILDING_DOCS}" DIRECTORY)
|
||||
set(SPHINX_HTML_FISH_INDENT_PATH ${FISH_INDENT_DIR})
|
||||
set(SPHINX_HTML_FISH_INDENT_DEP)
|
||||
else()
|
||||
set(SPHINX_HTML_FISH_INDENT_PATH ${CMAKE_BINARY_DIR})
|
||||
set(SPHINX_HTML_FISH_INDENT_DEP fish_indent)
|
||||
endif()
|
||||
|
||||
add_custom_target(sphinx-docs
|
||||
mkdir -p ${SPHINX_HTML_DIR}/_static/
|
||||
COMMAND env PATH="${CMAKE_BINARY_DIR}:$$PATH"
|
||||
COMMAND env FISH_BUILD_VERSION_FILE=${CMAKE_CURRENT_BINARY_DIR}/${FBVF}
|
||||
PATH="${SPHINX_HTML_FISH_INDENT_PATH}:$$PATH"
|
||||
${SPHINX_EXECUTABLE}
|
||||
-j auto
|
||||
-q -b html
|
||||
@@ -24,10 +34,12 @@ add_custom_target(sphinx-docs
|
||||
-d "${SPHINX_ROOT_DIR}/.doctrees-html"
|
||||
"${SPHINX_SRC_DIR}"
|
||||
"${SPHINX_HTML_DIR}"
|
||||
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
|
||||
DEPENDS
|
||||
CHECK-FISH-BUILD-VERSION-FILE
|
||||
${SPHINX_SRC_DIR}/fish_indent_lexer.py
|
||||
${SPHINX_HTML_FISH_INDENT_DEP}
|
||||
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,51 +48,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")
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
480
contrib/debian/changelog
Normal file
480
contrib/debian/changelog
Normal file
@@ -0,0 +1,480 @@
|
||||
fish (4.3.2-1) stable; urgency=medium
|
||||
|
||||
* Release of new version 4.3.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.2 for details.
|
||||
|
||||
-- Johannes Altmanninger <aclopte@gmail.com> Tue, 30 Dec 2025 17:21:04 +0100
|
||||
|
||||
fish (4.3.1-1) stable; urgency=medium
|
||||
|
||||
* Release of new version 4.3.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.1 for details.
|
||||
|
||||
-- Johannes Altmanninger <aclopte@gmail.com> Sun, 28 Dec 2025 16:54:44 +0100
|
||||
|
||||
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,33 +1,23 @@
|
||||
use fish_build_helper::env_var;
|
||||
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");
|
||||
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);
|
||||
if !cfg!(clippy) {
|
||||
build_man(&man_dir, &sec1_dir);
|
||||
}
|
||||
}
|
||||
|
||||
#[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},
|
||||
};
|
||||
|
||||
use fish_build_helper::workspace_root;
|
||||
|
||||
let workspace_root = workspace_root();
|
||||
let doc_src_dir = workspace_root.join("doc_src");
|
||||
|
||||
@@ -37,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()
|
||||
@@ -63,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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user