mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 09:41:16 -03:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fa252677a | ||
|
|
e074b27abf | ||
|
|
a5727e59da | ||
|
|
4e68f8a130 | ||
|
|
417755b6a7 | ||
|
|
ef30feda12 | ||
|
|
20e3ed23b7 | ||
|
|
7bfdb8460d | ||
|
|
8d9d5816ed | ||
|
|
97f6129dea | ||
|
|
c19de5aeb9 | ||
|
|
874fba1108 | ||
|
|
695f225cb4 | ||
|
|
9f36adb731 | ||
|
|
3ff699d7ea | ||
|
|
4b6ad751e8 | ||
|
|
8dd90085b6 | ||
|
|
47396e78ce | ||
|
|
77a038541a | ||
|
|
84dbdf4e2a | ||
|
|
0a50ba9ef5 | ||
|
|
8b317a192b | ||
|
|
42decbf1da | ||
|
|
79b0d24701 | ||
|
|
1f6cd5fc2d | ||
|
|
635525be96 | ||
|
|
280791c0f5 | ||
|
|
91faa1be49 | ||
|
|
24e529ea07 | ||
|
|
595bfda331 | ||
|
|
0f358756a2 | ||
|
|
0ace46d127 | ||
|
|
a143a67318 | ||
|
|
047b9d96a0 | ||
|
|
c942b034ba | ||
|
|
0f1caacae4 | ||
|
|
f332cdc757 | ||
|
|
c6912c6721 | ||
|
|
678edbd223 | ||
|
|
1a78407efe | ||
|
|
3ecf1bc46d | ||
|
|
4d99e51e62 | ||
|
|
a9576d44e3 | ||
|
|
2c0e912fe1 | ||
|
|
1f96e58852 | ||
|
|
03f4bf262a | ||
|
|
bb61c948af | ||
|
|
fa59a736bf | ||
|
|
97dc8f69d9 | ||
|
|
57753474e4 | ||
|
|
d5f4cedeb5 | ||
|
|
ec4700308e | ||
|
|
1d5ae08696 | ||
|
|
bb5b583d63 | ||
|
|
7d80a599f2 | ||
|
|
284d8fa3d1 | ||
|
|
a03f52add0 | ||
|
|
89fa81123b |
@@ -1,6 +1,7 @@
|
||||
image: alpine/edge
|
||||
packages:
|
||||
- cargo
|
||||
- clang17-libclang
|
||||
- cmake
|
||||
- ninja
|
||||
- pcre2-dev
|
||||
@@ -23,4 +24,4 @@ tasks:
|
||||
ninja
|
||||
- test: |
|
||||
cd fish-shell/build
|
||||
ninja fish_run_tests
|
||||
ninja test
|
||||
|
||||
@@ -20,4 +20,4 @@ tasks:
|
||||
ninja
|
||||
- test: |
|
||||
cd fish/build
|
||||
ninja fish_run_tests
|
||||
ninja test
|
||||
|
||||
@@ -5,10 +5,10 @@ packages:
|
||||
- gettext
|
||||
- gmake
|
||||
- llvm
|
||||
- terminfo-db
|
||||
- ninja
|
||||
- pcre2
|
||||
- py311-pexpect
|
||||
- py311-sphinx
|
||||
- python
|
||||
- rust
|
||||
- tmux
|
||||
@@ -27,4 +27,4 @@ tasks:
|
||||
ninja
|
||||
- test: |
|
||||
cd fish-shell/build
|
||||
ninja fish_run_tests
|
||||
ninja test
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
image: openbsd/latest
|
||||
packages:
|
||||
- cmake
|
||||
- gcc
|
||||
- gettext
|
||||
- gmake
|
||||
- llvm
|
||||
- ninja
|
||||
- pcre2
|
||||
- py3-pexpect
|
||||
- py3-sphinx
|
||||
- python
|
||||
- rust
|
||||
- tmux
|
||||
sources:
|
||||
- https://github.com/fish-shell/fish-shell
|
||||
tasks:
|
||||
- build: |
|
||||
cd fish-shell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -GNinja .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_DATADIR=share \
|
||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||
ninja
|
||||
- test: |
|
||||
cd fish-shell/build
|
||||
ninja fish_run_tests
|
||||
37
.cirrus.yml
37
.cirrus.yml
@@ -8,10 +8,18 @@ linux_task:
|
||||
container: &step
|
||||
image: ghcr.io/krobelus/fish-ci/alpine:latest
|
||||
memory: 4GB
|
||||
- name: ubuntu-oldest-supported
|
||||
- name: jammy
|
||||
container:
|
||||
<<: *step
|
||||
image: ghcr.io/krobelus/fish-ci/ubuntu-oldest-supported:latest
|
||||
image: ghcr.io/krobelus/fish-ci/jammy:latest
|
||||
# - name: jammy-asan
|
||||
# container:
|
||||
# <<: *step
|
||||
# image: ghcr.io/krobelus/fish-ci/jammy-asan:latest
|
||||
# - name: focal-32bit
|
||||
# container:
|
||||
# <<: *step
|
||||
# image: ghcr.io/krobelus/fish-ci/focal-32bit:latest
|
||||
tests_script:
|
||||
# cirrus at times gives us 32 procs and 2 GB of RAM
|
||||
# Unrestriced parallelism results in OOM
|
||||
@@ -23,11 +31,32 @@ linux_task:
|
||||
- ninja fish_run_tests
|
||||
only_if: $CIRRUS_REPO_OWNER == 'fish-shell'
|
||||
|
||||
linux_arm_task:
|
||||
matrix:
|
||||
- name: focal-arm64
|
||||
arm_container:
|
||||
image: ghcr.io/fish-shell/fish-ci/focal-arm64
|
||||
- name: jammy-armv7-32bit
|
||||
arm_container:
|
||||
image: ghcr.io/fish-shell/fish-ci/jammy-armv7-32bit
|
||||
tests_script:
|
||||
# cirrus at times gives us 32 procs and 2 GB of RAM
|
||||
# Unrestriced parallelism results in OOM
|
||||
- lscpu || true
|
||||
- (cat /proc/meminfo | grep MemTotal) || true
|
||||
- mkdir build && cd build
|
||||
- FISH_TEST_MAX_CONCURRENCY=6 cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..
|
||||
- ninja -j 6 fish
|
||||
- file ./fish
|
||||
- ninja fish_run_tests
|
||||
# CI task disabled during RIIR transition
|
||||
only_if: false && $CIRRUS_REPO_OWNER == 'fish-shell'
|
||||
|
||||
freebsd_task:
|
||||
matrix:
|
||||
- name: FreeBSD Stable
|
||||
- name: FreeBSD 14
|
||||
freebsd_instance:
|
||||
image: freebsd-14-3-release-amd64-ufs # updatecli.d/cirrus-freebsd.yml
|
||||
image: freebsd-14-3-release-amd64-ufs
|
||||
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
|
||||
|
||||
41
.github/actions/install-dependencies/action.yml
vendored
41
.github/actions/install-dependencies/action.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Install dependencies for system tests
|
||||
|
||||
inputs:
|
||||
include_sphinx:
|
||||
description: Whether to install Sphinx
|
||||
required: true
|
||||
default: false
|
||||
include_pcre:
|
||||
description: Whether to install the PCRE library
|
||||
required: false
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: bash
|
||||
env:
|
||||
include_pcre: ${{ inputs.include_pcre }}
|
||||
run: |
|
||||
set -x
|
||||
: "optional dependencies"
|
||||
sudo apt install \
|
||||
gettext \
|
||||
$(if $include_pcre; then echo libpcre2-dev; fi) \
|
||||
;
|
||||
: "system test dependencies"
|
||||
sudo apt install \
|
||||
diffutils $(: "for diff") \
|
||||
git \
|
||||
gettext \
|
||||
less \
|
||||
$(if ${{ inputs.include_pcre }}; then echo libpcre2-dev; fi) \
|
||||
python3-pexpect \
|
||||
tmux \
|
||||
wget \
|
||||
;
|
||||
- uses: ./.github/actions/install-sphinx
|
||||
if: ${{ inputs.include_sphinx == 'true' }}
|
||||
14
.github/actions/install-sphinx-markdown-builder/action.yml
vendored
Normal file
14
.github/actions/install-sphinx-markdown-builder/action.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Install sphinx-markdown-builder
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: bash
|
||||
run: |
|
||||
set -x
|
||||
commit=b259de1dc97573a71470a1d71c3d83535934136b
|
||||
pip install git+https://github.com/krobelus/sphinx-markdown-builder@"$commit"
|
||||
python -c 'import sphinx_markdown_builder'
|
||||
22
.github/actions/install-sphinx/action.yml
vendored
22
.github/actions/install-sphinx/action.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: Install sphinx
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: bash
|
||||
run: |
|
||||
set -x
|
||||
pip=$(command -v pip pip3 | head -1)
|
||||
sudo "$pip" install uv --break-system-packages
|
||||
# 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
|
||||
# Install globally.
|
||||
sudo $uv pip install --group=dev --system --break-system-packages
|
||||
# Smoke test.
|
||||
python -c 'import sphinx; import sphinx_markdown_builder'
|
||||
41
.github/actions/rust-toolchain/action.yml
vendored
41
.github/actions/rust-toolchain/action.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Rust Toolchain
|
||||
|
||||
inputs:
|
||||
toolchain_channel:
|
||||
description: Either "stable" or "msrv"
|
||||
required: true
|
||||
targets:
|
||||
description: Comma-separated list of target triples to install for this toolchain
|
||||
required: false
|
||||
components:
|
||||
description: Comma-separated list of components to be additionally installed
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set toolchain
|
||||
env:
|
||||
toolchain_channel: ${{ inputs.toolchain_channel }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
toolchain=$(
|
||||
case "$toolchain_channel" in
|
||||
(stable) echo 1.91 ;; # updatecli.d/rust.yml
|
||||
(msrv) echo 1.85 ;; # updatecli.d/rust.yml
|
||||
(*)
|
||||
printf >&2 "error: unsupported toolchain channel %s" "$toolchain_channel"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
)
|
||||
printf 'TOOLCHAIN=%s\n' "$toolchain" >>"$GITHUB_ENV"
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ env.TOOLCHAIN }}
|
||||
targets: ${{ inputs.targets }}
|
||||
components: ${{ inputs.components }}
|
||||
@@ -14,8 +14,7 @@ permissions:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: ./.github/actions/rust-toolchain
|
||||
- uses: dtolnay/rust-toolchain@1.70
|
||||
with:
|
||||
toolchain_channel: "msrv"
|
||||
targets: ${{ inputs.targets }}
|
||||
components: ${{ inputs.components }}
|
||||
components: ${{ inputs.components}}
|
||||
|
||||
@@ -14,8 +14,7 @@ permissions:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: ./.github/actions/rust-toolchain
|
||||
- uses: dtolnay/rust-toolchain@1.90
|
||||
with:
|
||||
toolchain_channel: "stable"
|
||||
targets: ${{ inputs.targets }}
|
||||
components: ${{ inputs.components }}
|
||||
|
||||
64
.github/workflows/build_docker_images.yml
vendored
64
.github/workflows/build_docker_images.yml
vendored
@@ -1,64 +0,0 @@
|
||||
name: Build Docker test images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'docker/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docker-builds
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
NAMESPACE: fish-ci
|
||||
|
||||
jobs:
|
||||
docker-build:
|
||||
if: github.repository_owner == 'fish-shell'
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: alpine
|
||||
- os: ubuntu-latest
|
||||
target: ubuntu-oldest-supported
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Login to Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.NAMESPACE }}/${{ matrix.target }}
|
||||
flavor: |
|
||||
latest=true
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: docker/context
|
||||
push: true
|
||||
file: docker/${{ matrix.target }}.Dockerfile
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
1
.github/workflows/lockthreads.yml
vendored
1
.github/workflows/lockthreads.yml
vendored
@@ -12,7 +12,6 @@ permissions:
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
if: github.repository_owner == 'fish-shell'
|
||||
permissions:
|
||||
issues: write # for dessant/lock-threads to lock issues
|
||||
pull-requests: write # for dessant/lock-threads to lock PRs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Test
|
||||
name: make fish_run_tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -11,17 +11,18 @@ permissions:
|
||||
|
||||
jobs:
|
||||
ubuntu:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/rust-toolchain@oldest-supported
|
||||
- name: Install deps
|
||||
uses: ./.github/actions/install-dependencies
|
||||
with:
|
||||
include_sphinx: true
|
||||
- name: Generate a locale that uses a comma as decimal separator.
|
||||
run: |
|
||||
sudo apt install gettext libpcre2-dev python3-pexpect python3-sphinx tmux
|
||||
# Generate a locale that uses a comma as decimal separator.
|
||||
sudo locale-gen fr_FR.UTF-8
|
||||
- uses: ./.github/actions/install-sphinx-markdown-builder
|
||||
- name: cmake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
@@ -42,20 +43,18 @@ jobs:
|
||||
git --no-pager diff --exit-code || { echo 'There are uncommitted changes after regenerating the gettext PO files. Make sure to update them via `build_tools/update_translations.fish` after changing source files.'; exit 1; }
|
||||
|
||||
ubuntu-32bit-static-pcre2:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/rust-toolchain@oldest-supported
|
||||
with:
|
||||
targets: "i586-unknown-linux-gnu"
|
||||
targets: "i586-unknown-linux-gnu" # rust-toolchain wants this comma-separated
|
||||
- name: Install deps
|
||||
uses: ./.github/actions/install-dependencies
|
||||
with:
|
||||
include_pcre: false
|
||||
include_sphinx: false
|
||||
- name: Install g++-multilib
|
||||
run: |
|
||||
sudo apt install g++-multilib
|
||||
sudo apt update
|
||||
sudo apt install gettext python3-pexpect g++-multilib tmux
|
||||
- name: cmake
|
||||
env:
|
||||
CFLAGS: "-m32"
|
||||
@@ -70,6 +69,7 @@ jobs:
|
||||
make -C build VERBOSE=1 fish_run_tests
|
||||
|
||||
ubuntu-asan:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
# Rust has two different memory sanitizers of interest; they can't be used at the same time:
|
||||
@@ -79,6 +79,7 @@ jobs:
|
||||
#
|
||||
RUSTFLAGS: "-Zsanitizer=address"
|
||||
# RUSTFLAGS: "-Zsanitizer=memory -Zsanitizer-memory-track-origins"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# All -Z options require running nightly
|
||||
@@ -88,11 +89,8 @@ jobs:
|
||||
# this is comma-separated
|
||||
components: rust-src
|
||||
- name: Install deps
|
||||
uses: ./.github/actions/install-dependencies
|
||||
with:
|
||||
include_sphinx: false
|
||||
- name: Install llvm
|
||||
run: |
|
||||
sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
||||
sudo apt install llvm # for llvm-symbolizer
|
||||
- name: cmake
|
||||
env:
|
||||
@@ -121,8 +119,38 @@ jobs:
|
||||
export LSAN_OPTIONS="$LSAN_OPTIONS:suppressions=$PWD/build_tools/lsan_suppressions.txt"
|
||||
make -C build VERBOSE=1 fish_run_tests
|
||||
|
||||
# Our clang++ tsan builds are not recognizing safe rust patterns (such as the fact that Drop
|
||||
# cannot be called while a thread is using the object in question). Rust has its own way of
|
||||
# running TSAN, but for the duration of the port from C++ to Rust, we'll keep this disabled.
|
||||
|
||||
# ubuntu-threadsan:
|
||||
#
|
||||
# runs-on: ubuntu-latest
|
||||
#
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: ./.github/actions/rust-toolchain@oldest-supported
|
||||
# - name: Install deps
|
||||
# run: |
|
||||
# sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
||||
# - name: cmake
|
||||
# env:
|
||||
# FISH_CI_SAN: 1
|
||||
# CC: clang
|
||||
# run: |
|
||||
# mkdir build && cd build
|
||||
# cmake ..
|
||||
# - name: make
|
||||
# run: |
|
||||
# make
|
||||
# - name: make fish_run_tests
|
||||
# run: |
|
||||
# make -C build fish_run_tests
|
||||
|
||||
macos:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
env:
|
||||
# macOS runners keep having issues loading Cargo.toml dependencies from git (GitHub) instead
|
||||
# of crates.io, so give this a try. It's also sometimes significantly faster on all platforms.
|
||||
@@ -135,45 +163,14 @@ jobs:
|
||||
# --break-system-packages because homebrew has now declared itself "externally managed".
|
||||
# this is CI so we don't actually care.
|
||||
sudo pip3 install --break-system-packages pexpect
|
||||
brew install gettext tmux
|
||||
- uses: ./.github/actions/install-sphinx
|
||||
brew install tmux
|
||||
- name: cmake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
FISH_TEST_MAX_CONCURRENCY=1 \
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
- name: make
|
||||
run: |
|
||||
make -C build VERBOSE=1
|
||||
- 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
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
msystem: MSYS
|
||||
- name: Install deps
|
||||
# Not using setup-msys2 `install` option to make it easier to copy/paste
|
||||
run: |
|
||||
pacman --noconfirm -S --needed git rust
|
||||
- name: cargo build
|
||||
run: |
|
||||
cargo build
|
||||
- name: smoketest
|
||||
# We can't run `build_tools/check.sh` yet, there are just too many failures
|
||||
# so this is just a quick check to make sure that fish can swim
|
||||
run: |
|
||||
set -x
|
||||
[ "$(target/debug/fish.exe -c 'echo (math 1 + 1)')" = 2 ]
|
||||
cargo test
|
||||
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@@ -41,8 +41,8 @@ jobs:
|
||||
# Workaround for https://github.com/actions/checkout/issues/882
|
||||
ref: ${{ inputs.version }}
|
||||
- name: Install dependencies
|
||||
run: sudo apt install cmake gettext ninja-build python3-pip
|
||||
- uses: ./.github/actions/install-sphinx
|
||||
run: sudo apt install cmake gettext ninja-build python3-pip python3-sphinx
|
||||
- uses: ./.github/actions/install-sphinx-markdown-builder
|
||||
- name: Create tarball
|
||||
run: |
|
||||
set -x
|
||||
@@ -52,10 +52,7 @@ jobs:
|
||||
# Need history since the last release (i.e. tag) for stats.
|
||||
git fetch --tags
|
||||
git fetch --unshallow
|
||||
gpg_public_key_url=https://github.com/${{ github.actor }}.gpg
|
||||
curl -sS "$gpg_public_key_url" | grep 'PGP PUBLIC KEY BLOCK' -A5
|
||||
FISH_GPG_PUBLIC_KEY_URL=$gpg_public_key_url \
|
||||
sh -x ./build_tools/release-notes.sh >"$relnotes"
|
||||
sh -x ./build_tools/release-notes.sh >"$relnotes"
|
||||
# Delete title
|
||||
sed -n 1p "$relnotes" | grep -q "^## fish .*"
|
||||
sed -n 2p "$relnotes" | grep -q '^$'
|
||||
@@ -71,7 +68,7 @@ jobs:
|
||||
|
||||
packages-for-linux:
|
||||
needs: [is-release-tag]
|
||||
name: Build single-file fish for Linux
|
||||
name: Build single-file fish for Linux (experimental)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -83,8 +80,7 @@ jobs:
|
||||
with:
|
||||
targets: x86_64-unknown-linux-musl,aarch64-unknown-linux-musl
|
||||
- name: Install dependencies
|
||||
run: sudo apt install crossbuild-essential-arm64 gettext musl-tools
|
||||
- uses: ./.github/actions/install-sphinx
|
||||
run: sudo apt install crossbuild-essential-arm64 gettext musl-tools python3-sphinx
|
||||
- name: Build statically-linked executables
|
||||
run: |
|
||||
set -x
|
||||
@@ -147,12 +143,13 @@ jobs:
|
||||
# Workaround for https://github.com/actions/checkout/issues/882
|
||||
ref: ${{ inputs.version }}
|
||||
- name: Install Rust
|
||||
uses: ./.github/actions/rust-toolchain@oldest-supported
|
||||
with:
|
||||
targets: x86_64-apple-darwin
|
||||
- name: Install Rust Stable
|
||||
uses: ./.github/actions/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-apple-darwin,x86_64-apple-darwin
|
||||
- name: Install dependencies
|
||||
run: brew install gettext
|
||||
- uses: ./.github/actions/install-sphinx
|
||||
targets: aarch64-apple-darwin
|
||||
- name: Build and codesign
|
||||
run: |
|
||||
die() { echo >&2 "$*"; exit 1; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Lint
|
||||
name: Rust checks
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -6,39 +6,25 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
format:
|
||||
rustfmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
- name: install dependencies
|
||||
run: pip install ruff
|
||||
- name: build fish
|
||||
run: cargo build
|
||||
- name: check format
|
||||
run: PATH="target/debug:$PATH" build_tools/style.fish --all --check
|
||||
- name: check rustfmt
|
||||
run: find build.rs crates src -type f -name '*.rs' | xargs rustfmt --check
|
||||
- name: cargo fmt
|
||||
run: cargo fmt --check
|
||||
|
||||
|
||||
clippy:
|
||||
clippy-stable:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- rust_version: "stable"
|
||||
features: ""
|
||||
- rust_version: "stable"
|
||||
features: "--no-default-features"
|
||||
- rust_version: "msrv"
|
||||
features: ""
|
||||
features: ["", "--no-default-features"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/rust-toolchain
|
||||
- uses: ./.github/actions/rust-toolchain@stable
|
||||
with:
|
||||
toolchain_channel: ${{ matrix.rust_version }}
|
||||
components: clippy
|
||||
- name: Install deps
|
||||
run: |
|
||||
@@ -46,6 +32,19 @@ jobs:
|
||||
- name: cargo clippy
|
||||
run: cargo clippy --workspace --all-targets ${{ matrix.features }} -- --deny=warnings
|
||||
|
||||
clippy-msrv:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/rust-toolchain@oldest-supported
|
||||
with:
|
||||
components: clippy
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt install gettext
|
||||
- name: cargo clippy
|
||||
run: cargo clippy --workspace --all-targets -- --deny=warnings
|
||||
|
||||
rustdoc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,6 +7,7 @@
|
||||
*.DS_Store
|
||||
*.a
|
||||
*.app
|
||||
*.d
|
||||
*.dll
|
||||
*.dylib
|
||||
*.exe
|
||||
@@ -104,6 +105,3 @@ target/
|
||||
|
||||
# JetBrains editors.
|
||||
.idea/
|
||||
|
||||
# AI slop
|
||||
.claude/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
edition = "2024"
|
||||
@@ -1,70 +1,5 @@
|
||||
fish 4.2.0 (released November 10, 2025)
|
||||
=======================================
|
||||
|
||||
Notable improvements and fixes
|
||||
------------------------------
|
||||
- History-based autosuggestions now include multi-line commands.
|
||||
- A :ref:`transient prompt <transient-prompt>` containing more lines than the final prompt will now be cleared properly (:issue:`11875`).
|
||||
- Taiwanese Chinese translations have been added.
|
||||
- French translations have been supplemented (:issue:`11842`).
|
||||
|
||||
Deprecations and removed features
|
||||
---------------------------------
|
||||
- fish now assumes UTF-8 for character encoding even if the system does not have a UTF-8 locale.
|
||||
Input bytes which are not valid UTF-8 are still round-tripped correctly.
|
||||
For example, file paths using legacy encodings can still be used,
|
||||
but may be rendered differently on the command line.
|
||||
- On systems where no multi-byte locale is available,
|
||||
fish will no longer fall back to using ASCII replacements for :ref:`Unicode characters <term-compat-unicode-codepoints>` such as "…".
|
||||
|
||||
Interactive improvements
|
||||
------------------------
|
||||
- The title of the terminal tab can now be set separately from the window title by defining the :doc:`fish_tab_title <cmds/fish_tab_title>` function (:issue:`2692`).
|
||||
- fish now hides the portion of a multiline prompt that is scrolled out of view due to a huge command line. This prevents duplicate lines after repainting with partially visible prompt (:issue:`11911`).
|
||||
- :doc:`fish_config prompt <cmds/fish_config>`'s ``choose`` and ``save`` subcommands have been taught to reset :doc:`fish_mode_prompt <cmds/fish_mode_prompt>` in addition to the other prompt functions (:issue:`11937`).
|
||||
- fish no longer force-disables mouse capture (DECSET/DECRST 1000),
|
||||
so you can use those commands
|
||||
to let mouse clicks move the cursor or select completions items (:issue:`4918`).
|
||||
- The :kbd:`alt-p` binding no longer adds a redundant space to the command line.
|
||||
- When run as a login shell on macOS, fish now sets :envvar:`MANPATH` correctly when that variable was already present in the environment (:issue:`10684`).
|
||||
- A Windows-specific case of the :doc:`web-based config <cmds/fish_config>` failing to launch has been fixed (:issue:`11805`).
|
||||
- A MSYS2-specific workaround for Konsole and WezTerm has been added,
|
||||
to prevent them from using the wrong working directory when opening new tabs (:issue:`11981`).
|
||||
|
||||
For distributors and developers
|
||||
-------------------------------
|
||||
- Release tags and source code tarballs are GPG-signed again (:issue:`11996`).
|
||||
- Documentation in release tarballs is now built with the latest version of Sphinx,
|
||||
which means that pre-built man pages include :ref:`OSC 8 hyperlinks <term-compat-osc-8>`.
|
||||
- The Sphinx dependency is now specified in ``pyproject.toml``,
|
||||
which allows you to use `uv <https://github.com/astral-sh/uv>`__ to provide Sphinx for building documentation (e.g. ``uv run cargo install --path .``).
|
||||
- The minimum supported Rust version (MSRV) has been updated to 1.85.
|
||||
- The standalone build mode has been made the default.
|
||||
This means that the files in ``$CMAKE_INSTALL_PREFIX/share/fish`` will not be used anymore, except for HTML docs.
|
||||
As a result, future upgrades will no longer break running shells
|
||||
if one of fish's internal helper functions has been changed in the updated version.
|
||||
For now, the data files are still installed redundantly,
|
||||
to prevent upgrades from breaking already-running shells (:issue:`11921`).
|
||||
To reverse this change (which should not be necessary),
|
||||
patch out the ``embed-data`` feature from ``cmake/Rust.cmake``.
|
||||
This option will be removed in future.
|
||||
- OpenBSD 7.8 revealed an issue with fish's approach for displaying builtin man pages, which has been fixed.
|
||||
|
||||
Regression fixes:
|
||||
-----------------
|
||||
- (from 4.1.0) Fix the :doc:`web-based config <cmds/fish_config>` for Python 3.9 and older (:issue:`12039`).
|
||||
- (from 4.1.0) Correct wrong terminal modes set by ``fish -c 'read; cat`` (:issue:`12024`).
|
||||
- (from 4.1.0) On VTE-based terminals, stop redrawing the prompt on resize again, to avoid glitches.
|
||||
- (from 4.1.0) On MSYS2, fix saving/loading of universal variables (:issue:`11948`).
|
||||
- (from 4.1.0) Fix error using ``man`` for the commands ``!`` ``.`` ``:`` ``[`` ``{`` (:issue:`11955`).
|
||||
- (from 4.1.0) Fix build issues on illumos systems (:issue:`11982`).
|
||||
- (from 4.1.0) Fix crash on invalid :doc:`function <cmds/function>` command (:issue:`11912`).
|
||||
- (from 4.0.0) Fix build on SPARC and MIPS Linux by disabling ``SIGSTKFLT``.
|
||||
- (from 4.0.0) Fix crash when passing negative PIDs to builtin :doc:`wait <cmds/wait>` (:issue:`11929`).
|
||||
- (from 4.0.0) On Linux, fix :doc:`status fish-path <cmds/status>` output when fish has been reinstalled since it was started.
|
||||
|
||||
fish 4.1.2 (released October 7, 2025)
|
||||
=====================================
|
||||
fish 4.1.2 (released October 07, 2025)
|
||||
======================================
|
||||
|
||||
This release fixes the following regressions identified in 4.1.0:
|
||||
|
||||
@@ -923,7 +858,7 @@ Notable improvements and fixes
|
||||
|
||||
which expands ``!!`` to the last history item, anywhere on the command line, mimicking other shells' history expansion.
|
||||
|
||||
See :doc:`the documentation <cmds/abbr>` for more.
|
||||
See :ref:`the documentation <cmd-abbr>` for more.
|
||||
- ``path`` gained a new ``mtime`` subcommand to print the modification time stamp for files. For example, this can be used to handle cache file ages (:issue:`9057`)::
|
||||
|
||||
> touch foo
|
||||
@@ -1348,7 +1283,7 @@ Scripting improvements
|
||||
two
|
||||
'blue '
|
||||
|
||||
- ``$fish_user_paths`` is now automatically deduplicated to fix a common user error of appending to it in config.fish when it is universal (:issue:`8117`). :doc:`fish_add_path <cmds/fish_add_path>` remains the recommended way to add to $PATH.
|
||||
- ``$fish_user_paths`` is now automatically deduplicated to fix a common user error of appending to it in config.fish when it is universal (:issue:`8117`). :ref:`fish_add_path <cmd-fish_add_path>` remains the recommended way to add to $PATH.
|
||||
- ``return`` can now be used outside functions. In scripts, it does the same thing as ``exit``. In interactive mode,it sets ``$status`` without exiting (:issue:`8148`).
|
||||
- An oversight prevented all syntax checks from running on commands given to ``fish -c`` (:issue:`8171`). This includes checks such as ``exec`` not being allowed in a pipeline, and ``$$`` not being a valid variable. Generally, another error was generated anyway.
|
||||
- ``fish_indent`` now correctly reformats tokens that end with a backslash followed by a newline (:issue:`8197`).
|
||||
|
||||
@@ -28,24 +28,6 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
# This defines the FBVF variable.
|
||||
include(Version)
|
||||
|
||||
# Set up the docs.
|
||||
include(cmake/Docs.cmake)
|
||||
|
||||
# Tell Cargo where our build directory is so it can find Cargo.toml.
|
||||
set(VARS_FOR_CARGO
|
||||
"FISH_CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}"
|
||||
"PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
"DOCDIR=${CMAKE_INSTALL_FULL_DOCDIR}"
|
||||
"DATADIR=${CMAKE_INSTALL_FULL_DATADIR}"
|
||||
"SYSCONFDIR=${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||
"BINDIR=${CMAKE_INSTALL_FULL_BINDIR}"
|
||||
"CARGO_TARGET_DIR=${FISH_RUST_BUILD_DIR}"
|
||||
"CARGO_BUILD_RUSTC=${Rust_COMPILER}"
|
||||
"${FISH_PCRE2_BUILDFLAG}"
|
||||
"RUSTFLAGS=$ENV{RUSTFLAGS} ${rust_debugflags}"
|
||||
"FISH_SPHINX=${SPHINX_EXECUTABLE}"
|
||||
)
|
||||
|
||||
# Let fish pick up when we're running out of the build directory without installing
|
||||
get_filename_component(REAL_CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}" REALPATH)
|
||||
get_filename_component(REAL_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH)
|
||||
@@ -89,6 +71,9 @@ create_target(fish_indent)
|
||||
# Define fish_key_reader.
|
||||
create_target(fish_key_reader)
|
||||
|
||||
# Set up the docs.
|
||||
include(cmake/Docs.cmake)
|
||||
|
||||
# Set up tests.
|
||||
include(cmake/Tests.cmake)
|
||||
|
||||
|
||||
130
CONTRIBUTING.rst
130
CONTRIBUTING.rst
@@ -71,7 +71,7 @@ Completion scripts should
|
||||
|
||||
1. Use as few dependencies as possible - try to use fish's builtins like ``string`` instead of ``grep`` and ``awk``,
|
||||
use ``python`` to read json instead of ``jq`` (because it's already a soft dependency for fish's tools)
|
||||
2. If it uses a common unix tool, use POSIX-compatible invocations - ideally it would work on GNU/Linux, macOS, the BSDs and other systems
|
||||
2. If it uses a common unix tool, use posix-compatible invocations - ideally it would work on GNU/Linux, macOS, the BSDs and other systems
|
||||
3. Option and argument descriptions should be kept short.
|
||||
The shorter the description, the more likely it is that fish can use more columns.
|
||||
4. Function names should start with ``__fish``, and functions should be kept in the completion file unless they're used elsewhere.
|
||||
@@ -100,18 +100,33 @@ The builtins and various functions shipped with fish are documented in doc_src/c
|
||||
Code Style
|
||||
==========
|
||||
|
||||
For formatting, we use:
|
||||
To ensure your changes conform to the style rules run
|
||||
|
||||
::
|
||||
|
||||
build_tools/style.fish
|
||||
|
||||
before committing your change. That will run our autoformatters:
|
||||
|
||||
- ``rustfmt`` for Rust
|
||||
- ``fish_indent`` (shipped with fish) for fish script
|
||||
- ``ruff format`` for Python
|
||||
- ``black`` for python
|
||||
|
||||
To reformat files, there is a script
|
||||
If you’ve already committed your changes that’s okay since it will then
|
||||
check the files in the most recent commit. This can be useful after
|
||||
you’ve merged another person’s change and want to check that it’s style
|
||||
is acceptable. However, in that case it will run ``clang-format`` to
|
||||
ensure the entire file, not just the lines modified by the commit,
|
||||
conform to the style.
|
||||
|
||||
If you want to check the style of the entire code base run
|
||||
|
||||
::
|
||||
|
||||
build_tools/style.fish --all
|
||||
build_tools/style.fish somefile.rs some.fish
|
||||
|
||||
That command will refuse to restyle any files if you have uncommitted
|
||||
changes.
|
||||
|
||||
Fish Script Style Guide
|
||||
-----------------------
|
||||
@@ -163,10 +178,10 @@ made to run fish_indent via e.g.
|
||||
(add-hook 'fish-mode-hook (lambda ()
|
||||
(add-hook 'before-save-hook 'fish_indent-before-save)))
|
||||
|
||||
Minimum Supported Rust Version (MSRV) Policy
|
||||
--------------------------------------------
|
||||
Rust Style Guide
|
||||
----------------
|
||||
|
||||
We support at least the version of ``rustc`` available in Debian Stable.
|
||||
Use ``cargo fmt`` and ``cargo clippy``. Clippy warnings can be turned off if there's a good reason to.
|
||||
|
||||
Testing
|
||||
=======
|
||||
@@ -181,47 +196,78 @@ 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
|
||||
regressions in the future (i.e., we don’t reintroduce the bug).
|
||||
|
||||
Unit tests live next to the implementation in Rust source files, in inline submodules (``mod tests {}``).
|
||||
The tests can be found in three places:
|
||||
|
||||
System tests live in ``tests/``:
|
||||
- src/tests for unit tests.
|
||||
- tests/checks for script tests, run by `littlecheck <https://github.com/ridiculousfish/littlecheck>`__
|
||||
- tests/pexpects for interactive tests using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
|
||||
|
||||
- ``tests/checks`` are run by `littlecheck <https://github.com/ridiculousfish/littlecheck>`__
|
||||
and test noninteractive (script) behavior,
|
||||
except for ``tests/checks/tmux-*`` which test interactive scenarios.
|
||||
- ``tests/pexpects`` tests interactive scenarios using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
|
||||
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests. The syntax is fairly self-explanatory. It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
|
||||
If your littlecheck test has a specific dependency, use ``# REQUIRE: ...`` with a posix sh script.
|
||||
|
||||
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests.
|
||||
The syntax is fairly self-explanatory.
|
||||
It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
|
||||
If your littlecheck test has a specific dependency, use ``# REQUIRE: ...`` with a POSIX sh script.
|
||||
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in tests/pexpect_helper.py, in case you need to modify something there.
|
||||
|
||||
The pexpect tests are written in Python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity.
|
||||
The runner is in tests/pexpect_helper.py, in case you need to modify something there.
|
||||
|
||||
These tests can be run via the tests/test_driver.py Python script, which will set up the environment.
|
||||
These tests can be run via the tests/test_driver.py python script, which will set up the environment.
|
||||
It sets up a temporary $HOME and also uses it as the current directory, so you do not need to create a temporary directory in them.
|
||||
|
||||
If you need a command to do something weird to test something, maybe add it to the ``fish_test_helper`` binary (in ``tests/fish_test_helper.c``).
|
||||
If you need a command to do something weird to test something, maybe add it to the ``fish_test_helper`` binary (in tests/fish_test_helper.c), or see if it can already do it.
|
||||
|
||||
Local testing
|
||||
-------------
|
||||
|
||||
The tests can be run on your local system::
|
||||
The tests can be run on your local computer on all operating systems.
|
||||
|
||||
cargo build
|
||||
# Run unit tests
|
||||
cargo test
|
||||
# Run system tests
|
||||
tests/test_driver.py target/debug
|
||||
# Run a specific system test.
|
||||
tests/test_driver.py target/debug tests/checks/abbr.fish
|
||||
::
|
||||
|
||||
cmake path/to/fish-shell
|
||||
make fish_run_tests
|
||||
|
||||
Or you can run them on a fish, without involving cmake::
|
||||
|
||||
cargo build
|
||||
cargo test # for the unit tests
|
||||
tests/test_driver.py target/debug # for the script and interactive tests
|
||||
|
||||
Here, the first argument to test_driver.py refers to a directory with ``fish``, ``fish_indent`` and ``fish_key_reader`` in it.
|
||||
In this example we're in the root of the workspace and have run ``cargo build`` without ``--release``, so it's a debug build.
|
||||
In this example we're in the root of the git repo and have run ``cargo build`` without ``--release``, so it's a debug build.
|
||||
|
||||
To run all tests and linters, use::
|
||||
Git hooks
|
||||
---------
|
||||
|
||||
build_tools/check.sh
|
||||
Since developers sometimes forget to run the tests, it can be helpful to
|
||||
use git hooks (see githooks(5)) to automate it.
|
||||
|
||||
One possibility is a pre-push hook script like this one:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
#!/bin/sh
|
||||
#### A pre-push hook for the fish-shell project
|
||||
# This will run the tests when a push to master is detected, and will stop that if the tests fail
|
||||
# Save this as .git/hooks/pre-push and make it executable
|
||||
|
||||
protected_branch='master'
|
||||
|
||||
# Git gives us lines like "refs/heads/frombranch SOMESHA1 refs/heads/tobranch SOMESHA1"
|
||||
# We're only interested in the branches
|
||||
isprotected=false
|
||||
while read from _ to _; do
|
||||
if [ "$to" = "refs/heads/$protected_branch" ]; then
|
||||
isprotected=true
|
||||
fi
|
||||
done
|
||||
if "$isprotected"; then
|
||||
echo "Running checks before push to master"
|
||||
build_tools/check.sh
|
||||
fi
|
||||
|
||||
This will check if the push is to the master branch and, if it is, only
|
||||
allow the push if running ``build_tools/check.sh`` succeeds. In some circumstances
|
||||
it may be advisable to circumvent this check with
|
||||
``git push --no-verify``, but usually that isn’t necessary.
|
||||
|
||||
To install the hook, place the code in a new file
|
||||
``.git/hooks/pre-push`` and make it executable.
|
||||
|
||||
Contributing Translations
|
||||
=========================
|
||||
@@ -297,7 +343,7 @@ command-line and graphical user interface programs. For simple use, you can use
|
||||
|
||||
Open up the PO file, for example ``po/sv.po``, and you'll see something like::
|
||||
|
||||
msgid "%s: No suitable job\n"
|
||||
msgid "%ls: No suitable job\n"
|
||||
msgstr ""
|
||||
|
||||
The ``msgid`` here is the "name" of the string to translate, typically the English string to translate.
|
||||
@@ -305,10 +351,10 @@ The second line (``msgstr``) is where your translation goes.
|
||||
|
||||
For example::
|
||||
|
||||
msgid "%s: No suitable job\n"
|
||||
msgstr "%s: Inget passande jobb\n"
|
||||
msgid "%ls: No suitable job\n"
|
||||
msgstr "%ls: Inget passande jobb\n"
|
||||
|
||||
Any ``%s`` or ``%d`` are placeholders that fish will use for formatting at runtime. It is important that they match - the translated string should have the same placeholders in the same order.
|
||||
Any ``%s`` / ``%ls`` or ``%d`` are placeholders that fish will use for formatting at runtime. It is important that they match - the translated string should have the same placeholders in the same order.
|
||||
|
||||
Also any escaped characters, like that ``\n`` newline at the end, should be kept so the translation has the same behavior.
|
||||
|
||||
@@ -335,7 +381,7 @@ macros:
|
||||
|
||||
::
|
||||
|
||||
streams.out.append(wgettext_fmt!("%s: There are no jobs\n", argv[0]));
|
||||
streams.out.append(wgettext_fmt!("%ls: There are no jobs\n", argv[0]));
|
||||
|
||||
All messages in fish script must be enclosed in single or double quote
|
||||
characters for our message extraction script to find them.
|
||||
@@ -358,12 +404,6 @@ You can use either single or double quotes to enclose the
|
||||
message to be translated. You can also optionally include spaces after
|
||||
the opening parentheses or before the closing parentheses.
|
||||
|
||||
Updating Dependencies
|
||||
=====================
|
||||
|
||||
To update dependencies, run ``build_tools/update-dependencies.sh``.
|
||||
This currently requires `updatecli <https://github.com/updatecli/updatecli>`__ and a few other tools.
|
||||
|
||||
Versioning
|
||||
==========
|
||||
|
||||
|
||||
468
Cargo.lock
generated
468
Cargo.lock
generated
@@ -1,15 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
@@ -19,15 +10,15 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -38,23 +29,12 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.41"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7"
|
||||
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
@@ -62,9 +42,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
@@ -74,9 +54,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -101,38 +81,17 @@ dependencies = [
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
@@ -144,19 +103,12 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
|
||||
|
||||
[[package]]
|
||||
name = "fish"
|
||||
version = "4.2.0"
|
||||
version = "4.1.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"errno",
|
||||
"fish-build-helper",
|
||||
"fish-build-man-pages",
|
||||
@@ -164,10 +116,8 @@ dependencies = [
|
||||
"fish-gettext-maps",
|
||||
"fish-gettext-mo-file-parser",
|
||||
"fish-printf",
|
||||
"fish-tempfile",
|
||||
"libc",
|
||||
"lru",
|
||||
"macro_rules_attribute",
|
||||
"nix",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
@@ -231,13 +181,6 @@ dependencies = [
|
||||
"widestring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-tempfile"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@@ -246,61 +189,25 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.9"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
@@ -309,44 +216,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
]
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
@@ -357,27 +254,11 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520"
|
||||
dependencies = [
|
||||
"macro_rules_attribute-proc_macro",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute-proc_macro"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
@@ -418,21 +299,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.5"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
@@ -440,23 +315,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.12"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-link",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pcre2"
|
||||
version = "0.2.9"
|
||||
@@ -555,40 +424,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
@@ -606,41 +469,13 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.18"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "rsconf"
|
||||
version = "0.2.2"
|
||||
@@ -652,9 +487,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.8.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb44e1917075637ee8c7bcb865cf8830e3a92b5b1189e44e3a0ab5a0d5be314b"
|
||||
checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
@@ -663,25 +498,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.8.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "382499b49db77a7c19abd2a574f85ada7e9dbe125d5d1160fa5cad7c4cf71fc9"
|
||||
checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"shellexpand",
|
||||
"syn",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.8.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21fcbee55c2458836bcdbfffb6ec9ba74bbc23ca7aa6816015a3dd2c4d8fc185"
|
||||
checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594"
|
||||
dependencies = [
|
||||
"globset",
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
@@ -697,9 +530,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "scc"
|
||||
version = "2.4.0"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc"
|
||||
checksum = "28e1c91382686d21b5ac7959341fcb9780fa7c03773646995a87c950fa7be640"
|
||||
dependencies = [
|
||||
"sdd",
|
||||
]
|
||||
@@ -712,38 +545,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sdd"
|
||||
version = "3.0.10"
|
||||
version = "3.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9"
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
@@ -770,24 +574,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -802,15 +597,15 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.107"
|
||||
version = "2.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b"
|
||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -829,37 +624,17 @@ dependencies = [
|
||||
"phf_codegen 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.20"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
@@ -869,9 +644,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.2"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "unix_path"
|
||||
@@ -904,53 +679,90 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.2.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
|
||||
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
41
Cargo.toml
41
Cargo.toml
@@ -1,16 +1,16 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
# To build revisions that use Corrosion (those before 2024-01), use CMake 3.19, Rustc 1.78 and Rustup 1.27.
|
||||
rust-version = "1.85"
|
||||
edition = "2024"
|
||||
rust-version = "1.70"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/fish-shell/fish-shell"
|
||||
|
||||
[workspace.dependencies]
|
||||
bitflags = "2.5.0"
|
||||
cc = "1.0.94"
|
||||
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" }
|
||||
@@ -18,8 +18,7 @@ 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" }
|
||||
libc = "0.2.177"
|
||||
libc = "0.2.155"
|
||||
# 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
|
||||
# files as of 22 April 2024.
|
||||
@@ -46,12 +45,7 @@ proc-macro2 = "1.0"
|
||||
# minimum supported version to 10.12.
|
||||
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
|
||||
rsconf = "0.2.2"
|
||||
rust-embed = { version = "8.7.2", features = [
|
||||
"deterministic-timestamps",
|
||||
"include-exclude",
|
||||
"interpolate-folder-path",
|
||||
] }
|
||||
|
||||
rust-embed = { version = "8.7.2", features = ["deterministic-timestamps"] }
|
||||
serial_test = { version = "3", default-features = false }
|
||||
# We need 0.9.0 specifically for some crash fixes.
|
||||
terminfo = "0.9.0"
|
||||
@@ -70,7 +64,7 @@ debug = true
|
||||
|
||||
[package]
|
||||
name = "fish"
|
||||
version = "4.2.0"
|
||||
version = "4.1.2"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
default-run = "fish"
|
||||
@@ -82,17 +76,14 @@ readme = "README.rst"
|
||||
|
||||
[dependencies]
|
||||
bitflags.workspace = true
|
||||
cfg-if.workspace = true
|
||||
errno.workspace = true
|
||||
fish-build-helper.workspace = true
|
||||
fish-build-man-pages = { 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
|
||||
libc.workspace = true
|
||||
lru.workspace = true
|
||||
macro_rules_attribute = "0.2.2"
|
||||
nix.workspace = true
|
||||
num-traits.workspace = true
|
||||
once_cell.workspace = true
|
||||
@@ -106,18 +97,9 @@ widestring.workspace = true
|
||||
portable-atomic.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rust-embed = { workspace = true, optional = true, features = [
|
||||
"deterministic-timestamps",
|
||||
"debug-embed",
|
||||
"include-exclude",
|
||||
"interpolate-folder-path",
|
||||
] }
|
||||
rust-embed = { workspace = true, optional = true, features = ["deterministic-timestamps", "debug-embed"] }
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
rust-embed = { workspace = true, optional = true, features = [
|
||||
"deterministic-timestamps",
|
||||
"include-exclude",
|
||||
"interpolate-folder-path",
|
||||
] }
|
||||
rust-embed = { workspace = true, optional = true, features = ["deterministic-timestamps"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test.workspace = true
|
||||
@@ -170,14 +152,9 @@ rust.non_camel_case_types = "allow"
|
||||
rust.non_upper_case_globals = "allow"
|
||||
rust.unknown_lints = "allow"
|
||||
rust.unstable_name_collisions = "allow"
|
||||
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.needless_lifetimes = "allow"
|
||||
clippy.needless_return = "allow"
|
||||
clippy.new_without_default = "allow"
|
||||
clippy.option_map_unit_fn = "allow"
|
||||
clippy.needless_lifetimes = "allow"
|
||||
|
||||
# We do not want to use the e?print(ln)?! macros.
|
||||
# These lints flag their use.
|
||||
|
||||
52
README.rst
52
README.rst
@@ -90,7 +90,7 @@ Running fish requires:
|
||||
|
||||
- some common \*nix system utilities (currently ``mktemp``), in
|
||||
addition to the basic POSIX utilities (``cat``, ``cut``, ``dirname``,
|
||||
``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sh``, ``sort``, ``tee``, ``tr``,
|
||||
``file``, ``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sh``, ``sort``, ``tee``, ``tr``,
|
||||
``uname`` and ``sed`` at least, but the full coreutils plus ``find`` and
|
||||
``awk`` is preferred)
|
||||
|
||||
@@ -100,7 +100,6 @@ The following optional features also have specific requirements:
|
||||
messages require ``man`` for display
|
||||
- automated completion generation from manual pages requires Python 3.5+
|
||||
- the ``fish_config`` web configuration tool requires Python 3.5+ and a web browser
|
||||
- the :ref:`alt-o <shared-binds-alt-o>` binding requires the ``file`` program.
|
||||
- system clipboard integration (with the default Ctrl-V and Ctrl-X
|
||||
bindings) require either the ``xsel``, ``xclip``,
|
||||
``wl-copy``/``wl-paste`` or ``pbcopy``/``pbpaste`` utilities
|
||||
@@ -112,12 +111,14 @@ The following optional features also have specific requirements:
|
||||
Building
|
||||
--------
|
||||
|
||||
.. _dependencies-1:
|
||||
|
||||
Dependencies
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Compiling fish requires:
|
||||
|
||||
- Rust (version 1.85 or later)
|
||||
- Rust (version 1.70 or later)
|
||||
- CMake (version 3.15 or later)
|
||||
- a C compiler (for system feature detection and the test helper binary)
|
||||
- PCRE2 (headers and libraries) - optional, this will be downloaded if missing
|
||||
@@ -127,7 +128,7 @@ Compiling fish requires:
|
||||
Sphinx is also optionally required to build the documentation from a
|
||||
cloned git repository.
|
||||
|
||||
Additionally, running the full test suite requires diff, git, Python 3.5+, pexpect, less, tmux and wget.
|
||||
Additionally, running the full test suite requires Python 3.5+, tmux, and the pexpect package.
|
||||
|
||||
Building from source with CMake
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -139,7 +140,7 @@ links above, and up-to-date `development builds of fish are available for many p
|
||||
|
||||
To install into ``/usr/local``, run:
|
||||
|
||||
.. code:: shell
|
||||
.. code:: bash
|
||||
|
||||
mkdir build; cd build
|
||||
cmake ..
|
||||
@@ -164,41 +165,34 @@ In addition to the normal CMake build options (like ``CMAKE_INSTALL_PREFIX``), f
|
||||
- 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
|
||||
|
||||
Building fish with Cargo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Building fish with embedded data (experimental)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can also build fish with Cargo.
|
||||
This example uses `uv <https://github.com/astral-sh/uv>`__ to install Sphinx (which is used for man-pages and ``--help`` options).
|
||||
You can also install Sphinx another way and drop the ``uv run --no-managed-python`` prefix.
|
||||
You can also build fish with the data files embedded.
|
||||
|
||||
.. code:: shell
|
||||
This will include all the datafiles like the included functions or web configuration tool in the main ``fish`` binary.
|
||||
|
||||
git clone https://github.com/fish-shell/fish-shell
|
||||
cd fish-shell
|
||||
Fish will then read these right from its own binary, and print them out when needed. Some files, like the webconfig tool and the manpage completion generator, will be extracted to a temporary directory on-demand. You can list the files with ``status list-files`` and print one with ``status get-file path/to/file`` (e.g. ``status get-file functions/fish_prompt.fish`` to get the default prompt).
|
||||
|
||||
# Optional: check out a specific version rather than building the latest
|
||||
# development version.
|
||||
git checkout "$(git for-each-ref refs/tags/ | awk '$2 == "tag" { print $3 }' | tail -1)"
|
||||
To install fish with embedded files, just use ``cargo``, like::
|
||||
|
||||
uv run --no-managed-python \
|
||||
cargo install --path .
|
||||
cargo install --path /path/to/fish # if you have a git clone
|
||||
cargo install --git https://github.com/fish-shell/fish-shell --tag "$(curl -s https://api.github.com/repos/fish-shell/fish-shell/releases/latest | jq -r .tag_name)" # to build the latest release
|
||||
cargo install --git https://github.com/fish-shell/fish-shell # to build the latest development snapshot
|
||||
|
||||
This will place standalone binaries in ``~/.cargo/bin/``, but you can move them wherever you want.
|
||||
This will place the standalone binaries in ``~/.cargo/bin/``, but you can place them wherever you want.
|
||||
|
||||
This build won't have the HTML docs (``help`` will open the online version).
|
||||
It will try to build the man pages with sphinx-build. If that is not available and you would like to include man pages, you need to install it and retrigger the build script, e.g. by setting FISH_BUILD_DOCS=1::
|
||||
|
||||
FISH_BUILD_DOCS=1 cargo install --path .
|
||||
|
||||
Setting it to "0" disables the inclusion of man pages.
|
||||
|
||||
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features --features=embed-data`` 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.
|
||||
- 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,
|
||||
(also recorded in ``$PREFIX/share/pkgconfig/fish.pc``)
|
||||
which are used by some package managers to house third-party completions.
|
||||
Regardless of build system, fish uses ``$XDG_DATA_DIRS/{vendor_completion.d,vendor_conf.d,vendor_functions.d}``.
|
||||
|
||||
Contributing Changes to the Code
|
||||
--------------------------------
|
||||
|
||||
|
||||
139
build.rs
139
build.rs
@@ -1,4 +1,6 @@
|
||||
use fish_build_helper::{env_var, fish_build_dir, workspace_root};
|
||||
#![allow(clippy::uninlined_format_args)]
|
||||
|
||||
use fish_build_helper::{fish_build_dir, workspace_root};
|
||||
use rsconf::Target;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -28,17 +30,16 @@ fn main() {
|
||||
);
|
||||
|
||||
// Some build info
|
||||
rsconf::set_env_value("BUILD_TARGET_TRIPLE", &env_var("TARGET").unwrap());
|
||||
rsconf::set_env_value("BUILD_HOST_TRIPLE", &env_var("HOST").unwrap());
|
||||
rsconf::set_env_value("BUILD_PROFILE", &env_var("PROFILE").unwrap());
|
||||
rsconf::set_env_value("BUILD_TARGET_TRIPLE", &env::var("TARGET").unwrap());
|
||||
rsconf::set_env_value("BUILD_HOST_TRIPLE", &env::var("HOST").unwrap());
|
||||
rsconf::set_env_value("BUILD_PROFILE", &env::var("PROFILE").unwrap());
|
||||
|
||||
let version = &get_version(&env::current_dir().unwrap());
|
||||
// Per https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script,
|
||||
// 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) };
|
||||
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).
|
||||
@@ -49,6 +50,9 @@ fn main() {
|
||||
#[cfg(feature = "gettext-extract")]
|
||||
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_FILE");
|
||||
|
||||
rsconf::rebuild_if_path_changed("src/libc.c");
|
||||
cc::Build::new().file("src/libc.c").compile("flibc.a");
|
||||
|
||||
let build = cc::Build::new();
|
||||
let mut target = Target::new_from(build).unwrap();
|
||||
// Keep verbose mode on until we've ironed out rust build script stuff
|
||||
@@ -56,9 +60,7 @@ fn main() {
|
||||
detect_cfgs(&mut target);
|
||||
|
||||
#[cfg(all(target_env = "gnu", target_feature = "crt-static"))]
|
||||
compile_error!(
|
||||
"Statically linking against glibc has unavoidable crashes and is unsupported. Use dynamic linking or link statically against musl."
|
||||
);
|
||||
compile_error!("Statically linking against glibc has unavoidable crashes and is unsupported. Use dynamic linking or link statically against musl.");
|
||||
}
|
||||
|
||||
/// Check target system support for certain functionality dynamically when the build is invoked,
|
||||
@@ -81,7 +83,6 @@ fn detect_cfgs(target: &mut Target) {
|
||||
("", &(|_: &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).
|
||||
@@ -116,7 +117,7 @@ fn detect_apple(_: &Target) -> bool {
|
||||
|
||||
fn detect_cygwin(_: &Target) -> bool {
|
||||
// Cygwin target is usually cross-compiled.
|
||||
env_var("CARGO_CFG_TARGET_OS").unwrap() == "cygwin"
|
||||
std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "cygwin"
|
||||
}
|
||||
|
||||
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
|
||||
@@ -128,10 +129,11 @@ fn detect_cygwin(_: &Target) -> bool {
|
||||
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();
|
||||
let mut target = std::env::var("TARGET").unwrap();
|
||||
if !target.chars().all(|c| c.is_ascii_lowercase()) {
|
||||
target = target.to_ascii_lowercase();
|
||||
}
|
||||
#[allow(clippy::let_and_return)] // for old clippy
|
||||
let is_bsd = target.ends_with("bsd") || target.ends_with("dragonfly");
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
@@ -161,16 +163,19 @@ fn has_small_stack(_: &Target) -> bool {
|
||||
{
|
||||
use core::ffi;
|
||||
|
||||
unsafe extern "C" {
|
||||
unsafe fn pthread_get_stacksize_np(thread: *const ffi::c_void) -> usize;
|
||||
unsafe fn pthread_self() -> *const ffi::c_void;
|
||||
extern "C" {
|
||||
fn pthread_get_stacksize_np(thread: *const ffi::c_void) -> usize;
|
||||
fn pthread_self() -> *const ffi::c_void;
|
||||
}
|
||||
|
||||
// build.rs is executed on the main thread, so we are getting the main thread's stack size.
|
||||
// Modern macOS versions default to an 8 MiB main stack but legacy OS X have a 0.5 MiB one.
|
||||
let stack_size = unsafe { pthread_get_stacksize_np(pthread_self()) };
|
||||
const TWO_MIB: usize = 2 * 1024 * 1024 - 1;
|
||||
stack_size <= TWO_MIB
|
||||
match stack_size {
|
||||
0..=TWO_MIB => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,77 +183,59 @@ fn setup_paths() {
|
||||
#[cfg(windows)]
|
||||
use unix_path::{Path, PathBuf};
|
||||
|
||||
fn overridable_path(
|
||||
env_var_name: &str,
|
||||
f: impl FnOnce(Option<String>) -> Option<PathBuf>,
|
||||
) -> Option<PathBuf> {
|
||||
rsconf::rebuild_if_env_changed(env_var_name);
|
||||
let maybe_path = f(env_var(env_var_name));
|
||||
if let Some(path) = maybe_path.as_ref() {
|
||||
rsconf::set_env_value(env_var_name, path.to_str().unwrap());
|
||||
fn get_path(name: &str, default: &str, onvar: &Path) -> PathBuf {
|
||||
let mut var = PathBuf::from(env::var(name).unwrap_or(default.to_string()));
|
||||
if var.is_relative() {
|
||||
var = onvar.join(var);
|
||||
}
|
||||
maybe_path
|
||||
var
|
||||
}
|
||||
|
||||
fn join_if_relative(parent_if_relative: &Path, path: String) -> PathBuf {
|
||||
let path = PathBuf::from(path);
|
||||
if path.is_relative() {
|
||||
parent_if_relative.join(path)
|
||||
let prefix = PathBuf::from(env::var("PREFIX").unwrap_or("/usr/local".to_string()));
|
||||
rsconf::rebuild_if_env_changed("PREFIX");
|
||||
rsconf::set_env_value("PREFIX", prefix.to_str().unwrap());
|
||||
|
||||
let datadir = get_path("DATADIR", "share/", &prefix);
|
||||
|
||||
let sysconfdir = get_path(
|
||||
"SYSCONFDIR",
|
||||
// Embedded builds use "/etc," not "./share/etc".
|
||||
if cfg!(feature = "embed-data") {
|
||||
"/etc/"
|
||||
} else {
|
||||
path
|
||||
}
|
||||
"etc/"
|
||||
},
|
||||
&datadir,
|
||||
);
|
||||
rsconf::set_env_value("SYSCONFDIR", sysconfdir.to_str().unwrap());
|
||||
rsconf::rebuild_if_env_changed("SYSCONFDIR");
|
||||
|
||||
#[cfg(not(feature = "embed-data"))]
|
||||
{
|
||||
rsconf::set_env_value("DATADIR", datadir.to_str().unwrap());
|
||||
rsconf::rebuild_if_env_changed("DATADIR");
|
||||
|
||||
let bindir = get_path("BINDIR", "bin/", &prefix);
|
||||
rsconf::set_env_value("BINDIR", bindir.to_str().unwrap());
|
||||
rsconf::rebuild_if_env_changed("BINDIR");
|
||||
|
||||
let localedir = get_path("LOCALEDIR", "locale/", &datadir);
|
||||
let localedir = localedir.to_str().unwrap();
|
||||
assert!(!localedir.is_empty(), "empty LOCALEDIR is not supported");
|
||||
rsconf::set_env_value("LOCALEDIR", localedir);
|
||||
rsconf::rebuild_if_env_changed("LOCALEDIR");
|
||||
|
||||
let docdir = get_path("DOCDIR", "doc/fish", &datadir);
|
||||
rsconf::set_env_value("DOCDIR", docdir.to_str().unwrap());
|
||||
rsconf::rebuild_if_env_changed("DOCDIR");
|
||||
}
|
||||
|
||||
let prefix = overridable_path("PREFIX", |env_prefix| {
|
||||
Some(PathBuf::from(
|
||||
env_prefix.unwrap_or("/usr/local".to_string()),
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
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(),
|
||||
),
|
||||
))
|
||||
});
|
||||
|
||||
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))
|
||||
});
|
||||
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))
|
||||
});
|
||||
overridable_path("DOCDIR", |env_docdir| {
|
||||
let default = default_ok.then_some("doc/fish".to_string());
|
||||
env_docdir.or(default).map(|p| {
|
||||
join_if_relative(
|
||||
&datadir
|
||||
.expect("Setting DOCDIR without setting DATADIR is not currently supported"),
|
||||
p,
|
||||
)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn get_version(src_dir: &Path) -> String {
|
||||
use std::fs::read_to_string;
|
||||
use std::process::Command;
|
||||
|
||||
if let Some(var) = env_var("FISH_BUILD_VERSION") {
|
||||
if let Ok(var) = std::env::var("FISH_BUILD_VERSION") {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,22 +8,6 @@ if [ "$FISH_CHECK_LINT" = false ]; then
|
||||
lint=false
|
||||
fi
|
||||
|
||||
check_dependency_versions=false
|
||||
if [ "${FISH_CHECK_DEPENDENCY_VERSIONS:-false}" != false ]; then
|
||||
check_dependency_versions=true
|
||||
fi
|
||||
|
||||
if $check_dependency_versions; then
|
||||
command -v curl
|
||||
command -v jq
|
||||
command -v rustup
|
||||
command -v uv
|
||||
sort --version-sort </dev/null
|
||||
# To match existing behavior, only check Rust/dockerfiles for now.
|
||||
# TODO: remove this from this script.
|
||||
updatecli diff --config=updatecli.d/docker.yml --config=updatecli.d/rust.yml
|
||||
fi
|
||||
|
||||
cargo_args=$FISH_CHECK_CARGO_ARGS
|
||||
target_triple=$FISH_CHECK_TARGET_TRIPLE
|
||||
if [ -n "$target_triple" ]; then
|
||||
@@ -59,16 +43,8 @@ fi
|
||||
# Currently, all builds are debug builds.
|
||||
build_dir="$target_dir/debug"
|
||||
|
||||
if [ -n "$FISH_TEST_MAX_CONCURRENCY" ]; then
|
||||
export RUST_TEST_THREADS="$FISH_TEST_MAX_CONCURRENCY"
|
||||
export CARGO_BUILD_JOBS="$FISH_TEST_MAX_CONCURRENCY"
|
||||
fi
|
||||
|
||||
template_file=$(mktemp)
|
||||
(
|
||||
export FISH_GETTEXT_EXTRACTION_FILE="$template_file"
|
||||
cargo build --workspace --all-targets --features=gettext-extract
|
||||
)
|
||||
FISH_GETTEXT_EXTRACTION_FILE=$template_file cargo build --workspace --all-targets --features=gettext-extract
|
||||
if $lint; then
|
||||
PATH="$build_dir:$PATH" "$workspace_root/build_tools/style.fish" --all --check
|
||||
for features in "" --no-default-features; do
|
||||
|
||||
23
build_tools/extract_help_sections.fish
Normal file
23
build_tools/extract_help_sections.fish
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env fish
|
||||
# Build a list of all sections in the html sphinx docs, separately by page,
|
||||
# so it can be added to share/functions/help.fish
|
||||
# Use like
|
||||
# fish extract_help_sections.fish user_doc/html/{fish_for_bash_users.html,faq.html,interactive.html,language.html,tutorial.html}
|
||||
# TODO: Currently `help` uses variable names we can't generate, so it needs to be touched up manually.
|
||||
# Also this could easily be broken by changes in sphinx, ideally we'd have a way to let it print the section titles.
|
||||
#
|
||||
|
||||
for file in $argv
|
||||
set -l varname (string replace -r '.*/(.*).html' '$1' -- $file | string escape --style=var)pages
|
||||
# Technically we can use any id in the document as an anchor, but listing them all is probably too much.
|
||||
# Sphinx stores section titles (in a slug-ized form) in the id,
|
||||
# and stores explicit section links in a `span` tag like
|
||||
# `<span id="identifiers"></span>`
|
||||
# We extract both separately.
|
||||
set -l sections (string replace -rf '.*class="headerlink" href="#([^"]*)".*' '$1' <$file)
|
||||
# Sections titled "id5" and such are internal cruft and shouldn't be offered.
|
||||
set -a sections (string replace -rf '.*span id="([^"]*)".*' '$1' <$file | string match -rv 'id\d+')
|
||||
|
||||
set sections (printf '%s\n' $sections | sort -u)
|
||||
echo set -l $varname $sections
|
||||
end
|
||||
@@ -27,21 +27,13 @@ begin
|
||||
else
|
||||
set rust_extraction_file (mktemp)
|
||||
# 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_FILE=$rust_extraction_file cargo check --features=gettext-extract
|
||||
or exit 1
|
||||
end
|
||||
|
||||
function mark_section
|
||||
set -l section_name $argv[1]
|
||||
echo 'msgid "fish-section-'$section_name'"'
|
||||
echo 'msgstr ""'
|
||||
echo ''
|
||||
end
|
||||
|
||||
mark_section tier1-from-rust
|
||||
|
||||
echo '# fish-section-tier1-from-rust'
|
||||
# Get rid of duplicates and sort.
|
||||
msguniq --no-wrap --sort-output $rust_extraction_file
|
||||
msguniq --no-wrap --strict --sort-output $rust_extraction_file
|
||||
or exit 1
|
||||
|
||||
if not set -l --query _flag_use_existing_template
|
||||
@@ -85,13 +77,13 @@ begin
|
||||
# This regex handles explicit requests to translate a message. These are more important to translate
|
||||
# than messages which should be implicitly translated.
|
||||
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
|
||||
mark_section "$tier-from-script-explicitly-added"
|
||||
echo "# fish-section-$tier-from-script-explicitly-added"
|
||||
extract_fish_script_messages_impl $explicit_regex $argv
|
||||
|
||||
# This regex handles descriptions for `complete` and `function` statements. These messages are not
|
||||
# particularly important to translate. Hence the "implicit" label.
|
||||
set -l implicit_regex '^(?:\s|and |or )*(?:complete|function).*? (?:-d|--description) (([\'"]).+?(?<!\\\\)\\2).*'
|
||||
mark_section "$tier-from-script-implicitly-added"
|
||||
echo "# fish-section-$tier-from-script-implicitly-added"
|
||||
extract_fish_script_messages_impl $implicit_regex $argv
|
||||
end
|
||||
|
||||
|
||||
@@ -24,7 +24,13 @@ SIGN=
|
||||
NOTARIZE=
|
||||
|
||||
ARM64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=11.0'
|
||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.12'
|
||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.9'
|
||||
|
||||
# As of this writing, the most recent Rust release supports macOS back to 10.12.
|
||||
# The first supported version of macOS on arm64 is 10.15, so any Rust is fine for arm64.
|
||||
# We wish to support back to 10.9 on x86-64; the last version of Rust to support that is
|
||||
# version 1.73.0.
|
||||
RUST_VERSION_X86_64=1.70.0
|
||||
|
||||
while getopts "sf:i:p:e:nj:" opt; do
|
||||
case $opt in
|
||||
@@ -59,29 +65,34 @@ OUTPUT_PATH=${FISH_ARTEFACT_PATH:-~/fish_built}
|
||||
|
||||
mkdir -p "$PKGDIR/build_x86_64" "$PKGDIR/build_arm64" "$PKGDIR/root" "$PKGDIR/intermediates" "$PKGDIR/dst"
|
||||
|
||||
do_cmake() {
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
||||
-DFISH_USE_SYSTEM_PCRE2=OFF \
|
||||
"$@" \
|
||||
"$SRC_DIR"
|
||||
}
|
||||
|
||||
# Build and install for arm64.
|
||||
# Pass FISH_USE_SYSTEM_PCRE2=OFF because a system PCRE2 on macOS will not be signed by fish,
|
||||
# and will probably not be built universal, so the package will fail to validate/run on other systems.
|
||||
# Note CMAKE_OSX_ARCHITECTURES is still relevant for the Mac app.
|
||||
{ cd "$PKGDIR/build_arm64" \
|
||||
&& do_cmake -DRust_CARGO_TARGET=aarch64-apple-darwin \
|
||||
&& cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
||||
-DRust_CARGO_TARGET=aarch64-apple-darwin \
|
||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
||||
-DFISH_USE_SYSTEM_PCRE2=OFF \
|
||||
"$SRC_DIR" \
|
||||
&& env $ARM64_DEPLOY_TARGET make VERBOSE=1 -j 12 \
|
||||
&& 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.
|
||||
# Set RUST_VERSION_X86_64 to the last version of Rust that supports macOS 10.9.
|
||||
{ cd "$PKGDIR/build_x86_64" \
|
||||
&& do_cmake -DRust_CARGO_TARGET=x86_64-apple-darwin \
|
||||
&& cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
||||
-DRust_TOOLCHAIN="$RUST_VERSION_X86_64" \
|
||||
-DRust_CARGO_TARGET=x86_64-apple-darwin \
|
||||
-DRust_COMPILER="$(rustup +$RUST_VERSION_X86_64 which rustc)" \
|
||||
-DRust_CARGO="$(rustup +$RUST_VERSION_X86_64 which cargo)" \
|
||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
||||
-DFISH_USE_SYSTEM_PCRE2=OFF "$SRC_DIR" \
|
||||
&& env $X86_64_DEPLOY_TARGET make VERBOSE=1 -j 12; }
|
||||
|
||||
# Fatten them up.
|
||||
|
||||
@@ -41,12 +41,6 @@ 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"
|
||||
@@ -66,8 +60,7 @@ 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
|
||||
$BUILD_TOOL doc
|
||||
|
||||
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
|
||||
--mode=g+w,a+rX --transform s/^/$prefix\//"
|
||||
|
||||
@@ -11,38 +11,37 @@ mkdir -p "$relnotes_tmp/fake-workspace" "$relnotes_tmp/out"
|
||||
cp -r doc_src CONTRIBUTING.rst README.rst "$relnotes_tmp/fake-workspace"
|
||||
)
|
||||
version=$(sed 's,^fish \(\S*\) .*,\1,; 1q' "$workspace_root/CHANGELOG.rst")
|
||||
add_stats=false
|
||||
# Skip on shallow clone (CI) for now.
|
||||
if test -z "$CI" || [ "$(git -C "$workspace_root" tag | wc -l)" -gt 1 ]; then {
|
||||
previous_version=$(
|
||||
cd "$workspace_root"
|
||||
git for-each-ref --format='%(objecttype) %(refname:strip=2)' refs/tags |
|
||||
awk '/tag/ {print $2}' | sort --version-sort |
|
||||
grep -vxF "$(git describe)" | tail -1
|
||||
)
|
||||
minor_version=${version%.*}
|
||||
previous_minor_version=${previous_version%.*}
|
||||
if [ "$minor_version" != "$previous_minor_version" ]; then
|
||||
add_stats=true
|
||||
fi
|
||||
} fi
|
||||
previous_version=$(
|
||||
cd "$workspace_root"
|
||||
awk <CHANGELOG.rst '
|
||||
( /^fish \S*\.\S*\.\S* \(released .*\)$/ &&
|
||||
NR > 1 &&
|
||||
# Skip tags that have not been created yet..
|
||||
system("git rev-parse --verify >/dev/null --quiet refs/tags/"$2) == 0 \
|
||||
) {
|
||||
print $2; ok = 1; exit
|
||||
}
|
||||
END { exit !ok }
|
||||
'
|
||||
)
|
||||
minor_version=${version%.*}
|
||||
previous_minor_version=${previous_version%.*}
|
||||
{
|
||||
sed -n 1,2p <"$workspace_root/CHANGELOG.rst"
|
||||
if $add_stats; then {
|
||||
ExtractCommitters() {
|
||||
git log "$1" --format="%aN"
|
||||
trailers='Co-authored-by|Signed-off-by'
|
||||
git log "$1" --format="%b" | sed -En "/^($trailers):\s*/{s///;s/\s*<.*//;p}"
|
||||
}
|
||||
ListCommitters() {
|
||||
comm "$@" "$relnotes_tmp/committers-then" "$relnotes_tmp/committers-now"
|
||||
}
|
||||
|
||||
ListCommitters() {
|
||||
comm "$@" "$relnotes_tmp/committers-then" "$relnotes_tmp/committers-now"
|
||||
}
|
||||
(
|
||||
cd "$workspace_root"
|
||||
git log "$previous_version" --format="%aN" | sort -u >"$relnotes_tmp/committers-then"
|
||||
git log "$previous_version".. --format="%aN" | sort -u >"$relnotes_tmp/committers-now"
|
||||
ListCommitters -13 >"$relnotes_tmp/committers-new"
|
||||
ListCommitters -12 >"$relnotes_tmp/committers-returning"
|
||||
)
|
||||
if [ "$minor_version" != "$previous_minor_version" ]; then
|
||||
(
|
||||
cd "$workspace_root"
|
||||
ExtractCommitters "$previous_version" | sort -u >"$relnotes_tmp/committers-then"
|
||||
ExtractCommitters "$previous_version".. | sort -u >"$relnotes_tmp/committers-now"
|
||||
ListCommitters -13 >"$relnotes_tmp/committers-new"
|
||||
ListCommitters -12 >"$relnotes_tmp/committers-returning"
|
||||
num_commits=$(git log --no-merges --format=%H "$previous_version".. | wc -l)
|
||||
num_authors=$(wc -l <"$relnotes_tmp/committers-now")
|
||||
num_new_authors=$(wc -l <"$relnotes_tmp/committers-new")
|
||||
@@ -52,7 +51,7 @@ if test -z "$CI" || [ "$(git -C "$workspace_root" tag | wc -l)" -gt 1 ]; then {
|
||||
echo
|
||||
echo
|
||||
)
|
||||
} fi
|
||||
fi
|
||||
|
||||
printf '%s\n' "$(awk <"$workspace_root/CHANGELOG.rst" '
|
||||
NR <= 2 || /^\.\. ignore / { next }
|
||||
@@ -61,9 +60,9 @@ if test -z "$CI" || [ "$(git -C "$workspace_root" tag | wc -l)" -gt 1 ]; then {
|
||||
' | sed '$d')" |
|
||||
sed -e '$s/^----*$//' # Remove spurious transitions at the end of the document.
|
||||
|
||||
if $add_stats; then {
|
||||
if [ "$minor_version" != "$previous_minor_version" ]; then {
|
||||
JoinEscaped() {
|
||||
LC_CTYPE=C.UTF-8 sed 's/\S/\\&/g' |
|
||||
sed 's/\S/\\&/g' |
|
||||
awk '
|
||||
NR != 1 { printf ",\n" }
|
||||
{ printf "%s", $0 }
|
||||
@@ -84,14 +83,9 @@ if test -z "$CI" || [ "$(git -C "$workspace_root" tag | wc -l)" -gt 1 ]; then {
|
||||
echo
|
||||
echo "---"
|
||||
echo
|
||||
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 "*Download links: To download the source code for fish, we suggest the file named \"fish-$version.tar.xz\". The file downloaded from \"Source code (tar.gz)\" will not build correctly.*"
|
||||
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>`__'
|
||||
echo 'for any Linux with the given CPU architecture.'
|
||||
echo "*The files called fish-$version-linux-\*.tar.xz are experimental packages containing a single standalone ``fish`` binary for any Linux with the given CPU architecture.*"
|
||||
} >"$relnotes_tmp/fake-workspace"/CHANGELOG.rst
|
||||
|
||||
sphinx-build >&2 -j auto \
|
||||
@@ -99,7 +93,7 @@ sphinx-build >&2 -j auto \
|
||||
-d "$relnotes_tmp/doctree" "$relnotes_tmp/fake-workspace/doc_src" "$relnotes_tmp/out" \
|
||||
-D markdown_http_base="https://fishshell.com/docs/$minor_version" \
|
||||
-D markdown_uri_doc_suffix=".html" \
|
||||
-D markdown_flavor=github \
|
||||
-D markdown_github_flavored=1 \
|
||||
"$@"
|
||||
|
||||
# Skip changelog header
|
||||
|
||||
@@ -19,14 +19,10 @@ fi
|
||||
|
||||
for tool in \
|
||||
bundle \
|
||||
diff \
|
||||
gh \
|
||||
gpg \
|
||||
jq \
|
||||
ruby \
|
||||
tar \
|
||||
timeout \
|
||||
uv \
|
||||
; do
|
||||
if ! command -v "$tool" >/dev/null; then
|
||||
echo >&2 "$0: missing command: $1"
|
||||
@@ -34,11 +30,6 @@ for tool in \
|
||||
fi
|
||||
done
|
||||
|
||||
committer=$(git var GIT_AUTHOR_IDENT)
|
||||
committer=${committer% *} # strip timezone
|
||||
committer=${committer% *} # strip timestamp
|
||||
gpg --local-user="$committer" --sign </dev/null >/dev/null
|
||||
|
||||
repo_root="$(dirname "$0")/.."
|
||||
fish_site=$repo_root/../fish-site
|
||||
fish_site_repo=git@github.com:$repository_owner/fish-site
|
||||
@@ -91,8 +82,8 @@ Created by ./build_tools/release.sh $version"
|
||||
|
||||
CommitVersion "$version" "Release $version"
|
||||
|
||||
git -c "user.signingKey=$committer" \
|
||||
tag --sign --message="Release $version" $version
|
||||
# N.B. this is not GPG-signed.
|
||||
git tag --annotate --message="Release $version" $version
|
||||
|
||||
git push $remote $version
|
||||
|
||||
@@ -117,21 +108,13 @@ done
|
||||
# Update fishshell.com
|
||||
tag_oid=$(git rev-parse "$version")
|
||||
tmpdir=$(mktemp -d)
|
||||
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
|
||||
cd "$local_tarball"
|
||||
tar xf "$fish_tar_xz"
|
||||
)
|
||||
# TODO This works on draft releases only if "gh" is configured to
|
||||
# have write access to the fish-shell repository. Unless we are fine
|
||||
# publishing the release at this point, we should at least fail if
|
||||
# "gh" doesn't have write access.
|
||||
while ! \
|
||||
gh release download "$version" --dir="$tmpdir" \
|
||||
--pattern="$fish_tar_xz"
|
||||
--pattern="fish-$version.tar.xz"
|
||||
do
|
||||
TIMEOUT=30 gh run watch "$run_id" ||:
|
||||
sleep 5
|
||||
@@ -139,16 +122,7 @@ done
|
||||
actual_tag_oid=$(git ls-remote "$remote" |
|
||||
awk '$2 == "refs/tags/'"$version"'" { print $1 }')
|
||||
[ "$tag_oid" = "$actual_tag_oid" ]
|
||||
|
||||
(
|
||||
cd "$tmpdir"
|
||||
tar xf "$fish_tar_xz"
|
||||
diff -ur "fish-$version" "local-tarball/fish-$version"
|
||||
gpg --local-user="$committer" --sign --detach --armor \
|
||||
"$fish_tar_xz"
|
||||
gh release upload "$version" "$fish_tar_xz.asc"
|
||||
)
|
||||
|
||||
( cd "$tmpdir" && tar xf fish-$version.tar.xz )
|
||||
CopyDocs() {
|
||||
rm -rf "$fish_site/site/docs/$1"
|
||||
cp -r "$tmpdir/fish-$version/user_doc/html" "$fish_site/site/docs/$1"
|
||||
@@ -259,7 +233,7 @@ milestone_number=$(
|
||||
gh_api_repo milestones?state=open |
|
||||
jq '.[] | select(.title == "fish '"$version"'") | .number'
|
||||
)
|
||||
gh_api_repo milestones/$milestone_number --method PATCH \
|
||||
gh_api_repo --method PATCH milestones/$milestone_number \
|
||||
--raw-field state=closed
|
||||
|
||||
next_patch_version=$(
|
||||
@@ -270,7 +244,7 @@ next_patch_version=$(
|
||||
'
|
||||
)
|
||||
if [ -n "$next_patch_version" ]; then
|
||||
gh_api_repo milestones --method POST \
|
||||
gh_api_repo --method POST milestones \
|
||||
--raw-field title="fish $next_patch_version"
|
||||
fi
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ if test $all = yes
|
||||
end
|
||||
end
|
||||
set fish_files $workspace_root/{benchmarks,build_tools,etc,share}/**.fish
|
||||
set python_files $workspace_root
|
||||
set python_files {doc_src,share,tests}/**.py
|
||||
else
|
||||
# Format the files specified as arguments.
|
||||
set -l files $argv
|
||||
@@ -58,11 +58,6 @@ set -l green (set_color green)
|
||||
set -l yellow (set_color yellow)
|
||||
set -l normal (set_color normal)
|
||||
|
||||
function die -V red -V normal
|
||||
echo $red$argv[1]$normal
|
||||
exit 1
|
||||
end
|
||||
|
||||
if set -q fish_files[1]
|
||||
if not type -q fish_indent
|
||||
echo
|
||||
@@ -71,52 +66,58 @@ if set -q fish_files[1]
|
||||
end
|
||||
echo === Running "$green"fish_indent"$normal"
|
||||
if set -l -q _flag_check
|
||||
fish_indent --check -- $fish_files
|
||||
or die "Fish files are not formatted correctly."
|
||||
if not fish_indent --check -- $fish_files
|
||||
echo $red"Fish files are not formatted correctly."$normal
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
fish_indent -w -- $fish_files
|
||||
end
|
||||
end
|
||||
|
||||
if set -q python_files[1]
|
||||
if not type -q ruff
|
||||
if not type -q black
|
||||
echo
|
||||
echo $yellow'Please install `ruff` to style python'$normal
|
||||
echo $yellow'Please install `black` to style python'$normal
|
||||
exit 127
|
||||
end
|
||||
echo === Running "$green"ruff format"$normal"
|
||||
echo === Running "$green"black"$normal"
|
||||
if set -l -q _flag_check
|
||||
ruff format --check $python_files
|
||||
or die "Python files are not formatted correctly."
|
||||
if not black --check $python_files
|
||||
echo $red"Python files are not formatted correctly."$normal
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
ruff format $python_files
|
||||
black $python_files
|
||||
end
|
||||
end
|
||||
|
||||
if test $all = yes; or set -q rust_files[1]
|
||||
if not cargo fmt --version >/dev/null
|
||||
echo
|
||||
echo $yellow'Please install "rustfmt" to style Rust, e.g. via:'
|
||||
echo "rustup component add rustfmt"$normal
|
||||
exit 127
|
||||
end
|
||||
|
||||
set -l edition_spec string match -r '^edition\s*=.*'
|
||||
test "$($edition_spec <Cargo.toml)" = "$($edition_spec <.rustfmt.toml)"
|
||||
or die "Cargo.toml and .rustfmt.toml use different editions"
|
||||
|
||||
echo === Running "$green"rustfmt"$normal"
|
||||
if set -l -q _flag_check
|
||||
if test $all = yes
|
||||
cargo fmt --all --check
|
||||
else
|
||||
rustfmt --check --files-with-diff $rust_files
|
||||
if not cargo fmt --version >/dev/null
|
||||
echo
|
||||
echo $yellow'Please install "rustfmt" to style Rust, e.g. via:'
|
||||
echo "rustup component add rustfmt"$normal
|
||||
exit 127
|
||||
end
|
||||
echo === Running "$green"rustfmt"$normal"
|
||||
if set -l -q _flag_check
|
||||
if set -l -q _flag_all
|
||||
if not cargo fmt --check
|
||||
echo $red"Rust files are not formatted correctly."$normal
|
||||
exit 1
|
||||
end
|
||||
or die "Rust files are not formatted correctly."
|
||||
else
|
||||
if test $all = yes
|
||||
cargo fmt --all
|
||||
else
|
||||
if set -q rust_files[1]
|
||||
if not rustfmt --check --files-with-diff $rust_files
|
||||
echo $red"Rust files are not formatted correctly."
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if set -l -q _flag_all
|
||||
cargo fmt
|
||||
else
|
||||
if set -q rust_files[1]
|
||||
rustfmt $rust_files
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
command -v curl
|
||||
command -v gcloud
|
||||
command -v jq
|
||||
command -v rustup
|
||||
command -v updatecli
|
||||
command -v uv
|
||||
sort --version-sort </dev/null
|
||||
|
||||
uv lock --check
|
||||
|
||||
updatecli "${@:-apply}"
|
||||
|
||||
uv lock # Python version constraints may have changed.
|
||||
uv lock --upgrade
|
||||
|
||||
from_gh() {
|
||||
repo=$1
|
||||
path=$2
|
||||
out_dir=$3
|
||||
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/littlecheck littlecheck/littlecheck.py tests/
|
||||
|
||||
# Update Cargo.lock
|
||||
cargo update
|
||||
# Update Cargo.toml and Cargo.lock
|
||||
cargo +nightly -Zunstable-options update --breaking
|
||||
@@ -31,9 +31,11 @@
|
||||
set -gx LC_ALL C.UTF-8
|
||||
|
||||
set -l build_tools (status dirname)
|
||||
set -g tmpdir
|
||||
set -l po_dir $build_tools/../po
|
||||
|
||||
set -l extract
|
||||
set -l po
|
||||
|
||||
argparse dry-run use-existing-template= -- $argv
|
||||
or exit $status
|
||||
@@ -44,8 +46,8 @@ if test -z $argv[1]
|
||||
else
|
||||
set -l po_dir_id (stat --format='%d:%i' -- $po_dir)
|
||||
for arg in $argv
|
||||
set -l arg_dir_id (stat --format='%d:%i' -- (dirname $arg) 2>/dev/null)
|
||||
if test $po_dir_id != "$arg_dir_id"
|
||||
set -l arg_dir_id (stat --format='%d:%i' -- (dirname $arg))
|
||||
if test $po_dir_id != $arg_dir_id
|
||||
echo "Argument $arg is not a file in the directory $(realpath $po_dir)."
|
||||
echo "Non-option arguments must specify paths to files in this directory."
|
||||
echo ""
|
||||
@@ -97,34 +99,44 @@ if set -l --query _flag_dry_run
|
||||
cp -r $po_dir/* $tmpdir
|
||||
end
|
||||
|
||||
# This is used to identify lines which should be set here via $header_lines.
|
||||
# Make sure that this prefix does not appear elsewhere in the file and only contains characters
|
||||
# without special meaning in a sed pattern.
|
||||
set -g header_prefix "# fish-note-sections: "
|
||||
|
||||
function print_header
|
||||
set -l header_lines \
|
||||
"Translations are divided into sections, each starting with a fish-section-* pseudo-message." \
|
||||
"The first few sections are more important." \
|
||||
"Ignore the tier3 sections unless you have a lot of time."
|
||||
for line in $header_lines
|
||||
printf '%s%s\n' $header_prefix $line
|
||||
end
|
||||
end
|
||||
|
||||
function merge_po_files --argument-names template_file po_file
|
||||
msgmerge --no-wrap --update --no-fuzzy-matching --backup=none --quiet \
|
||||
$po_file $template_file
|
||||
or cleanup_exit
|
||||
set -l new_po_file (mktemp) # TODO Remove on failure.
|
||||
# Remove obsolete messages instead of keeping them as #~ entries.
|
||||
and msgattrib --no-wrap --no-obsolete -o $new_po_file $po_file
|
||||
or cleanup_exit
|
||||
|
||||
begin
|
||||
print_header
|
||||
# Paste PO file without old header lines.
|
||||
sed '/^'$header_prefix'/d' $new_po_file
|
||||
echo "# fish-note-sections: Translations are divided into sections, each starting with a fish-section-* comment."
|
||||
echo "# fish-note-sections: The first few sections are more important."
|
||||
echo "# fish-note-sections: Ignore the tier3 sections unless you have a lot of time."
|
||||
sed -i '
|
||||
/^# fish-note-sections:/d;
|
||||
/^# fish-section-/d;
|
||||
' $new_po_file
|
||||
|
||||
set -l next_line 1
|
||||
set -l section
|
||||
awk <$template_file '
|
||||
/^# fish-section-\S*$/ {
|
||||
section = $0
|
||||
}
|
||||
section != "" && /^msgid ".+"$/ {
|
||||
print section
|
||||
print $0
|
||||
section = ""
|
||||
}
|
||||
' |
|
||||
while read -l section
|
||||
read -l msgid_line
|
||||
set -l line_number (grep -m1 -Fxn $msgid_line $new_po_file | string split :)[1]
|
||||
sed -n "$next_line,$(math $line_number - 1)"p $new_po_file
|
||||
echo $section
|
||||
set next_line $line_number
|
||||
# set section
|
||||
end
|
||||
sed -n "$next_line,\$"p $new_po_file
|
||||
end >$po_file
|
||||
rm $new_po_file
|
||||
end
|
||||
@@ -133,13 +145,12 @@ for po_file in $po_files
|
||||
if set --query tmpdir[1]
|
||||
set po_file $tmpdir/(basename $po_file)
|
||||
end
|
||||
if test -e $po_file
|
||||
merge_po_files $template_file $po_file
|
||||
else
|
||||
begin
|
||||
print_header
|
||||
cat $template_file
|
||||
end >$po_file
|
||||
if set -l --query po
|
||||
if test -e $po_file
|
||||
merge_po_files $template_file $po_file
|
||||
else
|
||||
cp $template_file $po_file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
channel=$1 # e.g. stable, testing
|
||||
package=$2 # e.g. rustc, sphinx
|
||||
|
||||
codename=$(
|
||||
curl -fsS https://ftp.debian.org/debian/dists/"${channel}"/Release |
|
||||
grep '^Codename:' | cut -d' ' -f2)
|
||||
curl -fsS https://sources.debian.org/api/src/"${package}"/ |
|
||||
jq -r --arg codename "${codename}" '
|
||||
.versions[] | select(.suites[] == $codename) | .version' |
|
||||
sed 's/^\([0-9]\+\.[0-9]\+\).*/\1/' |
|
||||
sort --version-sort |
|
||||
tail -1
|
||||
@@ -136,7 +136,7 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/
|
||||
PATTERN "*.1"
|
||||
PATTERN ${CONDEMNED_PAGE} EXCLUDE)
|
||||
|
||||
install(PROGRAMS share/tools/create_manpage_completions.py
|
||||
install(PROGRAMS share/tools/create_manpage_completions.py share/tools/deroff.py
|
||||
DESTINATION ${rel_datadir}/fish/tools/)
|
||||
|
||||
install(DIRECTORY share/tools/web_config
|
||||
|
||||
@@ -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")
|
||||
@@ -30,3 +28,19 @@ if(NOT DEFINED WITH_GETTEXT OR "${WITH_GETTEXT}")
|
||||
endif()
|
||||
|
||||
list(JOIN FISH_CARGO_FEATURES_LIST , FISH_CARGO_FEATURES)
|
||||
|
||||
# Tell Cargo where our build directory is so it can find Cargo.toml.
|
||||
set(VARS_FOR_CARGO
|
||||
"FISH_BUILD_DIR=${CMAKE_BINARY_DIR}"
|
||||
"PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
# Cheesy so we can tell cmake was used to build
|
||||
"CMAKE=1"
|
||||
"DOCDIR=${CMAKE_INSTALL_FULL_DOCDIR}"
|
||||
"DATADIR=${CMAKE_INSTALL_FULL_DATADIR}"
|
||||
"SYSCONFDIR=${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||
"BINDIR=${CMAKE_INSTALL_FULL_BINDIR}"
|
||||
"CARGO_TARGET_DIR=${FISH_RUST_BUILD_DIR}"
|
||||
"CARGO_BUILD_RUSTC=${Rust_COMPILER}"
|
||||
"${FISH_PCRE2_BUILDFLAG}"
|
||||
"RUSTFLAGS=$ENV{RUSTFLAGS} ${rust_debugflags}"
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ 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} cargo test --no-default-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
|
||||
|
||||
@@ -1,21 +1,4 @@
|
||||
use std::{borrow::Cow, env, os::unix::ffi::OsStrExt, path::Path};
|
||||
|
||||
pub fn env_var(name: &str) -> Option<String> {
|
||||
let err = match env::var(name) {
|
||||
Ok(p) => return Some(p),
|
||||
Err(err) => err,
|
||||
};
|
||||
use env::VarError::*;
|
||||
match err {
|
||||
NotPresent => None,
|
||||
NotUnicode(os_string) => {
|
||||
panic!(
|
||||
"Environment variable {name} is not valid Unicode: {:?}",
|
||||
os_string.as_bytes()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::{borrow::Cow, env, path::Path};
|
||||
|
||||
pub fn workspace_root() -> &'static Path {
|
||||
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -29,7 +12,8 @@ fn cargo_target_dir() -> Cow<'static, Path> {
|
||||
}
|
||||
|
||||
pub fn fish_build_dir() -> Cow<'static, Path> {
|
||||
option_env!("FISH_CMAKE_BINARY_DIR")
|
||||
// This is set if using CMake.
|
||||
option_env!("FISH_BUILD_DIR")
|
||||
.map(|d| Cow::Borrowed(Path::new(d)))
|
||||
.unwrap_or(cargo_target_dir())
|
||||
}
|
||||
|
||||
@@ -1,75 +1,53 @@
|
||||
use fish_build_helper::env_var;
|
||||
#[cfg(not(clippy))]
|
||||
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");
|
||||
let mandir = fish_build_helper::fish_build_dir().join("fish-man");
|
||||
let sec1dir = mandir.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.
|
||||
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();
|
||||
let _ = std::fs::create_dir_all(sec1dir.to_str().unwrap());
|
||||
|
||||
#[cfg(not(clippy))]
|
||||
build_man(&man_dir, &sec1_dir, &help_sections_path);
|
||||
build_man(&mandir);
|
||||
}
|
||||
|
||||
#[cfg(not(clippy))]
|
||||
fn build_man(man_dir: &Path, sec1_dir: &Path, help_sections_path: &Path) {
|
||||
fn build_man(man_dir: &Path) {
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
env,
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use fish_build_helper::workspace_root;
|
||||
|
||||
let workspace_root = workspace_root();
|
||||
let doc_src_dir = workspace_root.join("doc_src");
|
||||
|
||||
fish_build_helper::rebuild_if_paths_changed([
|
||||
&workspace_root.join("CHANGELOG.rst"),
|
||||
&workspace_root.join("CONTRIBUTING.rst"),
|
||||
&doc_src_dir,
|
||||
]);
|
||||
let man_str = man_dir.to_str().unwrap();
|
||||
|
||||
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()
|
||||
}
|
||||
macro_rules! as_os_strs {
|
||||
( [ $( $x:expr, )* ] ) => {
|
||||
&[
|
||||
$( as_os_str($x), )*
|
||||
]
|
||||
}
|
||||
}
|
||||
as_os_strs!([
|
||||
"-j",
|
||||
"auto",
|
||||
"-q",
|
||||
"-b",
|
||||
"man",
|
||||
"-c",
|
||||
&doc_src_dir,
|
||||
// doctree path - put this *above* the man1 dir to exclude it.
|
||||
// this is ~6M
|
||||
"-d",
|
||||
&man_dir,
|
||||
&doc_src_dir,
|
||||
&sec1_dir,
|
||||
"-D",
|
||||
&help_sections_arg,
|
||||
])
|
||||
};
|
||||
let sec1_dir = man_dir.join("man1");
|
||||
let sec1_str = sec1_dir.to_str().unwrap();
|
||||
|
||||
let docsrc_dir = workspace_root.join("doc_src");
|
||||
let docsrc_str = docsrc_dir.to_str().unwrap();
|
||||
|
||||
let sphinx_doc_sources = [
|
||||
workspace_root.join("CHANGELOG.rst"),
|
||||
workspace_root.join("CONTRIBUTING.rst"),
|
||||
docsrc_dir.clone(),
|
||||
];
|
||||
fish_build_helper::rebuild_if_paths_changed(sphinx_doc_sources);
|
||||
|
||||
let args = &[
|
||||
"-j", "auto", "-q", "-b", "man", "-c", docsrc_str,
|
||||
// doctree path - put this *above* the man1 dir to exclude it.
|
||||
// this is ~6M
|
||||
"-d", man_str, docsrc_str, sec1_str,
|
||||
];
|
||||
let _ = std::fs::create_dir_all(sec1_str);
|
||||
|
||||
rsconf::rebuild_if_env_changed("FISH_BUILD_DOCS");
|
||||
if env_var("FISH_BUILD_DOCS") == Some("0".to_string()) {
|
||||
if env::var("FISH_BUILD_DOCS") == Ok("0".to_string()) {
|
||||
rsconf::warn!("Skipping man pages because $FISH_BUILD_DOCS is set to 0");
|
||||
return;
|
||||
}
|
||||
@@ -79,24 +57,18 @@ macro_rules! as_os_strs {
|
||||
// - if we skipped the docs with sphinx not installed, installing it would not then build the docs.
|
||||
// That means you need to explicitly set $FISH_BUILD_DOCS=0 (`FISH_BUILD_DOCS=0 cargo install --path .`),
|
||||
// which is unfortunate - but the docs are pretty important because they're also used for --help.
|
||||
let sphinx_build = match Command::new(option_env!("FISH_SPHINX").unwrap_or("sphinx-build"))
|
||||
let sphinx_build = match Command::new("sphinx-build")
|
||||
.args(args)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
if env_var("FISH_BUILD_DOCS") == Some("1".to_string()) {
|
||||
panic!(
|
||||
"Could not find sphinx-build required to build man pages.\n\
|
||||
Install Sphinx or disable building the docs by setting $FISH_BUILD_DOCS=0."
|
||||
);
|
||||
if env::var("FISH_BUILD_DOCS") == Ok("1".to_string()) {
|
||||
panic!("Could not find sphinx-build to build man pages.\nInstall sphinx or disable building the docs by setting $FISH_BUILD_DOCS=0.");
|
||||
}
|
||||
rsconf::warn!(
|
||||
"Could not find sphinx-build required to build man pages. \
|
||||
If you install Sphinx now, you need to trigger a rebuild to include man pages. \
|
||||
For example by running `touch doc_src` followed by the build command."
|
||||
);
|
||||
rsconf::warn!("Cannot find sphinx-build to build man pages.");
|
||||
rsconf::warn!("If you install it now you need to run `cargo clean` and rebuild, or set $FISH_BUILD_DOCS=1 explicitly.");
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -1 +1 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/help_sections.rs"));
|
||||
|
||||
|
||||
@@ -50,9 +50,7 @@ fn append_po_entry_to_file(message: &TokenStream, file_name: &OsString) {
|
||||
.unwrap_or_else(|e| panic!("Could not open file {file_name:?}: {e}"));
|
||||
let message_string = unescape_multiline_rust_string(message.to_string());
|
||||
if message_string.contains('\n') {
|
||||
panic!(
|
||||
"Gettext strings may not contain unescaped newlines. Unescaped newline found in '{message_string}'"
|
||||
)
|
||||
panic!("Gettext strings may not contain unescaped newlines. Unescaped newline found in '{message_string}'")
|
||||
}
|
||||
// Crude check for format strings. This might result in false positives.
|
||||
let format_string_annotation = if message_string.contains('%') {
|
||||
@@ -86,26 +84,23 @@ pub fn gettext_extract(message: TokenStream) -> TokenStream {
|
||||
.next()
|
||||
.expect("gettext_extract got empty token stream. Expected one token.");
|
||||
if token_trees.next().is_some() {
|
||||
panic!(
|
||||
"Invalid number of tokens passed to gettext_extract. Expected one token, but got more."
|
||||
)
|
||||
panic!("Invalid number of tokens passed to gettext_extract. Expected one token, but got more.")
|
||||
}
|
||||
let proc_macro2::TokenTree::Group(group) = first_token else {
|
||||
panic!("Expected group in gettext_extract, but got: {first_token:?}");
|
||||
};
|
||||
let mut group_tokens = group.stream().into_iter();
|
||||
let first_group_token = group_tokens
|
||||
.next()
|
||||
.expect("gettext_extract expected one group token but got none.");
|
||||
if group_tokens.next().is_some() {
|
||||
panic!(
|
||||
"Invalid number of tokens in group passed to gettext_extract. Expected one token, but got more."
|
||||
)
|
||||
}
|
||||
if let proc_macro2::TokenTree::Literal(_) = first_group_token {
|
||||
append_po_entry_to_file(&message, &file_path);
|
||||
if let proc_macro2::TokenTree::Group(group) = first_token {
|
||||
let mut group_tokens = group.stream().into_iter();
|
||||
let first_group_token = group_tokens
|
||||
.next()
|
||||
.expect("gettext_extract expected one group token but got none.");
|
||||
if group_tokens.next().is_some() {
|
||||
panic!("Invalid number of tokens in group passed to gettext_extract. Expected one token, but got more.")
|
||||
}
|
||||
if let proc_macro2::TokenTree::Literal(_) = first_group_token {
|
||||
append_po_entry_to_file(&message, &file_path);
|
||||
} else {
|
||||
panic!("Expected literal in gettext_extract, but got: {first_group_token:?}");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected literal in gettext_extract, but got: {first_group_token:?}");
|
||||
panic!("Expected group in gettext_extract, but got: {first_token:?}");
|
||||
}
|
||||
}
|
||||
message
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsStr,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use fish_build_helper::env_var;
|
||||
|
||||
fn main() {
|
||||
let cache_dir =
|
||||
PathBuf::from(fish_build_helper::fish_build_dir()).join("fish-localization-map-cache");
|
||||
@@ -28,28 +27,29 @@ fn embed_localizations(cache_dir: &Path) {
|
||||
std::fs::create_dir_all(cache_dir).unwrap();
|
||||
|
||||
let localization_map_path =
|
||||
Path::new(&env_var("OUT_DIR").unwrap()).join("localization_maps.rs");
|
||||
Path::new(&env::var("OUT_DIR").unwrap()).join("localization_maps.rs");
|
||||
let mut localization_map_file = BufWriter::new(File::create(&localization_map_path).unwrap());
|
||||
|
||||
// This will become a map which maps from language identifiers to maps containing localizations
|
||||
// for the respective language.
|
||||
let mut catalogs = phf_codegen::Map::new();
|
||||
|
||||
match Command::new("msgfmt").arg("-h").output() {
|
||||
match Command::new("msgfmt").arg("-h").status() {
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
rsconf::warn!(
|
||||
"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."
|
||||
"Cannot find msgfmt to build gettext message catalogs. Localization will not work."
|
||||
);
|
||||
rsconf::warn!(
|
||||
"If you install it now you need to trigger a rebuild to get localization support."
|
||||
);
|
||||
rsconf::warn!(
|
||||
"One way to achieve that is running `touch po` followed by the build command."
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!("Error when trying to run `msgfmt -h`: {e:?}");
|
||||
}
|
||||
Ok(output) => {
|
||||
let has_check_format =
|
||||
String::from_utf8_lossy(&output.stdout).contains("--check-format");
|
||||
Ok(_) => {
|
||||
for dir_entry_result in po_dir.read_dir().unwrap() {
|
||||
let dir_entry = dir_entry_result.unwrap();
|
||||
let po_file_path = dir_entry.path();
|
||||
@@ -91,32 +91,13 @@ fn embed_localizations(cache_dir: &Path) {
|
||||
// Generate the map file.
|
||||
|
||||
// Try to create new MO data and load it into `mo_data`.
|
||||
let mut tmp_mo_file = None;
|
||||
let output = {
|
||||
let mut cmd = &mut Command::new("msgfmt");
|
||||
if has_check_format {
|
||||
cmd = cmd.arg("--check-format");
|
||||
} else {
|
||||
tmp_mo_file = Some(cache_dir.join("messages.mo"));
|
||||
};
|
||||
cmd.arg(format!(
|
||||
"--output-file={}",
|
||||
tmp_mo_file
|
||||
.as_ref()
|
||||
.map_or("-", |path| path.to_str().unwrap())
|
||||
))
|
||||
let output = Command::new("msgfmt")
|
||||
.arg("--check-format")
|
||||
.arg("--output-file=-")
|
||||
.arg(&po_file_path)
|
||||
.output()
|
||||
.unwrap()
|
||||
};
|
||||
if !output.status.success() {
|
||||
panic!(
|
||||
"msgfmt failed:\n{}",
|
||||
String::from_utf8(output.stderr).unwrap()
|
||||
);
|
||||
}
|
||||
let mo_data =
|
||||
tmp_mo_file.map_or(output.stdout, |path| std::fs::read(path).unwrap());
|
||||
.unwrap();
|
||||
let mo_data = output.stdout;
|
||||
|
||||
// Extract map from MO data.
|
||||
let language_localizations = parse_mo_file(&mo_data).unwrap();
|
||||
|
||||
@@ -15,7 +15,7 @@ pub enum Arg<'a> {
|
||||
#[cfg(feature = "widestring")]
|
||||
WString(WString),
|
||||
UInt(u64),
|
||||
SInt(i64),
|
||||
SInt(i64, u8), // signed integers track their width as the number of bits
|
||||
Float(f64),
|
||||
USizeRef(&'a mut usize), // for use with %n
|
||||
}
|
||||
@@ -59,7 +59,7 @@ pub fn as_str<'s>(&'s self, storage: &'s mut String) -> Result<&'s str, Error>
|
||||
pub fn as_uint(&self) -> Result<u64, Error> {
|
||||
match *self {
|
||||
Arg::UInt(u) => Ok(u),
|
||||
Arg::SInt(i) => i.try_into().map_err(|_| Error::Overflow),
|
||||
Arg::SInt(i, _w) => i.try_into().map_err(|_| Error::Overflow),
|
||||
_ => Err(Error::BadArgType),
|
||||
}
|
||||
}
|
||||
@@ -68,18 +68,25 @@ pub fn as_uint(&self) -> Result<u64, Error> {
|
||||
pub fn as_sint(&self) -> Result<i64, Error> {
|
||||
match *self {
|
||||
Arg::UInt(u) => u.try_into().map_err(|_| Error::Overflow),
|
||||
Arg::SInt(i) => Ok(i),
|
||||
Arg::SInt(i, _w) => Ok(i),
|
||||
_ => Err(Error::BadArgType),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwraps [`Arg::UInt`] to [`u64`].
|
||||
/// Unwraps [`Arg::SInt`] and casts the [`i64`] to [`u64`].
|
||||
/// Calling this on other variants of `[Arg]` is an error.
|
||||
pub fn as_wrapping_sint(&self) -> Result<u64, Error> {
|
||||
// If this is a signed value, then return the sign (true if negative) and the magnitude,
|
||||
// masked to the value's width. This allows for e.g. -1 to be returned as 0xFF, 0xFFFF, etc.
|
||||
// depending on the original width.
|
||||
// If this is an unsigned value, simply return (false, u64).
|
||||
pub fn as_wrapping_sint(&self) -> Result<(bool, u64), Error> {
|
||||
match *self {
|
||||
Arg::UInt(u) => Ok(u),
|
||||
Arg::SInt(i) => Ok(i as u64),
|
||||
Arg::UInt(u) => Ok((false, u)),
|
||||
Arg::SInt(i, w) => {
|
||||
// Need to shift twice in case w is 64.
|
||||
debug_assert!(w > 0);
|
||||
let mask = ((1u64 << (w - 1)) << 1).wrapping_sub(1);
|
||||
let ui = (i as u64) & mask;
|
||||
Ok((i < 0, ui))
|
||||
}
|
||||
_ => Err(Error::BadArgType),
|
||||
}
|
||||
}
|
||||
@@ -90,7 +97,7 @@ pub fn as_float(&self) -> Result<f64, Error> {
|
||||
match *self {
|
||||
Arg::Float(f) => Ok(f),
|
||||
Arg::UInt(u) => Ok(u as f64),
|
||||
Arg::SInt(i) => Ok(i as f64),
|
||||
Arg::SInt(i, _w) => Ok(i as f64),
|
||||
_ => Err(Error::BadArgType),
|
||||
}
|
||||
}
|
||||
@@ -174,7 +181,7 @@ macro_rules! impl_to_arg {
|
||||
$(
|
||||
impl<'a> ToArg<'a> for $t {
|
||||
fn to_arg(self) -> Arg<'a> {
|
||||
Arg::SInt(self as i64)
|
||||
Arg::SInt(self as i64, <$t>::BITS as u8)
|
||||
}
|
||||
}
|
||||
)*
|
||||
@@ -204,6 +211,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_to_arg() {
|
||||
const SIZE_WIDTH: u8 = isize::BITS as u8;
|
||||
|
||||
assert!(matches!("test".to_arg(), Arg::Str("test")));
|
||||
assert!(matches!(String::from("test").to_arg(), Arg::Str(_)));
|
||||
#[cfg(feature = "widestring")]
|
||||
@@ -215,17 +224,17 @@ fn test_to_arg() {
|
||||
assert!(matches!('x'.to_arg(), Arg::UInt(120)));
|
||||
let mut usize_val: usize = 0;
|
||||
assert!(matches!((&mut usize_val).to_arg(), Arg::USizeRef(_)));
|
||||
assert!(matches!(42i8.to_arg(), Arg::SInt(42)));
|
||||
assert!(matches!(42i16.to_arg(), Arg::SInt(42)));
|
||||
assert!(matches!(42i32.to_arg(), Arg::SInt(42)));
|
||||
assert!(matches!(42i64.to_arg(), Arg::SInt(42)));
|
||||
assert!(matches!(42isize.to_arg(), Arg::SInt(42)));
|
||||
assert!(matches!(42i8.to_arg(), Arg::SInt(42, 8)));
|
||||
assert!(matches!(42i16.to_arg(), Arg::SInt(42, 16)));
|
||||
assert!(matches!(42i32.to_arg(), Arg::SInt(42, 32)));
|
||||
assert!(matches!(42i64.to_arg(), Arg::SInt(42, 64)));
|
||||
assert!(matches!(42isize.to_arg(), Arg::SInt(42, SIZE_WIDTH)));
|
||||
|
||||
assert_eq!((-42i8).to_arg(), Arg::SInt(-42));
|
||||
assert_eq!((-42i16).to_arg(), Arg::SInt(-42));
|
||||
assert_eq!((-42i32).to_arg(), Arg::SInt(-42));
|
||||
assert_eq!((-42i64).to_arg(), Arg::SInt(-42));
|
||||
assert_eq!((-42isize).to_arg(), Arg::SInt(-42));
|
||||
assert_eq!((-42i8).to_arg(), Arg::SInt(-42, 8));
|
||||
assert_eq!((-42i16).to_arg(), Arg::SInt(-42, 16));
|
||||
assert_eq!((-42i32).to_arg(), Arg::SInt(-42, 32));
|
||||
assert_eq!((-42i64).to_arg(), Arg::SInt(-42, 64));
|
||||
assert_eq!((-42isize).to_arg(), Arg::SInt(-42, SIZE_WIDTH));
|
||||
|
||||
assert!(matches!(42u8.to_arg(), Arg::UInt(42)));
|
||||
assert!(matches!(42u16.to_arg(), Arg::UInt(42)));
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
mod tests;
|
||||
|
||||
use super::locale::Locale;
|
||||
use super::printf_impl::{ConversionSpec, Error, ModifierFlags, pad};
|
||||
use decimal::{DIGIT_WIDTH, Decimal, DigitLimit};
|
||||
use super::printf_impl::{pad, ConversionSpec, Error, ModifierFlags};
|
||||
use decimal::{Decimal, DigitLimit, DIGIT_WIDTH};
|
||||
use std::cmp::min;
|
||||
use std::fmt::Write;
|
||||
|
||||
@@ -279,6 +279,7 @@ fn format_a(mut y: f64, params: FormatParams<'_, impl Write>) -> Result<usize, E
|
||||
|
||||
// Compute the number of hex digits in the mantissa after the decimal.
|
||||
// -1 for leading 1 bit (we are to the range [1, 2)), then divide by 4, rounding up.
|
||||
#[allow(unknown_lints)] // for old clippy
|
||||
#[allow(clippy::manual_div_ceil)]
|
||||
const MANTISSA_HEX_DIGITS: usize = (MANTISSA_BITS - 1 + 3) / 4;
|
||||
if had_prec && prec < MANTISSA_HEX_DIGITS {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
mod fmt_fp;
|
||||
mod printf_impl;
|
||||
pub use printf_impl::{Error, FormatString, sprintf_locale};
|
||||
pub use printf_impl::{sprintf_locale, Error, FormatString};
|
||||
pub mod locale;
|
||||
pub use locale::{Locale, C_LOCALE, EN_US_LOCALE};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -66,7 +66,11 @@ fn next_group_size(&self, digits_left: usize) -> usize {
|
||||
// Divide remaining digits by repeat_group.
|
||||
// Apply any remainder to the first group.
|
||||
let res = (digits_left - accum) % (repeat_group as usize);
|
||||
if res > 0 { res } else { repeat_group as usize }
|
||||
if res > 0 {
|
||||
res
|
||||
} else {
|
||||
repeat_group as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,91 +122,86 @@ pub fn separator_count(&self, digits_count: usize) -> usize {
|
||||
group_repeat: true,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{C_LOCALE, EN_US_LOCALE, Locale};
|
||||
#[test]
|
||||
fn test_apply_grouping() {
|
||||
let input = "123456789";
|
||||
let mut result: String;
|
||||
|
||||
#[test]
|
||||
fn test_apply_grouping() {
|
||||
let input = "123456789";
|
||||
let mut result: String;
|
||||
// en_US has commas.
|
||||
assert_eq!(EN_US_LOCALE.thousands_sep, Some(','));
|
||||
result = EN_US_LOCALE.apply_grouping(input);
|
||||
assert_eq!(result, "123,456,789");
|
||||
|
||||
// en_US has commas.
|
||||
assert_eq!(EN_US_LOCALE.thousands_sep, Some(','));
|
||||
result = EN_US_LOCALE.apply_grouping(input);
|
||||
assert_eq!(result, "123,456,789");
|
||||
// Test weird locales.
|
||||
let input: &str = "1234567890123456";
|
||||
let mut locale: Locale = C_LOCALE;
|
||||
locale.thousands_sep = Some('!');
|
||||
|
||||
// Test weird locales.
|
||||
let input: &str = "1234567890123456";
|
||||
let mut locale: Locale = C_LOCALE;
|
||||
locale.thousands_sep = Some('!');
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = false;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1234567!8!901!23456");
|
||||
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = false;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1234567!8!901!23456");
|
||||
// group_repeat doesn't matter because trailing group is 0
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = true;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1234567!8!901!23456");
|
||||
|
||||
// group_repeat doesn't matter because trailing group is 0
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = true;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1234567!8!901!23456");
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = false;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "12345!67!8!901!23456");
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = false;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "12345!67!8!901!23456");
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = true;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1!23!45!67!8!901!23456");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_thousands_grouping_length_panics_if_no_sep() {
|
||||
// We should panic if we try to group with no thousands separator.
|
||||
assert_eq!(C_LOCALE.thousands_sep, None);
|
||||
C_LOCALE.apply_grouping("123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_thousands_grouping_length() {
|
||||
fn validate_grouping_length_hint(locale: Locale, mut input: &str) {
|
||||
loop {
|
||||
let expected = locale.separator_count(input.len()) + input.len();
|
||||
let actual = locale.apply_grouping(input).len();
|
||||
assert_eq!(expected, actual);
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input = &input[1..];
|
||||
}
|
||||
}
|
||||
|
||||
validate_grouping_length_hint(EN_US_LOCALE, "123456789");
|
||||
|
||||
// Test weird locales.
|
||||
let input = "1234567890123456";
|
||||
let mut locale: Locale = C_LOCALE;
|
||||
locale.thousands_sep = Some('!');
|
||||
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = false;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
// group_repeat doesn't matter because trailing group is 0
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = true;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = false;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = true;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
}
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = true;
|
||||
result = locale.apply_grouping(input);
|
||||
assert_eq!(result, "1!23!45!67!8!901!23456");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_thousands_grouping_length_panics_if_no_sep() {
|
||||
// We should panic if we try to group with no thousands separator.
|
||||
assert_eq!(C_LOCALE.thousands_sep, None);
|
||||
C_LOCALE.apply_grouping("123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_thousands_grouping_length() {
|
||||
fn validate_grouping_length_hint(locale: Locale, mut input: &str) {
|
||||
loop {
|
||||
let expected = locale.separator_count(input.len()) + input.len();
|
||||
let actual = locale.apply_grouping(input).len();
|
||||
assert_eq!(expected, actual);
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input = &input[1..];
|
||||
}
|
||||
}
|
||||
|
||||
validate_grouping_length_hint(EN_US_LOCALE, "123456789");
|
||||
|
||||
// Test weird locales.
|
||||
let input = "1234567890123456";
|
||||
let mut locale: Locale = C_LOCALE;
|
||||
locale.thousands_sep = Some('!');
|
||||
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = false;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
// group_repeat doesn't matter because trailing group is 0
|
||||
locale.grouping = [5, 3, 1, 0];
|
||||
locale.group_repeat = true;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = false;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
|
||||
locale.grouping = [5, 3, 1, 2];
|
||||
locale.group_repeat = true;
|
||||
validate_grouping_length_hint(locale, input);
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ pub fn sprintf_locale(
|
||||
// If someone passes us a negative value, format it with the width
|
||||
// we were given.
|
||||
let lower = conv_spec.is_lower();
|
||||
let uint = arg.as_wrapping_sint()?;
|
||||
let (_, uint) = arg.as_wrapping_sint()?;
|
||||
if uint != 0 {
|
||||
if flags.alt_form {
|
||||
prefix = if lower { "0x" } else { "0X" };
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::arg::ToArg;
|
||||
use crate::locale::{C_LOCALE, EN_US_LOCALE, Locale};
|
||||
use crate::{Error, FormatString, sprintf_locale};
|
||||
use crate::locale::{Locale, C_LOCALE, EN_US_LOCALE};
|
||||
use crate::{sprintf_locale, Error, FormatString};
|
||||
use libc::c_char;
|
||||
use std::f64::consts::{E, PI, TAU};
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
|
||||
// sprintf, checking length
|
||||
@@ -78,7 +77,7 @@ fn write_str(&mut self, _s: &str) -> fmt::Result {
|
||||
#[test]
|
||||
fn smoke() {
|
||||
assert_fmt!("Hello, %s!", "world" => "Hello, world!");
|
||||
assert_fmt!("Hello, %ls!", "world" => "Hello, world!"); // length modifier
|
||||
assert_fmt!("Hello, %ls!", "world" => "Hello, world!");
|
||||
assert_fmt!("Hello, world! %d %%%%", 3 => "Hello, world! 3 %%");
|
||||
assert_fmt!("" => "");
|
||||
}
|
||||
@@ -226,7 +225,7 @@ fn test_int() {
|
||||
assert_fmt!("%d", -123 => "-123");
|
||||
assert_fmt!("~%d~", 148 => "~148~");
|
||||
assert_fmt!("00%dxx", -91232 => "00-91232xx");
|
||||
assert_fmt!("%x", -9232 => "ffffffffffffdbf0");
|
||||
assert_fmt!("%x", -9232 => "ffffdbf0");
|
||||
assert_fmt!("%X", 432 => "1B0");
|
||||
assert_fmt!("%09X", 432 => "0000001B0");
|
||||
assert_fmt!("%9X", 432 => " 1B0");
|
||||
@@ -235,7 +234,6 @@ fn test_int() {
|
||||
assert_fmt!("%2o", 4 => " 4");
|
||||
assert_fmt!("% 12d", -4 => " -4");
|
||||
assert_fmt!("% 12d", 48 => " 48");
|
||||
// with length modifier
|
||||
assert_fmt!("%ld", -4_i64 => "-4");
|
||||
assert_fmt!("%lld", -4_i64 => "-4");
|
||||
assert_fmt!("%lX", -4_i64 => "FFFFFFFFFFFFFFFC");
|
||||
@@ -250,7 +248,6 @@ fn test_int() {
|
||||
assert_fmt!("%9X", 492 => " 1EC");
|
||||
assert_fmt!("% 12u", 4 => " 4");
|
||||
assert_fmt!("% 12u", 48 => " 48");
|
||||
// with length modifier
|
||||
assert_fmt!("%lu", 4_u64 => "4");
|
||||
assert_fmt!("%llu", 4_u64 => "4");
|
||||
assert_fmt!("%lX", 4_u64 => "4");
|
||||
@@ -417,7 +414,6 @@ fn test_float() {
|
||||
assert_fmt1!("%f", 0.0, "0.000000");
|
||||
assert_fmt1!("%g", 0.0, "0");
|
||||
assert_fmt1!("%#g", 0.0, "0.00000");
|
||||
// with length modifier
|
||||
assert_fmt1!("%la", 0.0, "0x0p+0");
|
||||
assert_fmt1!("%le", 0.0, "0.000000e+00");
|
||||
assert_fmt1!("%lf", 0.0, "0.000000");
|
||||
@@ -434,7 +430,7 @@ fn test_float() {
|
||||
assert_fmt1!("%.4f", 1.03125, "1.0312"); /* 0x1.08p0 */
|
||||
assert_fmt1!("%.2f", 1.375, "1.38");
|
||||
assert_fmt1!("%.1f", 1.375, "1.4");
|
||||
assert_fmt1!("%.1lf", 1.375, "1.4"); // length modifier
|
||||
assert_fmt1!("%.1lf", 1.375, "1.4");
|
||||
assert_fmt1!("%.15f", 1.1, "1.100000000000000");
|
||||
assert_fmt1!("%.16f", 1.1, "1.1000000000000001");
|
||||
assert_fmt1!("%.17f", 1.1, "1.10000000000000009");
|
||||
@@ -759,8 +755,8 @@ fn test_errors() {
|
||||
sprintf_err!("%1", => BadFormatString);
|
||||
sprintf_err!("%%%k", => BadFormatString);
|
||||
sprintf_err!("%B", => BadFormatString);
|
||||
sprintf_err!("%lC", 'q' => BadFormatString); // length modifier
|
||||
sprintf_err!("%lS", 'q' => BadFormatString); // length modifier
|
||||
sprintf_err!("%lC", 'q' => BadFormatString);
|
||||
sprintf_err!("%lS", 'q' => BadFormatString);
|
||||
sprintf_err!("%d", => MissingArg);
|
||||
sprintf_err!("%d %u", 1 => MissingArg);
|
||||
sprintf_err!("%*d", 5 => MissingArg);
|
||||
@@ -856,20 +852,25 @@ fn test_float_hex_prec() {
|
||||
// Note that our hex float formatting rounds according to the rounding mode,
|
||||
// while libc may not; as a result we may differ in the last digit. So this
|
||||
// requires manual comparison.
|
||||
let mut c_storage = [0u8; 256];
|
||||
let c_storage_ptr = c_storage.as_mut_ptr() as *mut c_char;
|
||||
let mut rust_str = String::with_capacity(256);
|
||||
|
||||
let mut c_storage = [0u8; 256];
|
||||
let mut libc_sprintf = libc_sprintf_one_float_with_precision(&mut c_storage, c"%.*a");
|
||||
|
||||
let c_fmt = b"%.*a\0".as_ptr() as *const c_char;
|
||||
let mut failed = false;
|
||||
for sign in [1.0, -1.0].into_iter() {
|
||||
for mut v in [0.0, 0.5, 1.0, 1.5, PI, TAU, E].into_iter() {
|
||||
v *= sign;
|
||||
for preci in 1..=200_usize {
|
||||
for preci in 1..=200_i32 {
|
||||
rust_str.clear();
|
||||
crate::sprintf!(=> &mut rust_str, "%.*a", preci, v);
|
||||
|
||||
let printf_str = libc_sprintf(preci, v);
|
||||
let printf_str = unsafe {
|
||||
let len = libc::snprintf(c_storage_ptr, c_storage.len(), c_fmt, preci, v);
|
||||
assert!(len >= 0);
|
||||
let sl = std::slice::from_raw_parts(c_storage_ptr as *const u8, len as usize);
|
||||
std::str::from_utf8(sl).unwrap()
|
||||
};
|
||||
if rust_str != printf_str {
|
||||
println!(
|
||||
"Our printf and libc disagree on hex formatting of float: {v}
|
||||
@@ -885,27 +886,14 @@ fn test_float_hex_prec() {
|
||||
assert!(!failed);
|
||||
}
|
||||
|
||||
fn libc_sprintf_one_float_with_precision<'a>(
|
||||
storage: &'a mut [u8],
|
||||
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);
|
||||
assert!(len >= 0);
|
||||
let sl = std::slice::from_raw_parts(storage_ptr as *const u8, len as usize);
|
||||
std::str::from_utf8(sl).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_exhaustive(rust_fmt: &str, c_fmt: &CStr) {
|
||||
fn test_exhaustive(rust_fmt: &str, c_fmt: *const c_char) {
|
||||
// "There's only 4 billion floats so test them all."
|
||||
// This tests a format string expected to be of the form "%.*g" or "%.*e".
|
||||
// That is, it takes a precision and a double.
|
||||
println!("Testing {rust_fmt}");
|
||||
let mut rust_str = String::with_capacity(128);
|
||||
let mut c_storage = [0u8; 128];
|
||||
let mut libc_sprintf = libc_sprintf_one_float_with_precision(&mut c_storage, c_fmt);
|
||||
let c_storage_ptr = c_storage.as_mut_ptr() as *mut c_char;
|
||||
|
||||
for i in 0..=u32::MAX {
|
||||
if i % 1000000 == 0 {
|
||||
@@ -917,7 +905,12 @@ fn test_exhaustive(rust_fmt: &str, c_fmt: &CStr) {
|
||||
rust_str.clear();
|
||||
crate::sprintf!(=> &mut rust_str, rust_fmt, preci, ff);
|
||||
|
||||
let printf_str = libc_sprintf(preci, ff);
|
||||
let printf_str = unsafe {
|
||||
let len = libc::snprintf(c_storage_ptr, c_storage.len(), c_fmt, preci, ff);
|
||||
assert!(len >= 0);
|
||||
let sl = std::slice::from_raw_parts(c_storage_ptr as *const u8, len as usize);
|
||||
std::str::from_utf8(sl).unwrap()
|
||||
};
|
||||
if rust_str != printf_str {
|
||||
println!(
|
||||
"Rust and libc disagree on formatting float {i:x}: {ff}\n
|
||||
@@ -936,19 +929,19 @@ fn test_exhaustive(rust_fmt: &str, c_fmt: &CStr) {
|
||||
#[ignore]
|
||||
fn test_float_g_exhaustive() {
|
||||
// To run: cargo test test_float_g_exhaustive --release -- --ignored --nocapture
|
||||
test_exhaustive("%.*g", c"%.*g");
|
||||
test_exhaustive("%.*g", b"%.*g\0".as_ptr() as *const c_char);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_float_e_exhaustive() {
|
||||
// To run: cargo test test_float_e_exhaustive --release -- --ignored --nocapture
|
||||
test_exhaustive("%.*e", c"%.*e");
|
||||
test_exhaustive("%.*e", b"%.*e\0".as_ptr() as *const c_char);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_float_f_exhaustive() {
|
||||
// To run: cargo test test_float_f_exhaustive --release -- --ignored --nocapture
|
||||
test_exhaustive("%.*f", c"%.*f");
|
||||
test_exhaustive("%.*f", b"%.*f\0".as_ptr() as *const c_char);
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[package]
|
||||
name = "fish-tempfile"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
nix = { workspace = true, features = ["fs", "feature"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,127 +0,0 @@
|
||||
use std::{fs::File, path::PathBuf};
|
||||
|
||||
pub struct TempFile {
|
||||
file: File,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl TempFile {
|
||||
pub fn get(&self) -> &File {
|
||||
&self.file
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> &mut File {
|
||||
&mut self.file
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempFile {
|
||||
fn drop(&mut self) {
|
||||
let _ = std::fs::remove_file(&self.path);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TempDir {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl TempDir {
|
||||
pub fn path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempDir {
|
||||
fn drop(&mut self) {
|
||||
let _ = std::fs::remove_dir_all(&self.path);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_tmpdir() -> PathBuf {
|
||||
PathBuf::from(std::env::var_os("TMPDIR").unwrap_or("/tmp".into()))
|
||||
}
|
||||
|
||||
fn get_template() -> PathBuf {
|
||||
get_tmpdir().join("fish_tmp_XXXXXX")
|
||||
}
|
||||
|
||||
/// Tries to create a new temporary file using `mkstemp`.
|
||||
/// 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);
|
||||
Ok(TempFile { file, path })
|
||||
}
|
||||
|
||||
/// Tries to create a new temporary directory using `mkdtemp`.
|
||||
/// 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())?;
|
||||
Ok(TempDir { path })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Seek, Write},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn create_tempfile() {
|
||||
super::new_file().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "file should no longer exist")]
|
||||
fn use_tempfile() {
|
||||
let mut tempfile = super::new_file().unwrap();
|
||||
let expected_content = "test";
|
||||
{
|
||||
let file = tempfile.get_mut();
|
||||
file.write_all(expected_content.as_bytes()).unwrap();
|
||||
file.seek(std::io::SeekFrom::Start(0)).unwrap();
|
||||
}
|
||||
let mut actual_content = String::new();
|
||||
{
|
||||
let mut file = tempfile.get();
|
||||
file.read_to_string(&mut actual_content).unwrap();
|
||||
}
|
||||
let path = tempfile.path().to_owned();
|
||||
drop(tempfile);
|
||||
assert_eq!(expected_content, actual_content);
|
||||
File::open(&path).expect("file should no longer exist");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_tempdir() {
|
||||
super::new_dir().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "file should no longer exist")]
|
||||
fn use_tempdir() {
|
||||
let tempdir = super::new_dir().unwrap();
|
||||
let file_path = tempdir.path().join("foo");
|
||||
let expected_content = "test";
|
||||
{
|
||||
let mut file = File::create(&file_path).unwrap();
|
||||
file.write_all(expected_content.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let mut file = File::open(&file_path).unwrap();
|
||||
let mut actual_content = String::new();
|
||||
file.read_to_string(&mut actual_content).unwrap();
|
||||
assert_eq!(expected_content, actual_content);
|
||||
}
|
||||
drop(tempdir);
|
||||
File::open(&file_path).expect("file should no longer exist");
|
||||
}
|
||||
}
|
||||
7
debian/control
vendored
7
debian/control
vendored
@@ -4,12 +4,11 @@ Priority: optional
|
||||
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
|
||||
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||
Build-Depends: debhelper (>= 12),
|
||||
# -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),
|
||||
cargo (>= 0.66) | cargo-mozilla (>= 0.66),
|
||||
cmake (>= 3.15.0) | cmake-mozilla (>= 3.15.0),
|
||||
gettext,
|
||||
libpcre2-dev,
|
||||
rustc (>= 1.85) | rustc-web (>= 1.85) | rustc-1.85,
|
||||
rustc (>= 1.70),
|
||||
# Test dependencies
|
||||
locales-all,
|
||||
ncurses-base,
|
||||
|
||||
8
debian/rules
vendored
8
debian/rules
vendored
@@ -8,15 +8,13 @@ export DH_VERBOSE=1
|
||||
export DEB_BUILD_MAINT_OPTIONS=optimize=-lto
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake --builddirectory=build
|
||||
dh $@
|
||||
|
||||
# Setting the build system is still required, because otherwise the GNUmakefile gets picked up
|
||||
override_dh_auto_configure:
|
||||
ln -s cargo-vendor/vendor vendor
|
||||
ln -s cargo-vendor/.cargo .cargo
|
||||
dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DRust_CARGO=$$(command -v cargo-1.85 || command -v cargo) \
|
||||
-DRust_COMPILER=$$(command -v rustc-1.85 || command -v rustc)
|
||||
dh_auto_configure --buildsystem=cmake -- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean --exclude=Cargo.toml.orig
|
||||
@@ -24,4 +22,4 @@ override_dh_clean:
|
||||
-unlink vendor
|
||||
|
||||
override_dh_auto_test:
|
||||
cd build && make fish_run_tests
|
||||
make fish_run_tests
|
||||
|
||||
@@ -18,7 +18,7 @@ We use forks of the last two - see the [FFI section](#ffi) below. No special act
|
||||
|
||||
### Build Dependencies
|
||||
|
||||
fish-shell currently depends on Rust 1.85 or later. To install Rust, follow https://rustup.rs.
|
||||
fish-shell currently depends on Rust 1.70 or later. To install Rust, follow https://rustup.rs.
|
||||
|
||||
### Build via CMake
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-_:
|
||||
|
||||
_ - call fish's translations
|
||||
============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-abbr:
|
||||
|
||||
abbr - manage fish abbreviations
|
||||
================================
|
||||
|
||||
@@ -8,8 +10,8 @@ Synopsis
|
||||
|
||||
abbr --add NAME [--position command | anywhere] [-r | --regex PATTERN] [-c | --command COMMAND]
|
||||
[--set-cursor[=MARKER]] ([-f | --function FUNCTION] | EXPANSION)
|
||||
abbr --erase [ [-c | --command COMMAND]... ] NAME ...
|
||||
abbr --rename [ [-c | --command COMMAND]... ] OLD_WORD NEW_WORD
|
||||
abbr --erase NAME ...
|
||||
abbr --rename OLD_WORD NEW_WORD
|
||||
abbr --show
|
||||
abbr --list
|
||||
abbr --query NAME ...
|
||||
@@ -134,10 +136,9 @@ Other subcommands
|
||||
|
||||
::
|
||||
|
||||
abbr --rename [ [-c | --command COMMAND]... ] OLD_NAME NEW_NAME
|
||||
abbr --rename OLD_NAME NEW_NAME
|
||||
|
||||
Renames an abbreviation, from *OLD_NAME* to *NEW_NAME*.
|
||||
For command-specific abbreviations, the ``--command`` options must be provided to disambiguate which abbreviation to rename.
|
||||
Renames an abbreviation, from *OLD_NAME* to *NEW_NAME*
|
||||
|
||||
::
|
||||
|
||||
@@ -153,10 +154,9 @@ Prints the names of all abbreviation
|
||||
|
||||
::
|
||||
|
||||
abbr [-e | --erase] [ [-c | --command COMMAND]... ] NAME ...
|
||||
abbr [-e | --erase] NAME
|
||||
|
||||
Erases the abbreviation with the given name.
|
||||
For command-specific abbreviations, the ``--command`` options must be provided to disambiguate which abbreviation to rename.
|
||||
Erases the abbreviation with the given name
|
||||
|
||||
::
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-alias:
|
||||
|
||||
alias - create a function
|
||||
=========================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-and:
|
||||
|
||||
and - conditionally execute a command
|
||||
=====================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-argparse:
|
||||
|
||||
argparse - parse options passed to a fish script or function
|
||||
============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-begin:
|
||||
|
||||
begin - start a new block of code
|
||||
=================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-bg:
|
||||
|
||||
bg - send jobs to background
|
||||
============================
|
||||
|
||||
@@ -40,6 +42,6 @@ The typical use is to run something, stop it with ctrl-z, and then continue it i
|
||||
|
||||
If only 123 and 789 exist, it will still background them and print an error about 456.
|
||||
|
||||
``bg 123 banana`` or ``bg banana 123`` will complain that "banana" is not a valid process ID.
|
||||
``bg 123 banana`` or ``bg banana 123`` will complain that "banana" is not a valid job specifier.
|
||||
|
||||
``bg %2`` will background job 2.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-bind:
|
||||
|
||||
bind - handle fish key bindings
|
||||
===============================
|
||||
Synopsis
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-block:
|
||||
|
||||
block - temporarily block delivery of events
|
||||
============================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-break:
|
||||
|
||||
break - stop the current inner loop
|
||||
===================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-breakpoint:
|
||||
|
||||
breakpoint - launch debug mode
|
||||
==============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-builtin:
|
||||
|
||||
builtin - run a builtin command
|
||||
===============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-case:
|
||||
|
||||
case - conditionally execute a block of commands
|
||||
================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-cd:
|
||||
|
||||
cd - change directory
|
||||
=====================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-cdh:
|
||||
|
||||
cdh - change to a recently visited directory
|
||||
============================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-command:
|
||||
|
||||
command - run a program
|
||||
=======================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-commandline:
|
||||
|
||||
commandline - set or get the current command line buffer
|
||||
========================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-complete:
|
||||
|
||||
complete - edit command-specific tab-completions
|
||||
================================================
|
||||
|
||||
@@ -14,7 +16,7 @@ Description
|
||||
|
||||
``complete`` defines, removes or lists completions for a command.
|
||||
|
||||
For an introduction to writing your own completions, see :doc:`Writing your own completions <../completions>` in
|
||||
For an introduction to writing your own completions, see :ref:`Writing your own completions <completion-own>` in
|
||||
the fish manual.
|
||||
|
||||
The following options are available:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-contains:
|
||||
|
||||
contains - test if a word is present in a list
|
||||
==============================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-continue:
|
||||
|
||||
continue - skip the remainder of the current iteration of the current inner loop
|
||||
================================================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-count:
|
||||
|
||||
count - count the number of elements of a list
|
||||
================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-dirh:
|
||||
|
||||
dirh - print directory history
|
||||
==============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-dirs:
|
||||
|
||||
dirs - print directory stack
|
||||
============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-disown:
|
||||
|
||||
disown - remove a process from the list of jobs
|
||||
===============================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-echo:
|
||||
|
||||
echo - display a line of text
|
||||
=============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-else:
|
||||
|
||||
else - execute command if a condition is not met
|
||||
================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-emit:
|
||||
|
||||
emit - emit a generic event
|
||||
===========================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-end:
|
||||
|
||||
end - end a block of commands
|
||||
=============================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-eval:
|
||||
|
||||
eval - evaluate the specified commands
|
||||
======================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-exec:
|
||||
|
||||
exec - execute command in current process
|
||||
=========================================
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
.. _cmd-exit:
|
||||
.. program::exit
|
||||
|
||||
exit - exit the shell
|
||||
=====================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-export:
|
||||
|
||||
export - compatibility function for exporting variables
|
||||
=======================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-false:
|
||||
|
||||
false - return an unsuccessful result
|
||||
=====================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fg:
|
||||
|
||||
fg - bring job to foreground
|
||||
============================
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
.. _cmd-fish:
|
||||
.. program::fish
|
||||
|
||||
fish - the friendly interactive shell
|
||||
=====================================
|
||||
|
||||
@@ -15,7 +18,7 @@ Description
|
||||
:command:`fish` is a command-line shell written mainly with interactive use in mind.
|
||||
This page briefly describes the options for invoking :command:`fish`.
|
||||
The :ref:`full manual <intro>` is available in HTML by using the :command:`help` command from inside fish, and in the `fish-doc(1)` man page.
|
||||
The :doc:`tutorial <../tutorial>` is available as HTML via ``help tutorial`` or in `man fish-tutorial`.
|
||||
The :ref:`tutorial <tutorial>` is available as HTML via ``help tutorial`` or in `man fish-tutorial`.
|
||||
|
||||
|
||||
The following options are available:
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
.. _cmd-fish_add_path:
|
||||
.. program::fish_add_path
|
||||
|
||||
fish_add_path - add to the path
|
||||
==============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_breakpoint_prompt:
|
||||
|
||||
fish_breakpoint_prompt - define the prompt when stopped at a breakpoint
|
||||
=======================================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_clipboard_copy:
|
||||
|
||||
fish_clipboard_copy - copy text to the system's clipboard
|
||||
==============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_clipboard_paste:
|
||||
|
||||
fish_clipboard_paste - get text from the system's clipboard
|
||||
==============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_command_not_found:
|
||||
|
||||
fish_command_not_found - what to do when a command wasn't found
|
||||
===============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_config:
|
||||
|
||||
fish_config - start the web-based configuration interface
|
||||
=========================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_default_key_bindings:
|
||||
|
||||
fish_default_key_bindings - set emacs key bindings for fish
|
||||
===============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_git_prompt:
|
||||
|
||||
fish_git_prompt - output git information for use in a prompt
|
||||
============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_greeting:
|
||||
|
||||
fish_greeting - display a welcome message in interactive shells
|
||||
===============================================================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-fish_hg_prompt:
|
||||
|
||||
fish_hg_prompt - output Mercurial information for use in a prompt
|
||||
=================================================================
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user