mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 01:21:16 -03:00
Compare commits
58 Commits
4.3.2
...
Integratio
| 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-15-0-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
|
||||
|
||||
@@ -14,6 +14,7 @@ indent_style = tab
|
||||
|
||||
[*.{md,rst}]
|
||||
max_line_length = unset
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.sh]
|
||||
indent_size = 4
|
||||
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -14,6 +14,8 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
/build_tools/make_tarball.sh export-ignore
|
||||
/debian export-ignore
|
||||
/debian/* export-ignore
|
||||
/.github export-ignore
|
||||
/.github/* export-ignore
|
||||
/.builds export-ignore
|
||||
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
||||
github:
|
||||
- krobelus
|
||||
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'
|
||||
23
.github/actions/install-sphinx/action.yml
vendored
23
.github/actions/install-sphinx/action.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: Install sphinx
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: bash
|
||||
run: |
|
||||
set -x
|
||||
sudo pip install uv --break-system-packages
|
||||
command -v uv
|
||||
command -v uvx
|
||||
# Check that pyproject.toml and the lock file are in sync.
|
||||
# TODO Use "uv" to install Python as well.
|
||||
: 'Note that --no-managed-python below would be implied but be explicit'
|
||||
uv='env UV_PYTHON=python uv --no-managed-python'
|
||||
$uv lock --check --exclude-newer="$(awk -F'"' <uv.lock '/^exclude-newer[[:space:]]*=/ {print $2}')"
|
||||
# Install globally.
|
||||
sudo $uv pip install --group=dev --system --break-system-packages
|
||||
# Smoke test.
|
||||
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.92 ;; # 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 }}
|
||||
24
.github/workflows/lint-dependencies.yml
vendored
24
.github/workflows/lint-dependencies.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Lint Dependencies
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/lint-dependencies.yml'
|
||||
- 'Cargo.lock'
|
||||
- '**/Cargo.toml'
|
||||
- 'deny.toml'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/lint-dependencies.yml'
|
||||
- 'Cargo.lock'
|
||||
- '**/Cargo.toml'
|
||||
- 'deny.toml'
|
||||
jobs:
|
||||
cargo-deny:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: EmbarkStudios/cargo-deny-action@v2
|
||||
with:
|
||||
command: check licenses
|
||||
arguments: --all-features --locked --exclude-dev
|
||||
rust-version: 1.92 # updatecli.d/rust.yml
|
||||
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,42 +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
|
||||
|
||||
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
|
||||
25
.github/workflows/release.yml
vendored
25
.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; }
|
||||
@@ -172,7 +169,7 @@ jobs:
|
||||
echo "$MACOS_NOTARIZE_JSON" >/tmp/notarize.json
|
||||
./build_tools/make_macos_pkg.sh -s -f /tmp/app.p12 \
|
||||
-i /tmp/installer.p12 -p "$MAC_CODESIGN_PASSWORD" \
|
||||
-n -j /tmp/notarize.json -- -c "-DWITH_DOCS=ON"
|
||||
-n -j /tmp/notarize.json
|
||||
version=$(git describe)
|
||||
[ -f "${FISH_ARTEFACT_PATH}/fish-$version.app.zip" ]
|
||||
[ -f "${FISH_ARTEFACT_PATH}/fish-$version.pkg" ]
|
||||
|
||||
@@ -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"
|
||||
169
CHANGELOG.rst
169
CHANGELOG.rst
@@ -1,164 +1,5 @@
|
||||
fish 4.3.2 (released December 30, 2025)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problems identified in 4.3.0:
|
||||
|
||||
- Pre-built macOS packages failed to start due to a ``Malformed Mach-O file`` error (:issue:`12224`).
|
||||
- ``extra_functionsdir`` (usually ``vendor_functions.d``) and friends were not used (:issue:`12226`).
|
||||
- Sample config file ``~/.config/fish/config.fish/`` and config directories ``~/.config/fish/conf.d/``, ``~/.config/fish/completions/`` and ``~/.config/fish/functions/`` were recreated on every startup instead of only the first time fish runs on a system (:issue:`12230`).
|
||||
- Spurious echo of ``^[[I`` in some scenarios (:issue:`12232`).
|
||||
- Infinite prompt redraw loop on some prompts (:issue:`12233`).
|
||||
- The removal of pre-built HTML docs from tarballs revealed that cross compilation is broken because we use ``${CMAKE_BINARY_DIR}/fish_indent`` for building HTML docs.
|
||||
As a workaround, the new CMake build option ``FISH_INDENT_FOR_BUILDING_DOCS`` can be set to the path of a runnable ``fish_indent`` binary.
|
||||
|
||||
fish 4.3.1 (released December 28, 2025)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problem identified in 4.3.0:
|
||||
|
||||
- Possible crash after expanding an abbreviation (:issue:`12223`).
|
||||
|
||||
fish 4.3.0 (released December 28, 2025)
|
||||
=======================================
|
||||
|
||||
Deprecations and removed features
|
||||
---------------------------------
|
||||
- fish no longer sets user-facing :ref:`universal variables <variables-universal>` by default, making the configuration easier to understand.
|
||||
Specifically, the ``fish_color_*``, ``fish_pager_color_*`` and ``fish_key_bindings`` variables are now set in the global scope by default.
|
||||
After upgrading to 4.3.0, fish will (once and never again) migrate these universals to globals set at startup in the
|
||||
``~/.config/fish/conf.d/fish_frozen_theme.fish`` and
|
||||
``~/.config/fish/conf.d/fish_frozen_key_bindings.fish`` files.
|
||||
We suggest that you delete those files and :ref:`set your theme <syntax-highlighting>` in ``~/.config/fish/config.fish``.
|
||||
|
||||
- You can still configure fish to propagate theme changes instantly; see :ref:`here <syntax-highlighting-instant-update>` for an example.
|
||||
- You can still opt into storing color variables in the universal scope
|
||||
via ``fish_config theme save`` though unlike ``fish_config theme choose``,
|
||||
it does not support dynamic theme switching based on the terminal's color theme (see below).
|
||||
- In addition to setting the variables which are explicitly defined in the given theme,
|
||||
``fish_config theme choose`` now clears only color variables that were set by earlier invocations of a ``fish_config theme choose`` command
|
||||
(which is how fish's default theme is set).
|
||||
|
||||
Scripting improvements
|
||||
----------------------
|
||||
- New :ref:`status language <status-language>` command allows showing and modifying language settings for fish messages without having to modify environment variables.
|
||||
- When using a noninteractive fish instance to compute completions, ``commandline --cursor`` works as expected instead of throwing an error (:issue:`11993`).
|
||||
- :envvar:`fish_trace` can now be set to ``all`` to also trace execution of key bindings, event handlers as well as prompt and title functions.
|
||||
|
||||
Interactive improvements
|
||||
------------------------
|
||||
- When typing immediately after starting fish, the first prompt is now rendered correctly.
|
||||
- Completion accuracy was improved for file paths containing ``=`` or ``:`` (:issue:`5363`).
|
||||
- Prefix-matching completions are now shown even if they don't match the case typed by the user (:issue:`7944`).
|
||||
- On Cygwin/MSYS, command name completion will favor the non-exe name (``foo``) unless the user started typing the extension.
|
||||
- When using the exe name (``foo.exe``), fish will use the description and completions for ``foo`` if there are none for ``foo.exe``.
|
||||
- Autosuggestions now also show soft-wrapped portions (:issue:`12045`).
|
||||
|
||||
New or improved bindings
|
||||
------------------------
|
||||
- :kbd:`ctrl-w` (``backward-kill-path-component``) also deletes escaped spaces (:issue:`2016`).
|
||||
- New special input functions ``backward-path-component``, ``forward-path-component`` and ``kill-path-component`` (:issue:`12127`).
|
||||
|
||||
Improved terminal support
|
||||
-------------------------
|
||||
- Themes can now be made color-theme-aware by including both ``[light]`` and ``[dark]`` sections in the :ref:`theme file <fish-config-theme-files>`.
|
||||
Some default themes have been made color-theme-aware, meaning they dynamically adjust as your terminal's background color switches between light and dark colors (:issue:`11580`).
|
||||
- The working directory is now reported on every fresh prompt (via OSC 7), fixing scenarios where a child process (like ``ssh``) left behind a stale working directory (:issue:`12191`).
|
||||
- OSC 133 prompt markers now also mark the prompt end, which improves shell integration with terminals like iTerm2 (:issue:`11837`).
|
||||
- Operating-system-specific key bindings are now decided based on the :ref:`terminal's host OS <status-terminal-os>`.
|
||||
- New :ref:`feature flag <featureflags>` ``omit-term-workarounds`` can be turned on to prevent fish from trying to work around some incompatible terminals.
|
||||
|
||||
For distributors and developers
|
||||
-------------------------------
|
||||
- Tarballs no longer contain prebuilt documentation,
|
||||
so building and installing documentation requires Sphinx.
|
||||
To avoid users accidentally losing docs, the ``BUILD_DOCS`` and ``INSTALL_DOCS`` configuration options have been replaced with a new ``WITH_DOCS`` option.
|
||||
- ``fish_key_reader`` and ``fish_indent`` are now installed as hardlinks to ``fish``, to save some space.
|
||||
|
||||
Regression fixes:
|
||||
-----------------
|
||||
- (from 4.1.0) Crash on incorrectly-set color variables (:issue:`12078`).
|
||||
- (from 4.1.0) Crash when autosuggesting Unicode characters with nontrivial lowercase mapping.
|
||||
- (from 4.2.0) Incorrect emoji width computation on macOS.
|
||||
- (from 4.2.0) Mouse clicks and :kbd:`ctrl-l` edge cases in multiline command lines (:issue:`12121`).
|
||||
- (from 4.2.0) Completions for Git remote names on some non-glibc systems.
|
||||
- (from 4.2.0) Expansion of ``~$USER``.
|
||||
|
||||
fish 4.2.1 (released November 13, 2025)
|
||||
=======================================
|
||||
|
||||
This release fixes the following problems identified in 4.2.0:
|
||||
|
||||
- When building from a tarball without Sphinx (that is, with ``-DBUILD_DOCS=OFF`` or when ``sphinx-build`` is not found),
|
||||
builtin man pages and help files were missing, which has been fixed (:issue:`12052`).
|
||||
- ``fish_config``'s theme selector (the "colors" tab) was broken, which has been fixed (:issue:`12053`).
|
||||
|
||||
fish 4.2.0 (released November 10, 2025)
|
||||
=======================================
|
||||
|
||||
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:
|
||||
|
||||
@@ -187,7 +28,7 @@ This release fixes the following regressions identified in 4.1.0:
|
||||
This will not affect fish's child processes unless ``LC_MESSAGES`` was already exported.
|
||||
|
||||
- Some :doc:`fish_config <cmds/fish_config>` subcommands for showing prompts and themes had been broken in standalone Linux builds (those using the ``embed-data`` cargo feature), which has been fixed (:issue:`11832`).
|
||||
- On Windows Terminal, we observed an issue where fish would fail to read the terminal's response to our new startup queries, causing noticeable lags and a misleading error message. A workaround has been added (:issue:`11841`).
|
||||
- On Windows Terminal, we observed an issue where fish would fail to read the terminal's response to our new startup queries, causing noticeable lags and a misleading error message. A workaround has been added (:issue:`11841`).
|
||||
- A WezTerm `issue breaking shifted key input <https://github.com/wezterm/wezterm/issues/6087>`__ has resurfaced on some versions of WezTerm; our workaround has been extended to cover all versions for now (:issue:`11204`).
|
||||
- Fixed a crash in :doc:`the web-based configuration tool <cmds/fish_config>` when using the new underline styles (:issue:`11840`).
|
||||
|
||||
@@ -1017,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
|
||||
@@ -1442,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,23 +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}"
|
||||
"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)
|
||||
@@ -56,40 +39,40 @@ if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST build_types)
|
||||
message(WARNING "Unsupported build type ${CMAKE_BUILD_TYPE}. If this doesn't build, try one of Release, RelWithDebInfo or Debug")
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
fish ALL
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E
|
||||
env ${VARS_FOR_CARGO}
|
||||
${Rust_CARGO}
|
||||
build --bin fish
|
||||
$<$<CONFIG:Release>:--release>
|
||||
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
|
||||
--target ${Rust_CARGO_TARGET}
|
||||
--no-default-features
|
||||
--features=${FISH_CARGO_FEATURES}
|
||||
${CARGO_FLAGS}
|
||||
&&
|
||||
"${CMAKE_COMMAND}" -E
|
||||
copy "${rust_target_dir}/${rust_profile}/fish" "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
function(CREATE_LINK target)
|
||||
# Define a function to build and link dependencies.
|
||||
function(CREATE_TARGET target)
|
||||
add_custom_target(
|
||||
${target} ALL
|
||||
DEPENDS fish
|
||||
COMMAND ln -f fish ${target}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E
|
||||
env ${VARS_FOR_CARGO}
|
||||
${Rust_CARGO}
|
||||
build --bin ${target}
|
||||
$<$<CONFIG:Release>:--release>
|
||||
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
|
||||
--target ${Rust_CARGO_TARGET}
|
||||
--no-default-features
|
||||
--features=${FISH_CARGO_FEATURES}
|
||||
${CARGO_FLAGS}
|
||||
&&
|
||||
"${CMAKE_COMMAND}" -E
|
||||
copy "${rust_target_dir}/${rust_profile}/${target}" "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
USES_TERMINAL
|
||||
)
|
||||
endfunction(CREATE_LINK)
|
||||
endfunction(CREATE_TARGET)
|
||||
|
||||
# Define fish.
|
||||
create_target(fish)
|
||||
|
||||
# Define fish_indent.
|
||||
create_link(fish_indent)
|
||||
create_target(fish_indent)
|
||||
|
||||
# Define fish_key_reader.
|
||||
create_link(fish_key_reader)
|
||||
create_target(fish_key_reader)
|
||||
|
||||
# Set up the docs.
|
||||
include(cmake/Docs.cmake)
|
||||
|
||||
# Set up tests.
|
||||
include(cmake/Tests.cmake)
|
||||
|
||||
177
CONTRIBUTING.rst
177
CONTRIBUTING.rst
@@ -21,10 +21,10 @@ Archives are available at https://lists.sr.ht/~krobelus/fish-shell/.
|
||||
GitHub
|
||||
======
|
||||
|
||||
Fish is available on GitHub, at https://github.com/fish-shell/fish-shell.
|
||||
Fish is available on Github, at https://github.com/fish-shell/fish-shell.
|
||||
|
||||
First, you'll need an account there, and you'll need a git clone of fish.
|
||||
Fork it on GitHub and then run::
|
||||
Fork it on Github and then run::
|
||||
|
||||
git clone https://github.com/<USERNAME>/fish-shell.git
|
||||
|
||||
@@ -52,23 +52,6 @@ In short:
|
||||
- Be conservative in what you need (keep to the agreed minimum supported Rust version, limit new dependencies)
|
||||
- Use automated tools to help you (``build_tools/check.sh``)
|
||||
|
||||
Commit History
|
||||
==============
|
||||
|
||||
We use a linear, `recipe-style <https://www.bitsnbites.eu/git-history-work-log-vs-recipe/>`__ history.
|
||||
Every commit should pass our checks.
|
||||
We do not want "fixup" commits in our history.
|
||||
If you notice an issue with a commit in a pull request, or get feedback suggesting changes,
|
||||
you should rewrite the commit history and fix the relevant commits directly,
|
||||
instead of adding new "fixup" commits.
|
||||
When a pull request is ready, we rebase it on top of the current master branch,
|
||||
so don't be shy about rewriting the history of commits which are not on master yet.
|
||||
Rebasing (not merging) your pull request on the latest version of master is also welcome, especially if it resolves conflicts.
|
||||
|
||||
If you're using Git, consider using `jj <https://www.jj-vcs.dev/>`__ to make this easier.
|
||||
|
||||
If a commit should close an issue, add a ``Fixes #<issue-number>`` line at the end of the commit description.
|
||||
|
||||
Contributing completions
|
||||
========================
|
||||
|
||||
@@ -88,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.
|
||||
@@ -106,36 +89,44 @@ Contributing documentation
|
||||
|
||||
The documentation is stored in ``doc_src/``, and written in ReStructured Text and built with Sphinx.
|
||||
|
||||
To build it locally, run either::
|
||||
To build it locally, run from the main fish-shell directory::
|
||||
|
||||
sphinx-build -j auto -b html doc_src/ /tmp/fish-doc/
|
||||
sphinx-build -j 8 -b html -n doc_src/ /tmp/fish-doc/
|
||||
|
||||
which will output HTML docs to /tmp/fish-doc.
|
||||
You can open it in a browser and see that it looks okay.
|
||||
|
||||
Alternatively, you can use::
|
||||
|
||||
cmake --build build -t sphinx-docs
|
||||
|
||||
which outputs to build/user_doc/html/.
|
||||
which will build the docs as html in /tmp/fish-doc. You can open it in a browser and see that it looks okay.
|
||||
|
||||
The builtins and various functions shipped with fish are documented in doc_src/cmds/.
|
||||
|
||||
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
|
||||
-----------------------
|
||||
@@ -187,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
|
||||
=======
|
||||
@@ -199,53 +190,84 @@ The source code for fish includes a large collection of tests. If you
|
||||
are making any changes to fish, running these tests is a good way to make
|
||||
sure the behaviour remains consistent and regressions are not
|
||||
introduced. Even if you don’t run the tests on your machine, they will
|
||||
still be run via GitHub Actions.
|
||||
still be run via Github Actions.
|
||||
|
||||
You are strongly encouraged to add tests when changing the functionality
|
||||
of fish, especially if you are fixing a bug to help ensure there are no
|
||||
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
|
||||
=========================
|
||||
@@ -257,8 +279,9 @@ It also means that some features are not supported, such as message context and
|
||||
We also expect all files to be UTF-8-encoded.
|
||||
In practice, this should not matter much for contributing translations.
|
||||
|
||||
Translation sources are stored in the ``localization/po`` directory and named ``ll_CC.po``,
|
||||
where ``ll`` is the two (or possibly three) letter ISO 639-1 language code of the target language
|
||||
Translation sources are
|
||||
stored in the ``po`` directory, named ``ll_CC.po``, where ``ll`` is the
|
||||
two (or possibly three) letter ISO 639-1 language code of the target language
|
||||
(e.g. ``pt`` for Portuguese). ``CC`` is an ISO 3166 country/territory code,
|
||||
(e.g. ``BR`` for Brazil).
|
||||
An example for a valid name is ``pt_BR.po``, indicating Brazilian Portuguese.
|
||||
@@ -272,7 +295,7 @@ More specifically, you will need ``msguniq`` and ``msgmerge`` for creating trans
|
||||
language.
|
||||
To create a new translation, run::
|
||||
|
||||
build_tools/update_translations.fish localization/po/ll_CC.po
|
||||
build_tools/update_translations.fish po/ll_CC.po
|
||||
|
||||
This will create a new PO file containing all messages available for translation.
|
||||
If the file already exists, it will be updated.
|
||||
@@ -318,9 +341,9 @@ Editing PO files
|
||||
Many tools are available for editing translation files, including
|
||||
command-line and graphical user interface programs. For simple use, you can use your text editor.
|
||||
|
||||
Open up the PO file, for example ``localization/po/sv.po``, and you'll see something like::
|
||||
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.
|
||||
@@ -328,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.
|
||||
|
||||
@@ -346,7 +369,7 @@ Modifications to strings in source files
|
||||
If a string changes in the sources, the old translations will no longer work.
|
||||
They will be preserved in the PO files, but commented-out (starting with ``#~``).
|
||||
If you add/remove/change a translatable strings in a source file,
|
||||
run ``build_tools/update_translations.fish`` to propagate this to all translation files (``localization/po/*.po``).
|
||||
run ``build_tools/update_translations.fish`` to propagate this to all translation files (``po/*.po``).
|
||||
This is only relevant for developers modifying the source files of fish or fish scripts.
|
||||
|
||||
Setting Code Up For Translations
|
||||
@@ -358,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.
|
||||
@@ -381,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
|
||||
==========
|
||||
|
||||
|
||||
583
Cargo.lock
generated
583
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,48 +103,35 @@ 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.3.2"
|
||||
version = "4.1.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"errno",
|
||||
"fish-build-helper",
|
||||
"fish-build-man-pages",
|
||||
"fish-common",
|
||||
"fish-fallback",
|
||||
"fish-gettext",
|
||||
"fish-gettext-extraction",
|
||||
"fish-gettext-maps",
|
||||
"fish-gettext-mo-file-parser",
|
||||
"fish-printf",
|
||||
"fish-tempfile",
|
||||
"fish-wchar",
|
||||
"fish-widecharwidth",
|
||||
"libc",
|
||||
"lru",
|
||||
"macro_rules_attribute",
|
||||
"nix",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"pcre2",
|
||||
"phf 0.12.1",
|
||||
"phf_codegen 0.12.1",
|
||||
"portable-atomic",
|
||||
"rand 0.9.2",
|
||||
"rand",
|
||||
"rsconf",
|
||||
"rust-embed",
|
||||
"serial_test",
|
||||
"terminfo",
|
||||
"unix_path",
|
||||
"widestring",
|
||||
"xterm-color",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -203,45 +149,11 @@ dependencies = [
|
||||
"rsconf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-common"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"nix",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-fallback"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fish-build-helper",
|
||||
"fish-common",
|
||||
"fish-wchar",
|
||||
"fish-widecharwidth",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"rsconf",
|
||||
"widestring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-gettext"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fish-gettext-maps",
|
||||
"once_cell",
|
||||
"phf 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-gettext-extraction"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fish-tempfile",
|
||||
"proc-macro2",
|
||||
"rsconf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -269,26 +181,6 @@ dependencies = [
|
||||
"widestring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-tempfile"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"rand 0.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-wchar"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fish-common",
|
||||
"widestring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fish-widecharwidth"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@@ -297,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",
|
||||
@@ -360,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"
|
||||
@@ -408,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"
|
||||
@@ -469,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",
|
||||
@@ -491,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"
|
||||
@@ -573,7 +391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared 0.11.3",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -606,76 +424,41 @@ 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"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
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"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.9.3",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -684,52 +467,15 @@ version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.18"
|
||||
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"
|
||||
@@ -741,9 +487,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.9.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca"
|
||||
checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
@@ -752,25 +498,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.9.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2"
|
||||
checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"shellexpand",
|
||||
"syn",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.9.0"
|
||||
version = "8.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475"
|
||||
checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594"
|
||||
dependencies = [
|
||||
"globset",
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
@@ -786,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",
|
||||
]
|
||||
@@ -801,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"
|
||||
@@ -859,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"
|
||||
@@ -891,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",
|
||||
@@ -918,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"
|
||||
@@ -958,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"
|
||||
@@ -993,79 +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"
|
||||
|
||||
[[package]]
|
||||
name = "xterm-color"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4de5f056fb9dc8b7908754867544e26145767187aaac5a98495e88ad7cb8a80f"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
"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 = "zerocopy-derive"
|
||||
version = "0.8.27"
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
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"
|
||||
|
||||
76
Cargo.toml
76
Cargo.toml
@@ -1,33 +1,24 @@
|
||||
[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"
|
||||
# see doc_src/license.rst for details
|
||||
# don't forget to update COPYING and debian/copyright too
|
||||
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
bitflags = "2.5.0"
|
||||
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" }
|
||||
fish-common = { path = "crates/common" }
|
||||
fish-fallback = { path = "crates/fallback" }
|
||||
fish-gettext = { path = "crates/gettext" }
|
||||
fish-gettext-extraction = { path = "crates/gettext-extraction" }
|
||||
fish-gettext-maps = { path = "crates/gettext-maps" }
|
||||
fish-gettext-mo-file-parser = { path = "crates/gettext-mo-file-parser" }
|
||||
fish-printf = { path = "crates/printf", features = ["widestring"] }
|
||||
fish-tempfile = { path = "crates/tempfile" }
|
||||
fish-wchar = { path = "crates/wchar" }
|
||||
fish-widecharwidth = { path = "crates/widecharwidth" }
|
||||
libc = "0.2.177"
|
||||
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.
|
||||
@@ -37,7 +28,6 @@ nix = { version = "0.30.1", default-features = false, features = [
|
||||
"inotify",
|
||||
"resource",
|
||||
"fs",
|
||||
"term",
|
||||
] }
|
||||
num-traits = "0.2.19"
|
||||
once_cell = "1.19.0"
|
||||
@@ -50,16 +40,12 @@ portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
] }
|
||||
proc-macro2 = "1.0"
|
||||
rand = { version = "0.9.2", default-features = false, features = [
|
||||
"small_rng",
|
||||
"thread_rng",
|
||||
] }
|
||||
# Don't use the "getrandom" feature as it requires "getentropy" which was not
|
||||
# available on macOS < 10.12. We can enable "getrandom" when we raise the
|
||||
# minimum supported version to 10.12.
|
||||
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
|
||||
rsconf = "0.2.2"
|
||||
rust-embed = { version = "8.9.0", 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"
|
||||
@@ -67,7 +53,6 @@ widestring = "1.2.0"
|
||||
unicode-segmentation = "1.12.0"
|
||||
unicode-width = "0.2.0"
|
||||
unix_path = "1.0.1"
|
||||
xterm-color = "1.0.1"
|
||||
|
||||
[profile.release]
|
||||
overflow-checks = true
|
||||
@@ -79,56 +64,42 @@ debug = true
|
||||
|
||||
[package]
|
||||
name = "fish"
|
||||
version = "4.3.2"
|
||||
version = "4.1.2"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
default-run = "fish"
|
||||
license.workspace = true
|
||||
# see doc_src/license.rst for details
|
||||
# don't forget to update COPYING and debian/copyright too
|
||||
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
|
||||
homepage = "https://fishshell.com"
|
||||
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-common.workspace = true
|
||||
fish-fallback.workspace = true
|
||||
fish-gettext = { workspace = true, optional = true }
|
||||
fish-gettext-extraction = { workspace = true, optional = true }
|
||||
fish-gettext-maps = { workspace = true, optional = true }
|
||||
fish-printf.workspace = true
|
||||
fish-tempfile.workspace = true
|
||||
fish-wchar.workspace = true
|
||||
fish-widecharwidth.workspace = true
|
||||
libc.workspace = true
|
||||
lru.workspace = true
|
||||
macro_rules_attribute = "0.2.2"
|
||||
nix.workspace = true
|
||||
num-traits.workspace = true
|
||||
once_cell.workspace = true
|
||||
pcre2.workspace = true
|
||||
phf = { workspace = true, optional = true }
|
||||
rand.workspace = true
|
||||
terminfo.workspace = true
|
||||
xterm-color.workspace = true
|
||||
widestring.workspace = true
|
||||
|
||||
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
|
||||
portable-atomic.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rust-embed = { workspace = true, 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, features = [
|
||||
"deterministic-timestamps",
|
||||
"include-exclude",
|
||||
"interpolate-folder-path",
|
||||
] }
|
||||
rust-embed = { workspace = true, optional = true, features = ["deterministic-timestamps"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test.workspace = true
|
||||
@@ -160,12 +131,12 @@ name = "fish_key_reader"
|
||||
path = "src/bin/fish_key_reader.rs"
|
||||
|
||||
[features]
|
||||
default = ["embed-manpages", "localize-messages"]
|
||||
default = ["embed-data", "localize-messages"]
|
||||
benchmark = []
|
||||
embed-manpages = ["dep:fish-build-man-pages"]
|
||||
embed-data = ["dep:rust-embed", "dep:fish-build-man-pages"]
|
||||
# Enable gettext localization at runtime. Requires the `msgfmt` tool to generate catalog data at
|
||||
# build time.
|
||||
localize-messages = ["dep:fish-gettext"]
|
||||
localize-messages = ["dep:phf", "dep:fish-gettext-maps"]
|
||||
# This feature is used to enable extracting messages from the source code for localization.
|
||||
# It only needs to be enabled if updating these messages (and the corresponding PO files) is
|
||||
# desired. This happens when running tests via `build_tools/check.sh` and when calling
|
||||
@@ -181,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.map_unwrap_or = "warn"
|
||||
clippy.needless_return = "allow"
|
||||
clippy.needless_lifetimes = "allow"
|
||||
clippy.new_without_default = "allow"
|
||||
clippy.option_map_unit_fn = "allow"
|
||||
|
||||
# We do not want to use the e?print(ln)?! macros.
|
||||
# These lints flag their use.
|
||||
|
||||
66
README.rst
66
README.rst
@@ -37,7 +37,7 @@ fish can be installed:
|
||||
- using the `installer from fishshell.com <https://fishshell.com/>`__
|
||||
- as a `standalone app from fishshell.com <https://fishshell.com/>`__
|
||||
|
||||
Note: The minimum supported macOS version is 10.12.
|
||||
Note: The minimum supported macOS version is 10.10 "Yosemite".
|
||||
|
||||
Packages for Linux
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
@@ -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 ..
|
||||
@@ -157,52 +158,41 @@ In addition to the normal CMake build options (like ``CMAKE_INSTALL_PREFIX``), f
|
||||
- Rust_COMPILER=path - the path to rustc. If not set, cmake will check $PATH and ~/.cargo/bin
|
||||
- Rust_CARGO=path - the path to cargo. If not set, cmake will check $PATH and ~/.cargo/bin
|
||||
- Rust_CARGO_TARGET=target - the target to pass to cargo. Set this for cross-compilation.
|
||||
- WITH_DOCS=ON|OFF - whether to build the documentation. By default, this is ON when Sphinx is installed.
|
||||
- FISH_INDENT_FOR_BUILDING_DOCS - useful for cross-compilation.
|
||||
Set this to the path to the ``fish_indent`` executable to use for building HTML docs.
|
||||
By default, ``${CMAKE_BINARY_DIR}/fish_indent`` will be used.
|
||||
If that's not runnable on the compile host,
|
||||
you can build a native one with ``cargo build --bin fish_indent`` and set this to ``$PWD/target/debug/fish_indent``.
|
||||
- BUILD_DOCS=ON|OFF - whether to build the documentation. This is automatically set to OFF when Sphinx isn't installed.
|
||||
- INSTALL_DOCS=ON|OFF - whether to install the docs. This is automatically set to on when BUILD_DOCS is or prebuilt documentation is available (like when building in-tree from a tarball).
|
||||
- FISH_USE_SYSTEM_PCRE2=ON|OFF - whether to use an installed pcre2. This is normally autodetected.
|
||||
- MAC_CODESIGN_ID=String|OFF - the codesign ID to use on Mac, or "OFF" to disable codesigning.
|
||||
- WITH_GETTEXT=ON|OFF - whether to include translations.
|
||||
- extra_functionsdir, extra_completionsdir and extra_confdir - to compile in an additional directory to be searched for functions, completions and configuration snippets
|
||||
|
||||
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.
|
||||
|
||||
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features --features=embed-manpages`` to cargo.
|
||||
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.
|
||||
- Separate files for builtins (e.g. ``$PREFIX/share/fish/man/man1/abbr.1``).
|
||||
- A local copy of the HTML documentation, typically accessed via the ``help`` fish function.
|
||||
In Cargo builds, ``help`` will redirect to `<https://fishshell.com/docs/current/>`__
|
||||
- Ability to use our CMake options extra_functionsdir, extra_completionsdir and extra_confdir,
|
||||
(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
|
||||
--------------------------------
|
||||
|
||||
|
||||
214
build.rs
214
build.rs
@@ -1,7 +1,6 @@
|
||||
use fish_build_helper::{
|
||||
env_var, fish_build_dir, target_os, target_os_is_apple, target_os_is_bsd, target_os_is_cygwin,
|
||||
workspace_root,
|
||||
};
|
||||
#![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};
|
||||
@@ -31,16 +30,28 @@ 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);
|
||||
|
||||
fish_build_helper::rebuild_if_embedded_path_changed("share");
|
||||
std::env::set_var("FISH_BUILD_VERSION", version);
|
||||
|
||||
// These are necessary if built with embedded functions,
|
||||
// but only in release builds (because rust-embed in debug builds reads from the filesystem).
|
||||
#[cfg(feature = "embed-data")]
|
||||
#[cfg(any(windows, not(debug_assertions)))]
|
||||
rsconf::rebuild_if_path_changed("share");
|
||||
|
||||
#[cfg(feature = "gettext-extract")]
|
||||
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_FILE");
|
||||
|
||||
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();
|
||||
@@ -49,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,
|
||||
@@ -66,41 +75,35 @@ fn main() {
|
||||
/// `Cargo.toml`) behind a feature we just enabled.
|
||||
///
|
||||
/// [0]: https://github.com/rust-lang/cargo/issues/5499
|
||||
#[rustfmt::skip]
|
||||
fn detect_cfgs(target: &mut Target) {
|
||||
for (name, handler) in [
|
||||
// Ignore the first entry, it just sets up the type inference.
|
||||
// Ignore the first entry, it just sets up the type inference. Model new entries after the
|
||||
// second line.
|
||||
("", &(|_: &Target| false) as &dyn Fn(&Target) -> bool),
|
||||
("apple", &(|_| target_os_is_apple())),
|
||||
("bsd", &(|_| target_os_is_bsd())),
|
||||
("cygwin", &(|_| target_os_is_cygwin())),
|
||||
("have_eventfd", &|target| {
|
||||
// FIXME: NetBSD 10 has eventfd, but the libc crate does not expose it.
|
||||
if target_os() == "netbsd" {
|
||||
false
|
||||
} else {
|
||||
target.has_header("sys/eventfd.h")
|
||||
}
|
||||
}),
|
||||
("have_localeconv_l", &|target| {
|
||||
("apple", &detect_apple),
|
||||
("bsd", &detect_bsd),
|
||||
("cygwin", &detect_cygwin),
|
||||
("small_main_stack", &has_small_stack),
|
||||
// See if libc supports the thread-safe localeconv_l(3) alternative to localeconv(3).
|
||||
("localeconv_l", &|target| {
|
||||
target.has_symbol("localeconv_l")
|
||||
}),
|
||||
("have_pipe2", &|target| target.has_symbol("pipe2")),
|
||||
("have_posix_spawn", &|target| {
|
||||
if matches!(target_os().as_str(), "openbsd" | "android") {
|
||||
// OpenBSD's posix_spawn returns status 127 instead of erroring with ENOEXEC when faced with a
|
||||
// shebang-less script. Disable posix_spawn on OpenBSD.
|
||||
//
|
||||
// Android is broken for unclear reasons
|
||||
false
|
||||
} else {
|
||||
target.has_header("spawn.h")
|
||||
("FISH_USE_POSIX_SPAWN", &|target| {
|
||||
target.has_header("spawn.h")
|
||||
}),
|
||||
("HAVE_PIPE2", &|target| {
|
||||
target.has_symbol("pipe2")
|
||||
}),
|
||||
("HAVE_EVENTFD", &|target| {
|
||||
// FIXME: NetBSD 10 has eventfd, but the libc crate does not expose it.
|
||||
if cfg!(target_os = "netbsd") {
|
||||
false
|
||||
} else {
|
||||
target.has_header("sys/eventfd.h")
|
||||
}
|
||||
}),
|
||||
("small_main_stack", &has_small_stack),
|
||||
("using_cmake", &|_| {
|
||||
option_env!("FISH_CMAKE_BINARY_DIR").is_some()
|
||||
}),
|
||||
("waitstatus_signal_ret", &|target| {
|
||||
("HAVE_WAITSTATUS_SIGNAL_RET", &|target| {
|
||||
target.r#if("WEXITSTATUS(0x007f) == 0x7f", &["sys/wait.h"])
|
||||
}),
|
||||
] {
|
||||
@@ -108,6 +111,40 @@ fn detect_cfgs(target: &mut Target) {
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_apple(_: &Target) -> bool {
|
||||
cfg!(any(target_os = "ios", target_os = "macos"))
|
||||
}
|
||||
|
||||
fn detect_cygwin(_: &Target) -> bool {
|
||||
// Cygwin target is usually cross-compiled.
|
||||
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
|
||||
/// `#[cfg(bsd)]`.
|
||||
///
|
||||
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
|
||||
/// doesn't necessarily include less-popular forks nor does it group them into families more
|
||||
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
|
||||
fn detect_bsd(_: &Target) -> bool {
|
||||
// Instead of using `uname`, we can inspect the TARGET env variable set by Cargo. This lets us
|
||||
// support cross-compilation scenarios.
|
||||
let mut target = 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",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
assert!(is_bsd, "Target incorrectly detected as not BSD!");
|
||||
is_bsd
|
||||
}
|
||||
|
||||
/// Rust sets the stack size of newly created threads to a sane value, but is at at the mercy of the
|
||||
/// OS when it comes to the size of the main stack. Some platforms we support default to a tiny
|
||||
/// 0.5 MiB main stack, which is insufficient for fish's MAX_EVAL_DEPTH/MAX_STACK_DEPTH values.
|
||||
@@ -126,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,63 +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("/etc/".to_string()),
|
||||
))
|
||||
});
|
||||
|
||||
let datadir = overridable_path("DATADIR", |env_datadir| {
|
||||
env_datadir.map(|p| join_if_relative(&prefix, p))
|
||||
});
|
||||
overridable_path("BINDIR", |env_bindir| {
|
||||
env_bindir.map(|p| join_if_relative(&prefix, p))
|
||||
});
|
||||
overridable_path("DOCDIR", |env_docdir| {
|
||||
env_docdir.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
|
||||
@@ -38,8 +22,8 @@ cargo() {
|
||||
}
|
||||
|
||||
cleanup () {
|
||||
if [ -n "$gettext_template_dir" ] && [ -e "$gettext_template_dir" ]; then
|
||||
rm -r "$gettext_template_dir"
|
||||
if [ -n "$template_file" ] && [ -e "$template_file" ]; then
|
||||
rm "$template_file"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -59,20 +43,9 @@ 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
|
||||
|
||||
gettext_template_dir=$(mktemp -d)
|
||||
(
|
||||
export FISH_GETTEXT_EXTRACTION_DIR="$gettext_template_dir"
|
||||
cargo build --workspace --all-targets --features=gettext-extract
|
||||
)
|
||||
template_file=$(mktemp)
|
||||
FISH_GETTEXT_EXTRACTION_FILE=$template_file cargo build --workspace --all-targets --features=gettext-extract
|
||||
if $lint; then
|
||||
if command -v cargo-deny >/dev/null; then
|
||||
cargo deny --all-features --locked --exclude-dev check licenses
|
||||
fi
|
||||
PATH="$build_dir:$PATH" "$workspace_root/build_tools/style.fish" --all --check
|
||||
for features in "" --no-default-features; do
|
||||
cargo clippy --workspace --all-targets $features
|
||||
@@ -81,9 +54,9 @@ fi
|
||||
cargo test --no-default-features --workspace --all-targets
|
||||
cargo test --doc --workspace
|
||||
if $lint; then
|
||||
cargo doc --workspace --no-deps
|
||||
cargo doc --workspace
|
||||
fi
|
||||
FISH_GETTEXT_EXTRACTION_DIR=$gettext_template_dir "$workspace_root/tests/test_driver.py" "$build_dir"
|
||||
FISH_GETTEXT_EXTRACTION_FILE=$template_file "$workspace_root/tests/test_driver.py" "$build_dir"
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
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
|
||||
@@ -21,31 +21,23 @@ begin
|
||||
|
||||
set -g workspace_root (path resolve (status dirname)/..)
|
||||
|
||||
set -l rust_extraction_dir
|
||||
set -l rust_extraction_file
|
||||
if set -l --query _flag_use_existing_template
|
||||
set rust_extraction_dir $_flag_use_existing_template
|
||||
set rust_extraction_file $_flag_use_existing_template
|
||||
else
|
||||
set rust_extraction_dir (mktemp -d)
|
||||
set rust_extraction_file (mktemp)
|
||||
# We need to build to ensure that the proc macro for extracting strings runs.
|
||||
FISH_GETTEXT_EXTRACTION_DIR=$rust_extraction_dir cargo check --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.
|
||||
find $rust_extraction_dir -type f -exec cat {} + | msguniq --no-wrap --sort-output
|
||||
msguniq --no-wrap --strict --sort-output $rust_extraction_file
|
||||
or exit 1
|
||||
|
||||
if not set -l --query _flag_use_existing_template
|
||||
rm -r $rust_extraction_dir
|
||||
rm $rust_extraction_file
|
||||
end
|
||||
|
||||
function extract_fish_script_messages_impl
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ git_permission_failed=0
|
||||
|
||||
# First see if there is a version file (included in release tarballs),
|
||||
# then try git-describe, then default.
|
||||
if test -f "$FISH_BASE_DIR"/version
|
||||
if test -f version
|
||||
then
|
||||
VN=$(cat "$FISH_BASE_DIR"/version) || VN="$DEF_VER"
|
||||
VN=$(cat version) || VN="$DEF_VER"
|
||||
else
|
||||
if VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
||||
:
|
||||
|
||||
@@ -24,12 +24,16 @@ SIGN=
|
||||
NOTARIZE=
|
||||
|
||||
ARM64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=11.0'
|
||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.12'
|
||||
cmake_args=()
|
||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.9'
|
||||
|
||||
while getopts "c:sf:i:p:e:nj:" opt; do
|
||||
# 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
|
||||
c) cmake_args+=("$OPTARG");;
|
||||
s) SIGN=1;;
|
||||
f) P12_APP_FILE=$(realpath "$OPTARG");;
|
||||
i) P12_INSTALL_FILE=$(realpath "$OPTARG");;
|
||||
@@ -61,37 +65,42 @@ 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 \
|
||||
"${cmake_args[@]}" \
|
||||
"$@" \
|
||||
"$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 a fat binary inside the root.
|
||||
# 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 it up.
|
||||
FILE=$PKGDIR/root/usr/local/bin/fish
|
||||
X86_FILE=$PKGDIR/build_x86_64/$(basename "$FILE")
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
chmod 755 "$FILE"
|
||||
# Fatten them up.
|
||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
||||
X86_FILE="$PKGDIR/build_x86_64/$(basename "$FILE")"
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
chmod 755 "$FILE"
|
||||
done
|
||||
|
||||
if test -n "$SIGN"; then
|
||||
echo "Signing executables"
|
||||
@@ -104,7 +113,9 @@ if test -n "$SIGN"; then
|
||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
||||
fi
|
||||
(set +x; rcodesign sign "${ARGS[@]}" "$PKGDIR"/root/usr/local/bin/fish)
|
||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
||||
(set +x; rcodesign sign "${ARGS[@]}" "$FILE")
|
||||
done
|
||||
fi
|
||||
|
||||
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
|
||||
@@ -125,13 +136,15 @@ fi
|
||||
(cd "$PKGDIR/build_arm64" && env $ARM64_DEPLOY_TARGET make -j 12 fish_macapp)
|
||||
(cd "$PKGDIR/build_x86_64" && env $X86_64_DEPLOY_TARGET make -j 12 fish_macapp)
|
||||
|
||||
# Make the app's /usr/local/bin/fish binary universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
||||
# Make the app's /usr/local/bin binaries universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
||||
cd "$PKGDIR/build_arm64"
|
||||
FILE=fish.app/Contents/Resources/base/usr/local/bin/fish
|
||||
X86_FILE=$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
# macho-universal-create screws up the permissions.
|
||||
chmod 755 "$FILE"
|
||||
for FILE in fish.app/Contents/Resources/base/usr/local/bin/*; do
|
||||
X86_FILE="$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")"
|
||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
||||
|
||||
# macho-universal-create screws up the permissions.
|
||||
chmod 755 "$FILE"
|
||||
done
|
||||
|
||||
if test -n "$SIGN"; then
|
||||
echo "Signing app"
|
||||
|
||||
@@ -1,23 +1,79 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Script to generate a tarball
|
||||
# We use git to output a tree. But we also want to build the user documentation
|
||||
# and put that in the tarball, so that nobody needs to have sphinx installed
|
||||
# to build it.
|
||||
# Outputs to $FISH_ARTEFACT_PATH or ~/fish_built by default
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
# We will generate a tarball with a prefix "fish-VERSION"
|
||||
# git can do that automatically for us via git-archive
|
||||
# but to get the documentation in, we need to make a symlink called "fish-VERSION"
|
||||
# and tar from that, so that the documentation gets the right prefix
|
||||
|
||||
# Use Ninja if available, as it automatically parallelises
|
||||
BUILD_TOOL="make"
|
||||
BUILD_GENERATOR="Unix Makefiles"
|
||||
if command -v ninja >/dev/null; then
|
||||
BUILD_TOOL="ninja"
|
||||
BUILD_GENERATOR="Ninja"
|
||||
fi
|
||||
|
||||
# We need GNU tar as that supports the --mtime and --transform options
|
||||
TAR=notfound
|
||||
for try in tar gtar gnutar; do
|
||||
if $try -Pcf /dev/null --mtime now /dev/null >/dev/null 2>&1; then
|
||||
TAR=$try
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$TAR" = "notfound" ]; then
|
||||
echo 'No suitable tar (supporting --mtime) found as tar/gtar/gnutar in PATH'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current directory, which we'll use for symlinks
|
||||
wd="$PWD"
|
||||
|
||||
# Get the version
|
||||
VERSION=$(build_tools/git_version_gen.sh --stdout 2>/dev/null)
|
||||
|
||||
prefix=fish-$VERSION
|
||||
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix.tar.xz
|
||||
# The name of the prefix, which is the directory that you get when you untar
|
||||
prefix="fish-$VERSION"
|
||||
|
||||
git archive \
|
||||
--prefix="$prefix/" \
|
||||
--add-virtual-file="$prefix/version:$VERSION" \
|
||||
HEAD |
|
||||
xz >"$path"
|
||||
# The path where we will output the tar file
|
||||
# Defaults to ~/fish_built
|
||||
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix.tar
|
||||
|
||||
# Clean up stuff we've written before
|
||||
rm -f "$path" "$path".xz
|
||||
|
||||
# git starts the archive
|
||||
git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
|
||||
|
||||
# tarball out the documentation, generate a version file
|
||||
PREFIX_TMPDIR=$(mktemp -d)
|
||||
cd "$PREFIX_TMPDIR"
|
||||
echo "$VERSION" > version
|
||||
cmake -G "$BUILD_GENERATOR" -DCMAKE_BUILD_TYPE=Debug "$wd"
|
||||
$BUILD_TOOL doc
|
||||
|
||||
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
|
||||
--mode=g+w,a+rX --transform s/^/$prefix\//"
|
||||
$TAR_APPEND --no-recursion user_doc
|
||||
$TAR_APPEND user_doc/html user_doc/man
|
||||
$TAR_APPEND version
|
||||
|
||||
cd -
|
||||
rm -r "$PREFIX_TMPDIR"
|
||||
|
||||
# xz it
|
||||
xz "$path"
|
||||
|
||||
# Output what we did, and the sha256 hash
|
||||
echo "Tarball written to $path"
|
||||
openssl dgst -sha256 "$path"
|
||||
echo "Tarball written to $path".xz
|
||||
openssl dgst -sha256 "$path".xz
|
||||
|
||||
@@ -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 `this key <'"${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
|
||||
|
||||
@@ -18,18 +18,11 @@ fi
|
||||
[ -n "$version" ]
|
||||
|
||||
for tool in \
|
||||
cmake \
|
||||
bundle \
|
||||
diff \
|
||||
gh \
|
||||
gpg \
|
||||
jq \
|
||||
ninja \
|
||||
ruby \
|
||||
tar \
|
||||
timeout \
|
||||
uv \
|
||||
xz \
|
||||
; do
|
||||
if ! command -v "$tool" >/dev/null; then
|
||||
echo >&2 "$0: missing command: $1"
|
||||
@@ -37,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
|
||||
@@ -86,22 +74,6 @@ sed -i \
|
||||
CommitVersion() {
|
||||
sed -i "s/^version = \".*\"/version = \"$1\"/g" Cargo.toml
|
||||
cargo fetch --offline
|
||||
if [ "$1" = "$version" ]; then
|
||||
# debchange is a Debian script to manage the Debian changelog, but
|
||||
# it's too annoying to install everywhere. Just do it by hand.
|
||||
cat - contrib/debian/changelog > contrib/debian/changelog.new <<EOF
|
||||
fish (${version}-1) stable; urgency=medium
|
||||
|
||||
* Release of new version $version.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/$version for details.
|
||||
|
||||
-- $committer $(date -R)
|
||||
|
||||
EOF
|
||||
mv contrib/debian/changelog.new contrib/debian/changelog
|
||||
git add contrib/debian/changelog
|
||||
fi
|
||||
git add CHANGELOG.rst Cargo.toml Cargo.lock
|
||||
git commit -m "$2
|
||||
|
||||
@@ -110,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
|
||||
|
||||
@@ -136,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 ./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
|
||||
@@ -158,26 +122,10 @@ 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/local-tarball/fish-$version"
|
||||
uv --no-managed-python venv
|
||||
. .venv/bin/activate
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug .
|
||||
ninja doc
|
||||
)
|
||||
( cd "$tmpdir" && tar xf fish-$version.tar.xz )
|
||||
CopyDocs() {
|
||||
rm -rf "$fish_site/site/docs/$1"
|
||||
cp -r "$tmpdir/local-tarball/fish-$version/user_doc/html" "$fish_site/site/docs/$1"
|
||||
cp -r "$tmpdir/fish-$version/user_doc/html" "$fish_site/site/docs/$1"
|
||||
git -C $fish_site add "site/docs/$1"
|
||||
}
|
||||
minor_version=${version%.*}
|
||||
@@ -265,8 +213,6 @@ done
|
||||
# This takes care to support remote names that are different from
|
||||
# fish-shell remote name. Also, support detached HEAD state.
|
||||
git push "$fish_site_repo" HEAD:master
|
||||
git fetch "$fish_site_repo" \
|
||||
"$(git rev-parse HEAD):refs/remotes/origin/master"
|
||||
)
|
||||
|
||||
if [ -n "$integration_branch" ]; then {
|
||||
@@ -283,27 +229,23 @@ EOF
|
||||
git push $remote HEAD:master
|
||||
} fi
|
||||
|
||||
milestone_version="$(
|
||||
if echo "$version" | grep -q '\.0$'; then
|
||||
echo "$minor_version"
|
||||
else
|
||||
echo "$version"
|
||||
fi
|
||||
)"
|
||||
milestone_number() {
|
||||
milestone_number=$(
|
||||
gh_api_repo milestones?state=open |
|
||||
jq --arg name "fish $1" '
|
||||
.[] | select(.title == $name) | .number
|
||||
'
|
||||
}
|
||||
gh_api_repo milestones/"$(milestone_number "$milestone_version")" \
|
||||
--method PATCH --raw-field state=closed
|
||||
jq '.[] | select(.title == "fish '"$version"'") | .number'
|
||||
)
|
||||
gh_api_repo --method PATCH milestones/$milestone_number \
|
||||
--raw-field state=closed
|
||||
|
||||
next_minor_version=$(echo "$minor_version" |
|
||||
awk -F. '{ printf "%s.%s", $1, $2+1 }')
|
||||
if [ -z "$(milestone_number "$next_minor_version")" ]; then
|
||||
gh_api_repo milestones --method POST \
|
||||
--raw-field title="fish $next_minor_version"
|
||||
next_patch_version=$(
|
||||
echo "$version" | awk -F. '
|
||||
NF == 3 && $3 ~ /[0-9]+/ {
|
||||
printf "%s.%s.%s", $1, $2, $3+1
|
||||
}
|
||||
'
|
||||
)
|
||||
if [ -n "$next_patch_version" ]; then
|
||||
gh_api_repo --method POST milestones \
|
||||
--raw-field title="fish $next_patch_version"
|
||||
fi
|
||||
|
||||
exit
|
||||
|
||||
@@ -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,22 +0,0 @@
|
||||
# /// script
|
||||
# requires-python = ">=3.5"
|
||||
# dependencies = [
|
||||
# "launchpadlib",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
from launchpadlib.launchpad import Launchpad
|
||||
|
||||
if __name__ == "__main__":
|
||||
launchpad = Launchpad.login_anonymously(
|
||||
"fish shell build script", "production", "~/.cache", version="devel"
|
||||
)
|
||||
ubu = launchpad.projects("ubuntu")
|
||||
print(
|
||||
"\n".join(
|
||||
x["name"]
|
||||
for x in ubu.series.entries
|
||||
if x["supported"] == True
|
||||
and x["name"] not in ("trusty", "xenial", "bionic", "focal")
|
||||
)
|
||||
)
|
||||
@@ -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 --exclude-newer="$(date --date='7 days ago' --iso-8601)"
|
||||
|
||||
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 crates/widecharwidth/src/
|
||||
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
|
||||
@@ -9,32 +9,33 @@
|
||||
# For developers:
|
||||
# - Run with no args to update all PO files after making changes to Rust/fish sources.
|
||||
# For translators:
|
||||
# - Specify the language you want to work on as an argument, which must be a file in the
|
||||
# localization/po/ directory. You can specify a language which does not have translations
|
||||
# yet by specifying the name of a file which does not yet exist.
|
||||
# Make sure to follow the naming convention.
|
||||
# - Specify the language you want to work on as an argument, which must be a file in the po/
|
||||
# directory. You can specify a language which does not have translations yet by specifying the
|
||||
# name of a file which does not yet exist. Make sure to follow the naming convention.
|
||||
# For testing:
|
||||
# - Specify `--dry-run` to see if any updates to the PO files would by applied by this script.
|
||||
# If this flag is specified, the script will exit with an error if there are outstanding
|
||||
# changes, and will display the diff. Do not specify other flags if `--dry-run` is specified.
|
||||
#
|
||||
# Specify `--use-existing-template=DIR` to prevent running cargo for extracting an up-to-date
|
||||
# Specify `--use-existing-template=FILE` to prevent running cargo for extracting an up-to-date
|
||||
# version of the localized strings. This flag is intended for testing setups which make it
|
||||
# inconvenient to run cargo here, but run it in an earlier step to ensure up-to-date values.
|
||||
# This argument is passed on to the `fish_xgettext.fish` script and has no other uses.
|
||||
# `DIR` must be the path to a gettext template file generated from our compilation process.
|
||||
# `FILE` must be the path to a gettext template file generated from our compilation process.
|
||||
# It can be obtained by running:
|
||||
# set -l DIR (mktemp -d)
|
||||
# FISH_GETTEXT_EXTRACTION_DIR=$DIR cargo check --features=gettext-extract
|
||||
# set -l FILE (mktemp)
|
||||
# FISH_GETTEXT_EXTRACTION_FILE=$FILE cargo check --features=gettext-extract
|
||||
|
||||
# The sort utility is locale-sensitive.
|
||||
# Ensure that sorting output is consistent by setting LC_ALL here.
|
||||
set -gx LC_ALL C.UTF-8
|
||||
|
||||
set -l build_tools (status dirname)
|
||||
set -l po_dir $build_tools/../localization/po
|
||||
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
|
||||
@@ -45,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 ""
|
||||
@@ -90,43 +91,52 @@ if set -l --query extract
|
||||
end
|
||||
|
||||
if set -l --query _flag_dry_run
|
||||
# On a dry run, we do not modify localization/po/ but write to a temporary directory instead
|
||||
# and check if there is a difference between localization/po/ and the tmpdir after re-generating
|
||||
# the PO files.
|
||||
# On a dry run, we do not modify po/ but write to a temporary directory instead and check if
|
||||
# there is a difference between po/ and the tmpdir after re-generating the PO files.
|
||||
set -g tmpdir (mktemp -d)
|
||||
|
||||
# Ensure tmpdir has the same initial state as the po dir.
|
||||
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
|
||||
@@ -135,20 +145,19 @@ 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
|
||||
|
||||
if set -g --query tmpdir[1]
|
||||
diff -ur $po_dir $tmpdir
|
||||
or begin
|
||||
echo ERROR: translations in localization/po/ are stale. Try running build_tools/update_translations.fish
|
||||
echo ERROR: translations in ./po/ are stale. Try running build_tools/update_translations.fish
|
||||
cleanup_exit
|
||||
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
|
||||
@@ -12,21 +12,11 @@ set(SPHINX_BUILD_DIR "${SPHINX_ROOT_DIR}/build")
|
||||
set(SPHINX_HTML_DIR "${SPHINX_ROOT_DIR}/html")
|
||||
set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
|
||||
|
||||
set(FISH_INDENT_FOR_BUILDING_DOCS "" CACHE FILEPATH "Path to fish_indent executable for building HTML docs")
|
||||
|
||||
if(FISH_INDENT_FOR_BUILDING_DOCS)
|
||||
get_filename_component(FISH_INDENT_DIR "${FISH_INDENT_FOR_BUILDING_DOCS}" DIRECTORY)
|
||||
set(SPHINX_HTML_FISH_INDENT_PATH ${FISH_INDENT_DIR})
|
||||
set(SPHINX_HTML_FISH_INDENT_DEP)
|
||||
else()
|
||||
set(SPHINX_HTML_FISH_INDENT_PATH ${CMAKE_BINARY_DIR})
|
||||
set(SPHINX_HTML_FISH_INDENT_DEP fish_indent)
|
||||
endif()
|
||||
|
||||
# sphinx-docs uses fish_indent for highlighting.
|
||||
# Prepend the output dir of fish_indent to PATH.
|
||||
add_custom_target(sphinx-docs
|
||||
mkdir -p ${SPHINX_HTML_DIR}/_static/
|
||||
COMMAND env FISH_BUILD_VERSION_FILE=${CMAKE_CURRENT_BINARY_DIR}/${FBVF}
|
||||
PATH="${SPHINX_HTML_FISH_INDENT_PATH}:$$PATH"
|
||||
COMMAND env PATH="${CMAKE_BINARY_DIR}:$$PATH"
|
||||
${SPHINX_EXECUTABLE}
|
||||
-j auto
|
||||
-q -b html
|
||||
@@ -34,12 +24,10 @@ add_custom_target(sphinx-docs
|
||||
-d "${SPHINX_ROOT_DIR}/.doctrees-html"
|
||||
"${SPHINX_SRC_DIR}"
|
||||
"${SPHINX_HTML_DIR}"
|
||||
DEPENDS
|
||||
CHECK-FISH-BUILD-VERSION-FILE
|
||||
${SPHINX_SRC_DIR}/fish_indent_lexer.py
|
||||
${SPHINX_HTML_FISH_INDENT_DEP}
|
||||
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
|
||||
COMMENT "Building HTML documentation with Sphinx")
|
||||
|
||||
# sphinx-manpages needs the fish_indent binary for the version number
|
||||
add_custom_target(sphinx-manpages
|
||||
env FISH_BUILD_VERSION_FILE=${CMAKE_CURRENT_BINARY_DIR}/${FBVF}
|
||||
${SPHINX_EXECUTABLE}
|
||||
@@ -48,36 +36,51 @@ add_custom_target(sphinx-manpages
|
||||
-c "${SPHINX_SRC_DIR}"
|
||||
-d "${SPHINX_ROOT_DIR}/.doctrees-man"
|
||||
"${SPHINX_SRC_DIR}"
|
||||
# TODO: This only works if we only have section 1 manpages.
|
||||
"${SPHINX_MANPAGE_DIR}/man1"
|
||||
DEPENDS CHECK-FISH-BUILD-VERSION-FILE
|
||||
COMMENT "Building man pages with Sphinx")
|
||||
|
||||
if(NOT DEFINED WITH_DOCS) # Don't check for legacy options if the new one is defined, to help bisecting.
|
||||
if(DEFINED BUILD_DOCS)
|
||||
message(FATAL_ERROR "the BUILD_DOCS option is no longer supported, use -DWITH_DOCS=ON|OFF")
|
||||
endif()
|
||||
if(DEFINED INSTALL_DOCS)
|
||||
message(FATAL_ERROR "the INSTALL_DOCS option is no longer supported, use -DWITH_DOCS=ON|OFF")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SPHINX_EXECUTABLE)
|
||||
option(WITH_DOCS "build documentation (requires Sphinx)" ON)
|
||||
else()
|
||||
option(WITH_DOCS "build documentation (requires Sphinx)" OFF)
|
||||
endif()
|
||||
option(BUILD_DOCS "build documentation (requires Sphinx)" ON)
|
||||
else(SPHINX_EXECUTABLE)
|
||||
option(BUILD_DOCS "build documentation (requires Sphinx)" OFF)
|
||||
endif(SPHINX_EXECUTABLE)
|
||||
|
||||
if(WITH_DOCS AND NOT SPHINX_EXECUTABLE)
|
||||
if(BUILD_DOCS AND NOT SPHINX_EXECUTABLE)
|
||||
message(FATAL_ERROR "build documentation selected, but sphinx-build could not be found")
|
||||
endif()
|
||||
|
||||
add_feature_info(Documentation WITH_DOCS "user manual and documentation")
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/html
|
||||
AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/man)
|
||||
set(HAVE_PREBUILT_DOCS TRUE)
|
||||
else()
|
||||
set(HAVE_PREBUILT_DOCS FALSE)
|
||||
endif()
|
||||
|
||||
if(WITH_DOCS)
|
||||
if(BUILD_DOCS OR HAVE_PREBUILT_DOCS)
|
||||
set(INSTALL_DOCS ON)
|
||||
else()
|
||||
set(INSTALL_DOCS OFF)
|
||||
endif()
|
||||
|
||||
add_feature_info(Documentation INSTALL_DOCS "user manual and documentation")
|
||||
|
||||
if(BUILD_DOCS)
|
||||
configure_file("${SPHINX_SRC_DIR}/conf.py" "${SPHINX_BUILD_DIR}/conf.py" @ONLY)
|
||||
add_custom_target(doc ALL
|
||||
DEPENDS sphinx-docs sphinx-manpages)
|
||||
|
||||
# Group docs targets into a DocsTargets folder
|
||||
set_property(TARGET doc sphinx-docs sphinx-manpages
|
||||
PROPERTY FOLDER cmake/DocTargets)
|
||||
endif()
|
||||
|
||||
elseif(HAVE_PREBUILT_DOCS)
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
# Out of tree build - link the prebuilt documentation to the build tree
|
||||
add_custom_target(link_doc ALL)
|
||||
add_custom_command(TARGET link_doc
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/user_doc ${CMAKE_CURRENT_BINARY_DIR}/user_doc
|
||||
POST_BUILD)
|
||||
endif()
|
||||
endif(BUILD_DOCS)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
set(CMAKE_INSTALL_MESSAGE NEVER)
|
||||
|
||||
set(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fish ${CMAKE_CURRENT_BINARY_DIR}/fish_indent ${CMAKE_CURRENT_BINARY_DIR}/fish_key_reader)
|
||||
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(bindir ${CMAKE_INSTALL_BINDIR})
|
||||
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
@@ -73,30 +75,22 @@ function(FISH_TRY_CREATE_DIRS)
|
||||
endforeach()
|
||||
endfunction(FISH_TRY_CREATE_DIRS)
|
||||
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fish
|
||||
install(PROGRAMS ${PROGRAMS}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
DESTINATION ${bindir})
|
||||
|
||||
if(NOT IS_ABSOLUTE ${bindir})
|
||||
set(abs_bindir "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${bindir}")
|
||||
else()
|
||||
set(abs_bindir "\$ENV{DESTDIR}${bindir}")
|
||||
endif()
|
||||
install(CODE "file(CREATE_LINK ${abs_bindir}/fish ${abs_bindir}/fish_indent)")
|
||||
install(CODE "file(CREATE_LINK ${abs_bindir}/fish ${abs_bindir}/fish_key_reader)")
|
||||
|
||||
fish_create_dirs(${sysconfdir}/fish/conf.d ${sysconfdir}/fish/completions
|
||||
${sysconfdir}/fish/functions)
|
||||
install(FILES etc/config.fish DESTINATION ${sysconfdir}/fish/)
|
||||
|
||||
fish_create_dirs(${rel_datadir}/fish ${rel_datadir}/fish/completions
|
||||
${rel_datadir}/fish/functions
|
||||
${rel_datadir}/fish/functions ${rel_datadir}/fish/groff
|
||||
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
|
||||
${rel_datadir}/fish/tools/web_config
|
||||
${rel_datadir}/fish/tools/web_config/js
|
||||
${rel_datadir}/fish/prompts
|
||||
${rel_datadir}/fish/themes
|
||||
${rel_datadir}/fish/tools/web_config/sample_prompts
|
||||
${rel_datadir}/fish/tools/web_config/themes
|
||||
)
|
||||
|
||||
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
|
||||
@@ -131,6 +125,9 @@ install(DIRECTORY share/functions/
|
||||
DESTINATION ${rel_datadir}/fish/functions
|
||||
FILES_MATCHING PATTERN "*.fish")
|
||||
|
||||
install(DIRECTORY share/groff
|
||||
DESTINATION ${rel_datadir}/fish)
|
||||
|
||||
# CONDEMNED_PAGE is managed by the conditional above
|
||||
# Building the man pages is optional: if sphinx isn't installed, they're not built
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/
|
||||
@@ -139,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
|
||||
|
||||
@@ -19,6 +19,7 @@ else()
|
||||
endif()
|
||||
|
||||
set(rust_profile $<IF:$<CONFIG:Debug>,debug,$<IF:$<CONFIG:RelWithDebInfo>,release-with-debug,release>>)
|
||||
set(rust_debugflags "$<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g>")
|
||||
|
||||
option(WITH_GETTEXT "Build with gettext localization support. Requires `msgfmt` to work." ON)
|
||||
# Enable gettext feature unless explicitly disabled.
|
||||
@@ -27,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,15 +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
|
||||
--features=${FISH_CARGO_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,480 +0,0 @@
|
||||
fish (4.3.2-1) stable; urgency=medium
|
||||
|
||||
* Release of new version 4.3.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.2 for details.
|
||||
|
||||
-- Johannes Altmanninger <aclopte@gmail.com> Tue, 30 Dec 2025 17:21:04 +0100
|
||||
|
||||
fish (4.3.1-1) stable; urgency=medium
|
||||
|
||||
* Release of new version 4.3.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.1 for details.
|
||||
|
||||
-- Johannes Altmanninger <aclopte@gmail.com> Sun, 28 Dec 2025 16:54:44 +0100
|
||||
|
||||
fish (4.3.0-1) stable; urgency=medium
|
||||
|
||||
* Release of new version 4.3.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.3.0 for details.
|
||||
|
||||
-- Johannes Altmanninger <aclopte@gmail.com> Sun, 28 Dec 2025 10:20:47 +0100
|
||||
|
||||
fish (4.2.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.2.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.2.1 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 13 Nov 2025 20:42:43 +0800
|
||||
|
||||
fish (4.2.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.2.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.2.0 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 10 Nov 2025 19:29:03 +0800
|
||||
|
||||
fish (4.1.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.1.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.1.2 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 08 Oct 2025 13:46:45 +0800
|
||||
|
||||
fish (4.1.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.1.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.1.1 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 03 Oct 2025 16:43:43 +0800
|
||||
|
||||
fish (4.0.8-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.0.8.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.8 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 18 Sep 2025 22:17:43 +0800
|
||||
|
||||
fish (4.0.6-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.0.6.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.6 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 17 Sep 2025 12:27:09 +0800
|
||||
|
||||
fish (4.0.2-2) testing; urgency=medium
|
||||
|
||||
* Fix tests on Debian.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 20 Apr 2025 23:08:14 +0800
|
||||
|
||||
fish (4.0.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.0.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.2 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 20 Apr 2025 21:24:18 +0800
|
||||
|
||||
fish (4.0.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.0.1.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 13 Mar 2025 11:30:21 +0800
|
||||
|
||||
fish (4.0.0-2) testing; urgency=medium
|
||||
|
||||
* Fix tests on Debian.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 27 Feb 2025 21:50:33 +0800
|
||||
|
||||
fish (4.0.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 4.0.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.0.0 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 27 Feb 2025 19:22:30 +0800
|
||||
|
||||
fish (4.0.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 4.0b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/4.0b1 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 17 Dec 2024 23:42:25 +0800
|
||||
|
||||
fish (3.7.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.7.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.7.1 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Mar 2024 13:26:22 +0800
|
||||
|
||||
fish (3.7.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.7.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.7.0 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 01 Jan 2024 23:32:55 +0800
|
||||
|
||||
fish (3.6.4-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.6.4.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.4 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 05 Dec 2023 22:34:09 +0800
|
||||
|
||||
fish (3.6.3-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.6.3.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.3 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 05 Dec 2023 00:11:12 +0800
|
||||
|
||||
fish (3.6.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.6.2.
|
||||
* Includes a fix for CVE-2023-49284.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.2 for details.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 04 Dec 2023 23:16:42 +0800
|
||||
|
||||
fish (3.6.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.6.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 25 Mar 2023 17:22:12 +0800
|
||||
|
||||
fish (3.6.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.6.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.6.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 07 Jan 2023 22:41:32 +0800
|
||||
|
||||
fish (3.5.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.5.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.5.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 20 Jul 2022 21:54:09 +0800
|
||||
|
||||
fish (3.5.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.5.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.5.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 16 Jun 2022 19:45:33 +0800
|
||||
|
||||
fish (3.4.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.4.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.4.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 12 Mar 2022 23:24:22 +0800
|
||||
|
||||
fish (3.3.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.3.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.3.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 06 Jul 2021 23:22:36 +0800
|
||||
|
||||
fish (3.3.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.3.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.3.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 28 Jun 2021 23:06:36 +0800
|
||||
|
||||
fish (3.2.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.2.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.2 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 07 Apr 2021 21:10:54 +0800
|
||||
|
||||
fish (3.2.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.2.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 18 Mar 2021 12:08:13 +0800
|
||||
|
||||
fish (3.2.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.2.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.2.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 01 Mar 2021 21:22:39 +0800
|
||||
|
||||
fish (3.1.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.1.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.2 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 29 Apr 2020 11:22:35 +0800
|
||||
|
||||
fish (3.1.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.1.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 27 Apr 2020 22:45:35 +0800
|
||||
|
||||
fish (3.1.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.1.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.1.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 12 Feb 2020 22:34:53 +0800
|
||||
|
||||
fish (3.1.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 3.1b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.1b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 26 Jan 2020 21:42:46 +0800
|
||||
|
||||
fish (3.0.2-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.0.2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.2 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Feb 2019 21:45:05 +0800
|
||||
|
||||
fish (3.0.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.0.1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 11 Feb 2019 20:23:55 +0800
|
||||
|
||||
fish (3.0.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 3.0.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.0.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 28 Dec 2018 21:10:28 +0800
|
||||
|
||||
fish (3.0.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 3.0b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/3.0b1 for
|
||||
significant changes, which includes backward incompatibility.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 11 Dec 2018 22:59:15 +0800
|
||||
|
||||
fish (2.7.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new bug fix version 2.7.1. On all Linux platforms, this is
|
||||
release will behave identically to 2.7.0.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 23 Dec 2017 00:43:12 +0800
|
||||
|
||||
fish (2.7.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.7.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.7.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 23 Nov 2017 18:38:21 +0800
|
||||
|
||||
fish (2.7.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.7b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.7b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 31 Oct 2017 20:32:29 +0800
|
||||
|
||||
fish (2.6.0-1) testing; urgency=medium
|
||||
|
||||
* Relase of new version 2.6.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.6.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 03 Jun 2017 20:51:50 +0800
|
||||
|
||||
fish (2.6b1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.6b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.6b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 14 May 2017 10:47:39 +0800
|
||||
|
||||
fish (2.5.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.5.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.5.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Fri, 03 Feb 2017 09:52:57 +0800
|
||||
|
||||
fish (2.5b1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.5b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.5b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 14 Jan 2017 08:49:34 +0800
|
||||
|
||||
fish (2.4.0-2) testing; urgency=medium
|
||||
|
||||
* Change recommendation of xdg-utils to suggestion (closes
|
||||
https://github.com/fish-shell/fish-shell/issues/3534).
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Wed, 09 Nov 2016 22:56:16 +0800
|
||||
|
||||
fish (2.4.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.4.0.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.4.0 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 08 Nov 2016 11:29:57 +0800
|
||||
|
||||
fish (2.4b1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.4b1.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.4b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 18 Oct 2016 22:25:26 +0800
|
||||
|
||||
fish (2.3.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.3.1.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 03 Jul 2016 21:21:51 +0800
|
||||
|
||||
fish (2.3.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.3.0.
|
||||
|
||||
See http://fishshell.com/release_notes.html for significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 21 May 2016 06:59:54 +0800
|
||||
|
||||
fish (2.3b2-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.3b2.
|
||||
|
||||
See https://github.com/fish-shell/fish-shell/releases/tag/2.3b2 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 05 May 2016 06:22:37 +0800
|
||||
|
||||
fish (2.3.1-1) testing; urgency=medium
|
||||
|
||||
* Release of new beta version 2.3b1.
|
||||
|
||||
See http://github.com/fish-shell/fish-shell/releases/tag/2.3b1 for
|
||||
significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Tue, 19 Apr 2016 21:07:17 +0800
|
||||
|
||||
fish (2.2.0-2) testing; urgency=medium
|
||||
|
||||
* Binary rebuild only to resynchronise repository state.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Mon, 15 Feb 2016 22:45:05 +0800
|
||||
|
||||
fish (2.2.0-1) testing; urgency=medium
|
||||
|
||||
* Release of new version 2.2.0.
|
||||
|
||||
See http://fishshell.com/release_notes.html for significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 12 Jul 2015 18:52:29 +0800
|
||||
|
||||
fish (2.2b1-1) testing; urgency=low
|
||||
|
||||
* Release of new beta version 2.2b1.
|
||||
|
||||
See http://fishshell.com/staging/release_notes.html for significant
|
||||
changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 07 May 2015 14:48:21 +0800
|
||||
|
||||
fish (2.1.1-1) unstable; urgency=high
|
||||
|
||||
* Release of new version 2.1.1.
|
||||
|
||||
See http://fishshell.com/release_notes.html for significant changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sun, 07 Sep 2014 17:06:31 +0800
|
||||
|
||||
fish (2.1.0-1) unstable; urgency=low
|
||||
|
||||
* Release of new version 2.1.0.
|
||||
|
||||
See http://fishshell.com/staging/release_notes.html for significant
|
||||
changes.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Sat, 19 Oct 2013 14:35:23 +0800
|
||||
|
||||
fish (2.0.0-0) unstable; urgency=low
|
||||
|
||||
* Initial release of fish 2.0.0.
|
||||
|
||||
-- David Adam <zanchey@ucc.gu.uwa.edu.au> Thu, 19 Jul 2012 23:17:58 +0800
|
||||
@@ -4,7 +4,6 @@ edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
rsconf.workspace = true
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
@@ -45,41 +29,3 @@ pub fn rebuild_if_paths_changed<P: AsRef<Path>, I: IntoIterator<Item = P>>(paths
|
||||
rsconf::rebuild_if_path_changed(path.as_ref().to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuild_if_embedded_path_changed<P: AsRef<Path>>(path: P) {
|
||||
// Not necessary in debug builds, where rust-embed reads from the filesystem.
|
||||
if cfg!(any(not(debug_assertions), windows)) {
|
||||
rebuild_if_path_changed(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Target OS for compiling our crates, as opposed to the build script.
|
||||
pub fn target_os() -> String {
|
||||
env_var("CARGO_CFG_TARGET_OS").unwrap()
|
||||
}
|
||||
|
||||
pub fn target_os_is_apple() -> bool {
|
||||
matches!(target_os().as_str(), "ios" | "macos")
|
||||
}
|
||||
|
||||
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
|
||||
/// `#[cfg(bsd)]`.
|
||||
///
|
||||
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
|
||||
/// doesn't necessarily include less-popular forks nor does it group them into families more
|
||||
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
|
||||
pub fn target_os_is_bsd() -> bool {
|
||||
let target_os = target_os();
|
||||
let is_bsd = target_os.ends_with("bsd") || target_os == "dragonfly";
|
||||
if matches!(
|
||||
target_os.as_str(),
|
||||
"dragonfly" | "freebsd" | "netbsd" | "openbsd"
|
||||
) {
|
||||
assert!(is_bsd, "Target incorrectly detected as not BSD!");
|
||||
}
|
||||
is_bsd
|
||||
}
|
||||
|
||||
pub fn target_os_is_cygwin() -> bool {
|
||||
target_os() == "cygwin"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
fish-build-helper.workspace = true
|
||||
|
||||
@@ -1,62 +1,53 @@
|
||||
#[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");
|
||||
// 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);
|
||||
if !cfg!(clippy) {
|
||||
build_man(&man_dir, &sec1_dir);
|
||||
}
|
||||
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(sec1dir.to_str().unwrap());
|
||||
|
||||
#[cfg(not(clippy))]
|
||||
build_man(&mandir);
|
||||
}
|
||||
|
||||
fn build_man(man_dir: &Path, sec1_dir: &Path) {
|
||||
use fish_build_helper::{env_var, workspace_root};
|
||||
#[cfg(not(clippy))]
|
||||
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 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,
|
||||
])
|
||||
};
|
||||
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;
|
||||
}
|
||||
@@ -66,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,15 +0,0 @@
|
||||
[package]
|
||||
name = "fish-common"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
libc.workspace = true
|
||||
nix.workspace = true
|
||||
once_cell.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,60 +0,0 @@
|
||||
use libc::STDIN_FILENO;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::env;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
// These are in the Unicode private-use range. We really shouldn't use this
|
||||
// range but have little choice in the matter given how our lexer/parser works.
|
||||
// We can't use non-characters for these two ranges because there are only 66 of
|
||||
// them and we need at least 256 + 64.
|
||||
//
|
||||
// If sizeof(wchar_t))==4 we could avoid using private-use chars; however, that
|
||||
// would result in fish having different behavior on machines with 16 versus 32
|
||||
// bit wchar_t. It's better that fish behave the same on both types of systems.
|
||||
//
|
||||
// Note: We don't use the highest 8 bit range (0xF800 - 0xF8FF) because we know
|
||||
// of at least one use of a codepoint in that range: the Apple symbol (0xF8FF)
|
||||
// on Mac OS X. See http://www.unicode.org/faq/private_use.html.
|
||||
pub const ENCODE_DIRECT_BASE: char = '\u{F600}';
|
||||
pub const ENCODE_DIRECT_END: char = char_offset(ENCODE_DIRECT_BASE, 256);
|
||||
|
||||
pub const fn char_offset(base: char, offset: u32) -> char {
|
||||
match char::from_u32(base as u32 + offset) {
|
||||
Some(c) => c,
|
||||
None => panic!("not a valid char"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subslice_position<T: Eq>(a: &[T], b: &[T]) -> Option<usize> {
|
||||
if b.is_empty() {
|
||||
return Some(0);
|
||||
}
|
||||
a.windows(b.len()).position(|aw| aw == b)
|
||||
}
|
||||
|
||||
/// This function attempts to distinguish between a console session (at the actual login vty) and a
|
||||
/// session within a terminal emulator inside a desktop environment or over SSH. Unfortunately
|
||||
/// there are few values of $TERM that we can interpret as being exclusively console sessions, and
|
||||
/// most common operating systems do not use them. The value is cached for the duration of the fish
|
||||
/// session. We err on the side of assuming it's not a console session. This approach isn't
|
||||
/// bullet-proof and that's OK.
|
||||
pub fn is_console_session() -> bool {
|
||||
static IS_CONSOLE_SESSION: OnceCell<bool> = OnceCell::new();
|
||||
// TODO(terminal-workaround)
|
||||
*IS_CONSOLE_SESSION.get_or_init(|| {
|
||||
nix::unistd::ttyname(unsafe { std::os::fd::BorrowedFd::borrow_raw(STDIN_FILENO) })
|
||||
.is_ok_and(|buf| {
|
||||
// Check if the tty matches /dev/(console|dcons|tty[uv\d])
|
||||
let is_console_tty = match buf.as_os_str().as_bytes() {
|
||||
b"/dev/console" => true,
|
||||
b"/dev/dcons" => true,
|
||||
bytes => bytes.strip_prefix(b"/dev/tty").is_some_and(|rest| {
|
||||
matches!(rest.first(), Some(b'u' | b'v' | b'0'..=b'9'))
|
||||
}),
|
||||
};
|
||||
|
||||
// and that $TERM is simple, e.g. `xterm` or `vt100`, not `xterm-something` or `sun-color`.
|
||||
is_console_tty && env::var_os("TERM").is_none_or(|t| !t.as_bytes().contains(&b'-'))
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "fish-fallback"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
fish-common.workspace = true
|
||||
fish-wchar.workspace = true
|
||||
fish-widecharwidth.workspace = true
|
||||
libc.workspace = true
|
||||
once_cell.workspace = true
|
||||
widestring.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
fish-build-helper.workspace = true
|
||||
rsconf.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,5 +0,0 @@
|
||||
use fish_build_helper::target_os_is_cygwin;
|
||||
|
||||
fn main() {
|
||||
rsconf::declare_cfg("cygwin", target_os_is_cygwin())
|
||||
}
|
||||
@@ -4,18 +4,13 @@ edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
description = "proc-macro for extracting strings for gettext translation"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
fish-tempfile.workspace = true
|
||||
proc-macro2.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
rsconf.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
rsconf::rebuild_if_env_changed("FISH_GETTEXT_EXTRACTION_DIR");
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
extern crate proc_macro;
|
||||
use fish_tempfile::random_filename;
|
||||
use proc_macro::TokenStream;
|
||||
use std::{ffi::OsString, io::Write, path::PathBuf};
|
||||
use std::{ffi::OsString, fs::OpenOptions, io::Write};
|
||||
|
||||
fn unescape_multiline_rust_string(s: String) -> String {
|
||||
if !s.contains('\n') {
|
||||
@@ -43,14 +42,15 @@ enum State {
|
||||
unescaped
|
||||
}
|
||||
|
||||
// Each entry is written to a fresh file to avoid race conditions arising when there are multiple
|
||||
// unsynchronized writers to the same file.
|
||||
fn write_po_entry_to_file(message: &TokenStream, dir: &OsString) {
|
||||
fn append_po_entry_to_file(message: &TokenStream, file_name: &OsString) {
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(file_name)
|
||||
.unwrap_or_else(|e| panic!("Could not open file {file_name:?}: {e}"));
|
||||
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('%') {
|
||||
@@ -59,58 +59,48 @@ fn write_po_entry_to_file(message: &TokenStream, dir: &OsString) {
|
||||
""
|
||||
};
|
||||
let po_entry = format!("{format_string_annotation}msgid {message_string}\nmsgstr \"\"\n\n");
|
||||
|
||||
let dir = PathBuf::from(dir);
|
||||
let (path, result) =
|
||||
fish_tempfile::create_file_with_retry(|| dir.join(random_filename(OsString::new())));
|
||||
let mut file = result.unwrap_or_else(|e| {
|
||||
panic!("Failed to create temporary file {path:?}:\n{e}");
|
||||
});
|
||||
file.write_all(po_entry.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
/// The `message` is passed through unmodified.
|
||||
/// If `FISH_GETTEXT_EXTRACTION_DIR` is defined in the environment,
|
||||
/// the message ID is written into a new file in this directory,
|
||||
/// If `FISH_GETTEXT_EXTRACTION_FILE` is defined in the environment,
|
||||
/// this file is used to write the message,
|
||||
/// so that it can then be used for generating gettext PO files.
|
||||
/// The `message` must be a string literal.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This macro panics if the `FISH_GETTEXT_EXTRACTION_DIR` variable is set and `message` has an
|
||||
/// This macro panics if the `FISH_GETTEXT_EXTRACTION_FILE` variable is set and `message` has an
|
||||
/// unexpected format.
|
||||
/// Note that for example `concat!(...)` cannot be passed to this macro, because expansion works
|
||||
/// outside in, meaning this macro would still see the `concat!` macro invocation, instead of a
|
||||
/// string literal.
|
||||
#[proc_macro]
|
||||
pub fn gettext_extract(message: TokenStream) -> TokenStream {
|
||||
if let Some(dir_path) = std::env::var_os("FISH_GETTEXT_EXTRACTION_DIR") {
|
||||
if let Some(file_path) = std::env::var_os("FISH_GETTEXT_EXTRACTION_FILE") {
|
||||
let pm2_message = proc_macro2::TokenStream::from(message.clone());
|
||||
let mut token_trees = pm2_message.into_iter();
|
||||
let first_token = token_trees
|
||||
.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 {
|
||||
write_po_entry_to_file(&message, &dir_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
|
||||
|
||||
@@ -4,7 +4,6 @@ edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
phf.workspace = true
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
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");
|
||||
embed_localizations(&cache_dir);
|
||||
|
||||
fish_build_helper::rebuild_if_path_changed(
|
||||
fish_build_helper::workspace_root()
|
||||
.join("localization")
|
||||
.join("po"),
|
||||
);
|
||||
fish_build_helper::rebuild_if_path_changed(fish_build_helper::workspace_root().join("po"));
|
||||
}
|
||||
|
||||
fn embed_localizations(cache_dir: &Path) {
|
||||
@@ -25,37 +20,36 @@ fn embed_localizations(cache_dir: &Path) {
|
||||
io::{BufWriter, Write},
|
||||
};
|
||||
|
||||
let po_dir = fish_build_helper::workspace_root()
|
||||
.join("localization")
|
||||
.join("po");
|
||||
let po_dir = fish_build_helper::workspace_root().join("po");
|
||||
|
||||
// Ensure that the directory is created, because clippy cannot compile the code if the
|
||||
// directory does not exist.
|
||||
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 localization/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();
|
||||
@@ -97,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();
|
||||
|
||||
@@ -4,7 +4,6 @@ edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
[package]
|
||||
name = "fish-gettext"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
fish-gettext-maps.workspace = true
|
||||
once_cell.workspace = true
|
||||
phf.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,268 +0,0 @@
|
||||
use fish_gettext_maps::CATALOGS;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{collections::HashSet, sync::Mutex};
|
||||
|
||||
type Catalog = &'static phf::Map<&'static str, &'static str>;
|
||||
|
||||
pub struct SetLanguageLints<'a> {
|
||||
pub duplicates: Vec<&'a str>,
|
||||
pub non_existing: Vec<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum LanguagePrecedenceOrigin {
|
||||
Default,
|
||||
LocaleVariable(LocaleVariable),
|
||||
LanguageEnvVar,
|
||||
StatusLanguage,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum LocaleVariable {
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
LANG,
|
||||
#[allow(non_camel_case_types)]
|
||||
LC_MESSAGES,
|
||||
#[allow(non_camel_case_types)]
|
||||
LC_ALL,
|
||||
}
|
||||
|
||||
impl LocaleVariable {
|
||||
fn as_language_precedence_origin(&self) -> LanguagePrecedenceOrigin {
|
||||
LanguagePrecedenceOrigin::LocaleVariable(*self)
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::LANG => "LANG",
|
||||
Self::LC_MESSAGES => "LC_MESSAGES",
|
||||
Self::LC_ALL => "LC_ALL",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LocaleVariable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
struct InternalLocalizationState {
|
||||
precedence_origin: LanguagePrecedenceOrigin,
|
||||
language_precedence: Vec<(String, Catalog)>,
|
||||
}
|
||||
|
||||
pub struct PublicLocalizationState {
|
||||
pub precedence_origin: LanguagePrecedenceOrigin,
|
||||
pub language_precedence: Vec<String>,
|
||||
}
|
||||
|
||||
/// Stores the current localization status.
|
||||
/// `is_active` indicates whether localization is currently active, and the reason if it is
|
||||
/// not.
|
||||
/// The `origin` indicates where the values in `language_precedence` were taken from.
|
||||
/// `language_precedence` stores the catalogs in the order they should be used.
|
||||
///
|
||||
/// This struct should be updated when the relevant variables change or `status language` is used
|
||||
/// to modify the localization state.
|
||||
static LOCALIZATION_STATE: Lazy<Mutex<InternalLocalizationState>> =
|
||||
Lazy::new(|| Mutex::new(InternalLocalizationState::new()));
|
||||
|
||||
impl InternalLocalizationState {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
precedence_origin: LanguagePrecedenceOrigin::Default,
|
||||
language_precedence: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn to_public(&self) -> PublicLocalizationState {
|
||||
PublicLocalizationState {
|
||||
precedence_origin: self.precedence_origin,
|
||||
language_precedence: self
|
||||
.language_precedence
|
||||
.iter()
|
||||
.map(|(lang, _)| lang.to_owned())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_from_env(
|
||||
&mut self,
|
||||
message_locale: Option<(LocaleVariable, String)>,
|
||||
language_var: Option<Vec<String>>,
|
||||
) {
|
||||
// Do not override values set via `status language`.
|
||||
if self.precedence_origin == LanguagePrecedenceOrigin::StatusLanguage {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some((precedence_origin, locale)) = &message_locale {
|
||||
// Regular locale names start with lowercase letters (`ll_CC`, followed by some suffix).
|
||||
// The C or POSIX locale is special, and often used to disable localization.
|
||||
// Their names are upper-case, but variants with suffixes (`C.UTF-8`) exist.
|
||||
// To ensure that such variants are accounted for, we match on prefixes of the
|
||||
// locale name.
|
||||
// https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html#tag_07_02
|
||||
fn is_c_locale(locale: &str) -> bool {
|
||||
locale.starts_with('C') || locale.starts_with("POSIX")
|
||||
}
|
||||
if is_c_locale(locale) {
|
||||
self.precedence_origin =
|
||||
LanguagePrecedenceOrigin::LocaleVariable(*precedence_origin);
|
||||
self.language_precedence.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let (precedence_origin, language_list) = if let Some(list) = language_var {
|
||||
(LanguagePrecedenceOrigin::LanguageEnvVar, list)
|
||||
} else if let Some((precedence_origin, locale)) = message_locale {
|
||||
let mut normalized_name = String::new();
|
||||
// Strip off encoding and modifier. (We always expect UTF-8 and don't support modifiers.)
|
||||
for c in locale.chars() {
|
||||
if c.is_alphabetic() || c == '_' {
|
||||
normalized_name.push(c);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point, the normalized_name should have the shape `ll` or `ll_CC`.
|
||||
(
|
||||
precedence_origin.as_language_precedence_origin(),
|
||||
vec![normalized_name],
|
||||
)
|
||||
} else {
|
||||
(LanguagePrecedenceOrigin::Default, vec![])
|
||||
};
|
||||
|
||||
let mut seen_languages = HashSet::new();
|
||||
self.language_precedence = language_list
|
||||
.into_iter()
|
||||
.flat_map(|lang| find_existing_catalogs(&lang))
|
||||
.filter(|(lang, _)| seen_languages.insert(lang.to_owned()))
|
||||
.collect();
|
||||
self.precedence_origin = precedence_origin;
|
||||
}
|
||||
|
||||
fn update_from_status_language_builtin<'a, 'b: 'a, S: AsRef<str> + 'a>(
|
||||
&mut self,
|
||||
langs: &'b [S],
|
||||
) -> SetLanguageLints<'a> {
|
||||
let mut seen = HashSet::new();
|
||||
let mut duplicates = vec![];
|
||||
for lang in langs {
|
||||
let lang = lang.as_ref();
|
||||
if !seen.insert(lang) {
|
||||
duplicates.push(lang)
|
||||
}
|
||||
}
|
||||
let mut existing_langs = vec![];
|
||||
let mut non_existing = vec![];
|
||||
for lang in langs {
|
||||
let lang = lang.as_ref();
|
||||
if let Some(catalog) = CATALOGS.get(lang) {
|
||||
existing_langs.push((lang.to_owned(), *catalog));
|
||||
} else {
|
||||
non_existing.push(lang);
|
||||
}
|
||||
}
|
||||
|
||||
let mut seen = HashSet::new();
|
||||
let unique_langs = existing_langs
|
||||
.into_iter()
|
||||
.filter(|(lang, _)| seen.insert(lang.to_owned()))
|
||||
.collect();
|
||||
self.language_precedence = unique_langs;
|
||||
self.precedence_origin = LanguagePrecedenceOrigin::StatusLanguage;
|
||||
|
||||
SetLanguageLints {
|
||||
duplicates,
|
||||
non_existing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to find catalogs for `language`.
|
||||
/// `language` must be an ISO 639 language code, optionally followed by an underscore and an ISO
|
||||
/// 3166 country/territory code.
|
||||
/// Uses the catalog with the exact same name as `language` if it exists.
|
||||
/// If a country code is present (`ll_CC`), only the catalog named `ll` will be considered as a fallback.
|
||||
/// If no country code is present (`ll`), all catalogs whose names start with `ll_` will be used in
|
||||
/// arbitrary order.
|
||||
fn find_existing_catalogs(language: &str) -> Vec<(String, Catalog)> {
|
||||
// Try the exact name first.
|
||||
// If there already is a corresponding catalog return the language.
|
||||
if let Some(catalog) = CATALOGS.get(language) {
|
||||
return vec![(language.to_owned(), catalog)];
|
||||
}
|
||||
let language_without_country_code = language.split_once('_').map_or(language, |(ll, _cc)| ll);
|
||||
if language == language_without_country_code {
|
||||
// We have `ll` format. In this case, try to find any catalog whose name starts with `ll_`.
|
||||
// Note that it is important to include the underscore in the pattern, otherwise `ll` might
|
||||
// fall back to `llx_CC`, where `llx` is a 3-letter language identifier.
|
||||
let ll_prefix = format!("{language}_");
|
||||
let mut lang_catalogs = vec![];
|
||||
for (&lang_name, &catalog) in CATALOGS.entries() {
|
||||
if lang_name.starts_with(&ll_prefix) {
|
||||
lang_catalogs.push((lang_name.to_owned(), catalog));
|
||||
}
|
||||
}
|
||||
lang_catalogs
|
||||
} else {
|
||||
// If `language` contained a country code, we only try to fall back to a catalog
|
||||
// without a country code.
|
||||
if let Some(catalog) = CATALOGS.get(language_without_country_code) {
|
||||
vec![(language_without_country_code.to_owned(), catalog)]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_from_env(
|
||||
locale: Option<(LocaleVariable, String)>,
|
||||
language_var: Option<Vec<String>>,
|
||||
) {
|
||||
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
|
||||
localization_state.update_from_env(locale, language_var);
|
||||
}
|
||||
|
||||
pub fn update_from_status_language_builtin<'a, 'b: 'a, S: AsRef<str> + 'a>(
|
||||
langs: &'b [S],
|
||||
) -> SetLanguageLints<'a> {
|
||||
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
|
||||
localization_state.update_from_status_language_builtin(langs)
|
||||
}
|
||||
|
||||
pub fn unset_from_status_language_builtin(
|
||||
locale: Option<(LocaleVariable, String)>,
|
||||
language_var: Option<Vec<String>>,
|
||||
) {
|
||||
let mut localization_state = LOCALIZATION_STATE.lock().unwrap();
|
||||
localization_state.precedence_origin = LanguagePrecedenceOrigin::Default;
|
||||
localization_state.update_from_env(locale, language_var);
|
||||
}
|
||||
|
||||
pub fn status_language() -> PublicLocalizationState {
|
||||
let localization_state = LOCALIZATION_STATE.lock().unwrap();
|
||||
localization_state.to_public()
|
||||
}
|
||||
|
||||
pub fn gettext(message_str: &'static str) -> Option<&'static str> {
|
||||
let localization_state = LOCALIZATION_STATE.lock().unwrap();
|
||||
|
||||
// Use the localization from the highest-precedence language that has one available.
|
||||
for (_, catalog) in localization_state.language_precedence.iter() {
|
||||
if let Some(localized_str) = catalog.get(message_str) {
|
||||
return Some(localized_str);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn list_available_languages() -> Vec<&'static str> {
|
||||
let mut langs: Vec<_> = CATALOGS.entries().map(|(&lang, _)| lang).collect();
|
||||
langs.sort();
|
||||
langs
|
||||
}
|
||||
@@ -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)));
|
||||
@@ -233,7 +242,7 @@ fn test_to_arg() {
|
||||
assert!(matches!(42u64.to_arg(), Arg::UInt(42)));
|
||||
assert!(matches!(42usize.to_arg(), Arg::UInt(42)));
|
||||
|
||||
let ptr = std::ptr::from_ref(&42f32);
|
||||
let ptr = &42f32 as *const f32;
|
||||
assert!(matches!(ptr.to_arg(), Arg::UInt(_)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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,8 +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
|
||||
@@ -77,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!("" => "");
|
||||
}
|
||||
@@ -225,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");
|
||||
@@ -234,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");
|
||||
@@ -249,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");
|
||||
@@ -416,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");
|
||||
@@ -433,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");
|
||||
@@ -758,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);
|
||||
@@ -855,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}
|
||||
@@ -884,33 +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();
|
||||
let len = libc::snprintf(
|
||||
storage_ptr.cast(),
|
||||
storage.len(),
|
||||
fmt.as_ptr(),
|
||||
preci,
|
||||
float_val,
|
||||
);
|
||||
assert!(len >= 0);
|
||||
let sl = std::slice::from_raw_parts(storage_ptr, 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 {
|
||||
@@ -922,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
|
||||
@@ -941,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,14 +0,0 @@
|
||||
[package]
|
||||
name = "fish-tempfile"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
nix = { workspace = true, features = ["fs", "feature"] }
|
||||
rand.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,171 +0,0 @@
|
||||
use std::{
|
||||
ffi::OsString,
|
||||
fs::{File, OpenOptions},
|
||||
io::ErrorKind,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use rand::distr::{Alphanumeric, Distribution};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a random filename with the given prefix.
|
||||
/// Appends a random sequence of alphanumeric ASCII characters.
|
||||
pub fn random_filename(mut prefix: OsString) -> OsString {
|
||||
let mut rng = rand::rng();
|
||||
let suffix_length = 10;
|
||||
let random_part: String = Alphanumeric
|
||||
.sample_iter(&mut rng)
|
||||
.take(suffix_length)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
assert_eq!(random_part.len(), suffix_length);
|
||||
prefix.push(random_part);
|
||||
prefix
|
||||
}
|
||||
|
||||
/// Tries to create a new file at the path returned by `generate_path`.
|
||||
/// If a file already exists at this path, `generate_path` will be called again and file creation
|
||||
/// will be retried. This is repeated until a new file is created, or an error occurs.
|
||||
pub fn create_file_with_retry(
|
||||
generate_path: impl Fn() -> PathBuf,
|
||||
) -> (PathBuf, std::io::Result<File>) {
|
||||
loop {
|
||||
let path = generate_path();
|
||||
match OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(&path)
|
||||
{
|
||||
Ok(file) => {
|
||||
return (path, Ok(file));
|
||||
}
|
||||
Err(e) => {
|
||||
if e.kind() != ErrorKind::AlreadyExists {
|
||||
return (path, Err(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to create a new temporary file in the operating system's default location for temporary
|
||||
/// files.
|
||||
/// On success, a [`TempFile`] is returned.
|
||||
/// When this struct is dropped, the backing file will be deleted.
|
||||
pub fn new_file() -> std::io::Result<TempFile> {
|
||||
let (path, result) = create_file_with_retry(|| {
|
||||
std::env::temp_dir().join(random_filename(OsString::from("fish_tmp_")))
|
||||
});
|
||||
let file = result?;
|
||||
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 template = std::env::temp_dir().join("fish_tmp_XXXXXX");
|
||||
let path = nix::unistd::mkdtemp(&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");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "fish-wchar"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
fish-common.workspace = true
|
||||
widestring.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "fish-widecharwidth"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
repository.workspace = true
|
||||
license = "CC0-1.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
23
contrib/debian/control → debian/control
vendored
23
contrib/debian/control → debian/control
vendored
@@ -3,31 +3,32 @@ Section: shells
|
||||
Priority: optional
|
||||
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
|
||||
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
# -web is for Debian's updated version, -X.Y is for Ubuntu's backported versions
|
||||
cargo (>= 1.85) | cargo-web (>= 1.85) | cargo-1.85,
|
||||
cmake (>= 3.15.0),
|
||||
Build-Depends: debhelper (>= 12),
|
||||
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,
|
||||
sphinx-doc,
|
||||
rustc (>= 1.70),
|
||||
# Test dependencies
|
||||
locales-all,
|
||||
man-db,
|
||||
ncurses-base,
|
||||
python3
|
||||
# 4.6.2 is Debian 12/Ubuntu Noble 24.04; Ubuntu Jammy is 4.6.0.1
|
||||
Standards-Version: 4.6.2
|
||||
Standards-Version: 4.1.5
|
||||
Homepage: https://fishshell.com/
|
||||
Vcs-Git: https://github.com/fish-shell/fish-shell.git
|
||||
Vcs-Browser: https://github.com/fish-shell/fish-shell
|
||||
|
||||
Package: fish
|
||||
Architecture: any
|
||||
# for col and lock
|
||||
Depends: bsdextrautils,
|
||||
# for col and lock - bsdmainutils is required in Ubuntu focal
|
||||
Depends: bsdextrautils | bsdmainutils,
|
||||
file,
|
||||
# for the msgfmt command
|
||||
gettext-base,
|
||||
# for man
|
||||
man-db,
|
||||
# for terminal definitions
|
||||
ncurses-base,
|
||||
# for kill
|
||||
procps,
|
||||
python3 (>=3.5),
|
||||
4
contrib/debian/copyright → debian/copyright
vendored
4
contrib/debian/copyright → debian/copyright
vendored
@@ -17,11 +17,11 @@ Files: share/tools/web_config/js/alpine.js
|
||||
Copyright: 2019-2021 Caleb Porzio and contributors
|
||||
License: MIT
|
||||
|
||||
Files: share/themes/Dracula.theme
|
||||
Files: share/tools/web_config/themes/Dracula.theme
|
||||
Copyright: 2018 Dracula Team
|
||||
License: MIT
|
||||
|
||||
Files: share/themes/Nord.theme
|
||||
Files: share/tools/web_config/themes/Nord.theme
|
||||
Copyright: 2016-2024 Sven Greb
|
||||
License: MIT
|
||||
|
||||
0
contrib/debian/docs → debian/docs
vendored
0
contrib/debian/docs → debian/docs
vendored
0
contrib/debian/prerm → debian/prerm
vendored
0
contrib/debian/prerm → debian/prerm
vendored
15
contrib/debian/rules → debian/rules
vendored
15
contrib/debian/rules → debian/rules
vendored
@@ -1,25 +1,20 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
ifeq (,$(filter terse,$(DEB_BUILD_OPTIONS)))
|
||||
export DH_VERBOSE=1
|
||||
# VERBOSE to satisfy Debian policy 4.9, introduced in version 4.2.0
|
||||
export CARGO_TERM_VERBOSE=true
|
||||
endif
|
||||
# Uncomment this to turn on verbose mode.
|
||||
export DH_VERBOSE=1
|
||||
# The LTO profile sets CFLAGS/CXXFLAGS which confuse the compilation process; disable it
|
||||
# LTO is still performed by rustc based on Cargo.toml
|
||||
export DEB_BUILD_MAINT_OPTIONS=optimize=-lto
|
||||
|
||||
%:
|
||||
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
|
||||
@@ -27,4 +22,4 @@ override_dh_clean:
|
||||
-unlink vendor
|
||||
|
||||
override_dh_auto_test:
|
||||
cd build && make fish_run_tests
|
||||
make fish_run_tests
|
||||
@@ -6,12 +6,9 @@ allow = [
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause",
|
||||
"BSL-1.0",
|
||||
"CC0-1.0",
|
||||
"GPL-2.0",
|
||||
"GPL-2.0-only",
|
||||
"ISC",
|
||||
"LGPL-2.0",
|
||||
"LGPL-2.0-or-later",
|
||||
"MIT",
|
||||
"MPL-2.0",
|
||||
"PSF-2.0",
|
||||
|
||||
@@ -31,7 +31,7 @@ The work will **proceed on master**: no long-lived branches. Tests and CI contin
|
||||
|
||||
The Rust code will initially resemble the replaced C++. Fidelity to existing code is more important than Rust idiomaticity, to aid review and bisecting. But don't take this to extremes - use judgement.
|
||||
|
||||
The port will proceed "outside in." We'll start with leaf components (e.g. builtins) and proceed towards the core. Some components will have both a Rust and C++ implementation (e.g. flog), in other cases we'll change the existing C++ to invoke the new Rust implementations (builtins).
|
||||
The port will proceed "outside in." We'll start with leaf components (e.g. builtins) and proceed towards the core. Some components will have both a Rust and C++ implementation (e.g. FLOG), in other cases we'll change the existing C++ to invoke the new Rust implementations (builtins).
|
||||
|
||||
After porting the C++, we'll replace CMake.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -58,7 +58,7 @@ The basic development loop for this port:
|
||||
- Do this even if it results in less idiomatic Rust, but avoid being super-dogmatic either way.
|
||||
- One technique is to paste the C++ into the Rust code, commented out, and go line by line.
|
||||
4. Decide whether any existing C++ callers should invoke the Rust implementation, or whether we should keep the C++ one.
|
||||
- Utility functions may have both a Rust and C++ implementation. An example is `flog` where interop is too hard.
|
||||
- Utility functions may have both a Rust and C++ implementation. An example is `FLOG` where interop is too hard.
|
||||
- Major components (e.g. builtin implementations) should _not_ be duplicated; instead the Rust should call C++ or vice-versa.
|
||||
5. Remember to run `cargo fmt` and `cargo clippy` to keep the codebase somewhat clean (otherwise CI will fail). If you use rust-analyzer, you can run clippy automatically by setting `rust-analyzer.checkOnSave.command = "clippy"`.
|
||||
|
||||
@@ -93,7 +93,7 @@ None of the Rust string types are nul-terminated. We're taking this opportunity
|
||||
One may create a `&wstr` from a string literal using the `wchar::L!` macro:
|
||||
|
||||
```rust
|
||||
use crate::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
// This imports wstr, the L! macro, WString, a ToWString trait that supplies .to_wstring() along with other things
|
||||
|
||||
fn get_shell_name() -> &'static wstr {
|
||||
@@ -116,7 +116,7 @@ fn get_shell_name() -> &'static wstr {
|
||||
#### The wchar prelude
|
||||
|
||||
We have a prelude to make working with these string types a whole lot more ergonomic. In particular `WExt` supplies the null-terminated-compatible `.char_at(usize)`,
|
||||
and a whole lot more methods that makes porting C++ code easier. It is also preferred to use char-based-methods like `.char_count()` and `.slice_{from,to}()`
|
||||
and a whole lot more methods that makes porting C++ code easier. It is also preferred to use char-based-methods like `.char_count()` and `.slice_{from,to}()`
|
||||
of the `WExt` trait over directly calling `.len()` and `[usize..]/[..usize]`, as that makes the code compatible with a potential future change to UTF8-strings.
|
||||
|
||||
```rust
|
||||
@@ -144,7 +144,7 @@ These types should be confined to the FFI modules, in particular `wchar_ffi`. Th
|
||||
|
||||
### Format strings
|
||||
|
||||
Rust's builtin `std::fmt` modules do not accept runtime-provided format strings, so we mostly won't use them, except perhaps for flog / other non-translated text.
|
||||
Rust's builtin `std::fmt` modules do not accept runtime-provided format strings, so we mostly won't use them, except perhaps for FLOG / other non-translated text.
|
||||
|
||||
Instead we'll continue to use printf-style strings, with a Rust printf implementation.
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _cmd-_:
|
||||
|
||||
_ - call fish's translations
|
||||
============================
|
||||
|
||||
@@ -23,8 +25,6 @@ If other programs launched via fish should respect these locale variables they h
|
||||
|
||||
For :envvar:`LANGUAGE` you can use a list, or use colons to separate multiple languages.
|
||||
|
||||
If the :ref:`status language set <status-language>` command was used, its arguments specify the language precedence, and the environment variables are ignored.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
|
||||
@@ -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 ...
|
||||
@@ -46,7 +48,7 @@ Combining these features, it is possible to create custom syntaxes, where a regu
|
||||
|
||||
> abbr >> ~/.config/fish/config.fish
|
||||
> abbr --erase (abbr --list)
|
||||
|
||||
|
||||
Alternatively you can keep them in a separate :ref:`configuration file <configuration>` by doing something like the following::
|
||||
|
||||
> abbr > ~/.config/fish/conf.d/myabbrs.fish
|
||||
@@ -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
|
||||
=========================
|
||||
|
||||
@@ -46,12 +48,12 @@ The following code will create ``rmi``, which runs ``rm`` with additional argume
|
||||
::
|
||||
|
||||
alias rmi="rm -i"
|
||||
|
||||
|
||||
# This is equivalent to entering the following function:
|
||||
function rmi --wraps rm --description 'alias rmi=rm -i'
|
||||
rm -i $argv
|
||||
end
|
||||
|
||||
|
||||
``alias`` sometimes requires escaping, as you can see here::
|
||||
|
||||
# This needs to have the spaces escaped or "Chrome.app..."
|
||||
|
||||
@@ -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
|
||||
=================================
|
||||
|
||||
@@ -33,10 +35,10 @@ The following code sets a number of variables inside of a block scope. Since the
|
||||
|
||||
begin
|
||||
set -l PIRATE Yarrr
|
||||
|
||||
|
||||
...
|
||||
end
|
||||
|
||||
|
||||
echo $PIRATE
|
||||
# This will not output anything, since the PIRATE variable
|
||||
# went out of scope at the end of the block
|
||||
|
||||
@@ -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
|
||||
@@ -145,17 +147,12 @@ The following special input functions are available:
|
||||
``backward-kill-line``
|
||||
move everything from the beginning of the line to the cursor to the killring
|
||||
|
||||
.. _cmd-bind-backward-kill-path-component:
|
||||
|
||||
``backward-kill-path-component``
|
||||
move one path component to the left of the cursor to the killring. A path component is everything likely to belong to a path component, i.e. not any of the following: `/={,}'\":@ |;<>&`, plus newlines and tabs.
|
||||
|
||||
``backward-kill-word``
|
||||
move the word to the left of the cursor to the killring. The "word" here is everything up to punctuation or whitespace.
|
||||
|
||||
``backward-path-component``
|
||||
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the left.
|
||||
|
||||
``backward-word``
|
||||
move one word to the left
|
||||
|
||||
@@ -246,9 +243,6 @@ The following special input functions are available:
|
||||
commandline, does not accept the current autosuggestion (if any). Does not change the selected item in the completion pager,
|
||||
if shown.
|
||||
|
||||
``forward-path-component``
|
||||
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the right; or if at the end of the commandline, accept a path component from the current autosuggestion.
|
||||
|
||||
``forward-single-char``
|
||||
move one character to the right; or if at the end of the commandline, accept a single char from the current autosuggestion.
|
||||
|
||||
@@ -316,9 +310,6 @@ The following special input functions are available:
|
||||
``kill-line``
|
||||
move everything from the cursor to the end of the line to the killring
|
||||
|
||||
``kill-path-component``
|
||||
move one :ref:`path component <cmd-bind-backward-kill-path-component>` to the killring.
|
||||
|
||||
``kill-selection``
|
||||
move the selected text to the killring
|
||||
|
||||
|
||||
@@ -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
|
||||
=====================
|
||||
|
||||
@@ -41,7 +43,7 @@ Examples
|
||||
|
||||
cd
|
||||
# changes the working directory to your home directory.
|
||||
|
||||
|
||||
cd /usr/src/fish-shell
|
||||
# changes the working directory to /usr/src/fish-shell
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user