From e3212cdc0883c8402b429d775d4883847752e0e2 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 18 Nov 2025 13:54:46 +0530 Subject: [PATCH 01/30] Use template for mktemp (#1140) --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 1e44feb..3108dd4 100755 --- a/install.sh +++ b/install.sh @@ -31,7 +31,7 @@ main() { # Create and enter a temporary directory. local _tmp_dir - _tmp_dir="$(mktemp -d)" || err "mktemp: could not create temporary directory" + _tmp_dir="$(mktemp -d /tmp/zoxide_XXXXXX)" || err "mktemp: could not create temporary directory" cd "${_tmp_dir}" || err "cd: failed to enter directory: ${_tmp_dir}" # Download and extract zoxide. From 9e82a6d12779bb1a25a23903ebcee83322f12639 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 18 Nov 2025 14:05:45 +0530 Subject: [PATCH 02/30] Add ARMv7 target for Android in release workflow (#1144) --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7398a6a..099d950 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,8 @@ jobs: deb: true - os: ubuntu-latest target: aarch64-linux-android + - os: ubuntu-latest + target: armv7-linux-androideabi - os: macos-latest target: x86_64-apple-darwin - os: macos-latest From ecf72c9cfdc0c8f04ac1e2953bb3703ea6805e05 Mon Sep 17 00:00:00 2001 From: Mark Derricutt Date: Tue, 18 Nov 2025 22:19:41 +1300 Subject: [PATCH 03/30] Update zoxide to support Fish 4.1.x (#1046) --- templates/fish.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/fish.txt b/templates/fish.txt index f6ade18..038e08e 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -19,7 +19,11 @@ end # A copy of fish's internal cd function. This makes it possible to use # `alias cd=z` without causing an infinite loop. if ! builtin functions --query __zoxide_cd_internal - string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' <$__fish_data_dir/functions/cd.fish | source + if status list-files functions/cd.fish &>/dev/null + status get-file functions/cd.fish | string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' | source + else + string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' <$__fish_data_dir/functions/cd.fish | source + end end # cd + custom logic based on the value of _ZO_ECHO. From d304543d2ef90eff3f27e7c6029dfdde789598cf Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 18 Nov 2025 20:14:28 +0530 Subject: [PATCH 04/30] Remove uses of builtin from POSIX (#1146) --- templates/posix.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/posix.txt b/templates/posix.txt index b7ba9b3..6219b58 100644 --- a/templates/posix.txt +++ b/templates/posix.txt @@ -10,7 +10,7 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. __zoxide_pwd() { {%- if cfg!(windows) %} - \command cygpath -w "$(\builtin pwd -P)" + \command cygpath -w "$(\command pwd -P)" {%- else if resolve_symlinks %} \command pwd -P {%- else %} @@ -35,7 +35,7 @@ __zoxide_cd() { {%- when InitHook::Prompt -%} # Hook to add new entries to the database. __zoxide_hook() { - \command zoxide add -- "$(__zoxide_pwd || \builtin true)" + \command zoxide add -- "$(__zoxide_pwd || \command true)" } # Initialize hook. @@ -95,7 +95,7 @@ __zoxide_z() { elif [ "$#" -eq 1 ] && [ -d "$1" ]; then __zoxide_cd "$1" else - __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd || \builtin true)" -- "$@")" && + __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd || \command true)" -- "$@")" && __zoxide_cd "${__zoxide_result}" fi } From da3905ba848ba63b4789f62663a59e7abb9b8053 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 03:14:24 +0530 Subject: [PATCH 05/30] Bump Swatinem/rust-cache from 2.8.1 to 2.8.2 (#1154) Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.8.1...v2.8.2) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87368c6..9ccdb38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: authToken: ${{ env.CACHIX_AUTH_TOKEN }} name: zoxide - name: Setup cache - uses: Swatinem/rust-cache@v2.8.1 + uses: Swatinem/rust-cache@v2.8.2 with: key: ${{ matrix.os }} - name: Install just diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 099d950..7a0c50a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: override: true target: ${{ matrix.target }} - name: Setup cache - uses: Swatinem/rust-cache@v2.8.1 + uses: Swatinem/rust-cache@v2.8.2 with: key: ${{ matrix.target }} - name: Install cross From 20dd3e1ec6d6e559ad64e7e7b6c797965ad5309a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 03:14:34 +0530 Subject: [PATCH 06/30] Bump actions/checkout from 5 to 6 (#1152) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ccdb38..3f35ac3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [ubuntu-latest] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 - uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a0c50a..4ba6c83 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,7 +44,7 @@ jobs: target: aarch64-pc-windows-msvc steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Get version From f00fe0f0aeaeaf8fda48ca467c706a5174830b77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 00:19:31 +0530 Subject: [PATCH 07/30] Bump actions/upload-artifact from 5 to 6 (#1157) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4ba6c83..27a5166 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,7 +102,7 @@ jobs: CHANGELOG.md LICENSE README.md ./man/ ./contrib/completions/ ` ./target/${{ matrix.target }}/release/zoxide.exe - name: Upload artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ matrix.target }} path: | From 324b0d35e72efd52259b77c800487de373cb66df Mon Sep 17 00:00:00 2001 From: Simon Olofsson Date: Fri, 30 Jan 2026 12:24:27 +0100 Subject: [PATCH 08/30] fish: clear existing completions before defining aliases (#1165) Fish ships with built-in completions for common commands like `j` (share/completions/j.fish for autojump). These override zoxide's completions when using `--cmd j`. Clear them before defining aliases. --- templates/fish.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/fish.txt b/templates/fish.txt index 038e08e..36ca833 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -117,9 +117,11 @@ end {%- when Some with (cmd) %} abbr --erase {{cmd}} &>/dev/null +complete --erase --command {{cmd}} alias {{cmd}}=__zoxide_z abbr --erase {{cmd}}i &>/dev/null +complete --erase --command {{cmd}}i alias {{cmd}}i=__zoxide_zi {%- when None %} From 52a716fed6be54665cb4085b1b1aab259062c131 Mon Sep 17 00:00:00 2001 From: stringscut Date: Fri, 30 Jan 2026 19:25:23 +0800 Subject: [PATCH 09/30] chore: improve code comments clarity (#1158) Signed-off-by: stringscut --- src/cmd/import.rs | 2 +- src/db/mod.rs | 2 +- src/db/stream.rs | 2 +- src/shell.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/import.rs b/src/cmd/import.rs index f13381c..ac0777a 100644 --- a/src/cmd/import.rs +++ b/src/cmd/import.rs @@ -37,7 +37,7 @@ fn import_autojump(db: &mut Database, buffer: &str) -> Result<()> { let mut rank = rank.parse::().with_context(|| format!("invalid rank: {rank}"))?; // Normalize the rank using a sigmoid function. Don't import actual ranks from // autojump, since its scoring algorithm is very different and might - // take a while to get normalized. + // take a while to normalize. rank = sigmoid(rank); db.add_unchecked(path, rank, 0); diff --git a/src/db/mod.rs b/src/db/mod.rs index d459f39..86808f2 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -76,7 +76,7 @@ impl Database { } /// Creates a new directory. This will create a duplicate entry if this - /// directory is always in the database, it is expected that the user either + /// directory is already in the database, it is expected that the user either /// does a check before calling this, or calls `dedup()` afterward. pub fn add_unchecked(&mut self, path: impl AsRef + Into, rank: Rank, now: Epoch) { self.with_dirs_mut(|dirs| { diff --git a/src/db/stream.rs b/src/db/stream.rs index 4b06193..24c84e0 100644 --- a/src/db/stream.rs +++ b/src/db/stream.rs @@ -70,7 +70,7 @@ impl<'a> Stream<'a> { } // The logic here is reversed - if we resolve symlinks when adding entries to - // the database, we should not return symlinks when querying back from + // the database, we should not return symlinks when querying from // the database. let resolver = if self.options.resolve_symlinks { fs::symlink_metadata } else { fs::metadata }; diff --git a/src/shell.rs b/src/shell.rs index 37fe1a2..8812b1c 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -100,7 +100,7 @@ mod tests { let mut source = String::new(); // Filter out lines using edit:*, since those functions are only available in - // the interactive editor. + // interactive editor mode. for line in Elvish(&opts).render().unwrap().lines().filter(|line| !line.contains("edit:")) { source.push_str(line); source.push('\n'); From 9cdc6aa3740b4d8a9d62406c99e84c5de49645e9 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Sat, 31 Jan 2026 13:12:16 +0530 Subject: [PATCH 10/30] chore(release): v0.9.9 --- CHANGELOG.md | 23 ++++++++++++++++++++--- Cargo.lock | 2 +- Cargo.toml | 2 +- src/db/mod.rs | 5 +++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 071a7c6..ffcaafd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.9.9] - 2026-01-31 + +### Added + +- Support for Android ARMv7. +- Fish: support for v4.1.0+. + +### Fixed + +- Nushell: use sigil operator when calling external commands. +- Zsh: support multiple digits in `z +N` and `z -N` dirstack commands. +- Bash: avoid downcasting `$PROMPT_COMMAND` array into a string. +- Bash: avoid overwriting `$PIPESTATUS`. +- POSIX: remove non-POSIX compliant calls to `builtin`. +- Fish: clear existing completions when defining `z` command. + ## [0.9.8] - 2025-05-27 ### Added @@ -22,7 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Bash: doctor now handles `PROMPT_COMMAND` being an array. +- Bash: doctor now handles `$PROMPT_COMMAND` being an array. - Bash: doctor now handles Visual Studio Code's shell integration. - Bash: completions now work with `ble.sh`. - Nushell: stop ignoring symlinks when `cd`-ing into a directory. @@ -35,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Nushell: support for 0.102.0. +- Nushell: support for v0.102.0. - Bash / Zsh: add doctor to diagnose common issues. ### Fixed @@ -302,7 +318,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `zoxide query --all` for listing deleted directories. - Lazy deletion for removed directories that have not been accessed in > 90 days. -- Nushell: support for 0.32.0+. +- Nushell: support for v0.32.0+. ### Fixed @@ -536,6 +552,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - GitHub Actions pipeline to build and upload releases. - Add support for Zsh. +[0.9.9]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.8...v0.9.9 [0.9.8]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.7...v0.9.8 [0.9.7]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.6...v0.9.7 [0.9.6]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.5...v0.9.6 diff --git a/Cargo.lock b/Cargo.lock index 732e696..27da609 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -983,7 +983,7 @@ dependencies = [ [[package]] name = "zoxide" -version = "0.9.8" +version = "0.9.9" dependencies = [ "anyhow", "askama", diff --git a/Cargo.toml b/Cargo.toml index 58b0d57..d137115 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ name = "zoxide" readme = "README.md" repository = "https://github.com/ajeetdsouza/zoxide" rust-version = "1.85.0" -version = "0.9.8" +version = "0.9.9" [badges] maintenance = { status = "actively-developed" } diff --git a/src/db/mod.rs b/src/db/mod.rs index 86808f2..1856fda 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -76,8 +76,9 @@ impl Database { } /// Creates a new directory. This will create a duplicate entry if this - /// directory is already in the database, it is expected that the user either - /// does a check before calling this, or calls `dedup()` afterward. + /// directory is already in the database, it is expected that the user + /// either does a check before calling this, or calls `dedup()` + /// afterward. pub fn add_unchecked(&mut self, path: impl AsRef + Into, rank: Rank, now: Epoch) { self.with_dirs_mut(|dirs| { dirs.push(Dir { path: path.into().into(), rank, last_accessed: now }) From d7458b756ee218e6f597218a8d9065b2032601f1 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Mon, 2 Feb 2026 00:37:36 -0500 Subject: [PATCH 11/30] Support symlinks on Windows (#1149) --- CHANGELOG.md | 10 ++++++++++ templates/bash.txt | 12 ++++++++---- templates/fish.txt | 12 ++++++++---- templates/posix.txt | 25 +++++++++++++++++++------ templates/zsh.txt | 12 ++++++++---- 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffcaafd..6b38fe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- POSIX: support for non-Cygwin Windows environments (e.g. Busybox). + +### Fixed + +- Bash/Fish/POSIX/Zsh: resolve symlinks on Windows. + ## [0.9.9] - 2026-01-31 ### Added diff --git a/templates/bash.txt b/templates/bash.txt index f96edb0..86a2884 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -9,12 +9,16 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd() { +{%- let pwd -%} +{%- if resolve_symlinks -%} +{%- let pwd = "\\builtin pwd -P" -%} +{%- else -%} +{%- let pwd = "\\builtin pwd -L" -%} +{%- endif -%} {%- if cfg!(windows) %} - \command cygpath -w "$(\builtin pwd -P)" -{%- else if resolve_symlinks %} - \builtin pwd -P + \command cygpath -w "{{ pwd }}" {%- else %} - \builtin pwd -L + {{ pwd }} {%- endif %} } diff --git a/templates/fish.txt b/templates/fish.txt index 36ca833..a13edc7 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -7,12 +7,16 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd +{%- let pwd -%} +{%- if resolve_symlinks -%} +{%- let pwd = "builtin pwd -P" -%} +{%- else -%} +{%- let pwd = "builtin pwd -L" -%} +{%- endif -%} {%- if cfg!(windows) %} - command cygpath -w (builtin pwd -P) -{%- else if resolve_symlinks %} - builtin pwd -P + command cygpath -w ({{ pwd }}) {%- else %} - builtin pwd -L + {{ pwd }} {%- endif %} end diff --git a/templates/posix.txt b/templates/posix.txt index 6219b58..b3f660c 100644 --- a/templates/posix.txt +++ b/templates/posix.txt @@ -8,15 +8,28 @@ # # pwd based on the value of _ZO_RESOLVE_SYMLINKS. -__zoxide_pwd() { +{%- let pwd -%} +{%- if resolve_symlinks -%} +{%- let pwd = "\\command pwd -P" -%} +{%- else -%} +{%- let pwd = "\\command pwd -L" -%} +{%- endif -%} {%- if cfg!(windows) %} - \command cygpath -w "$(\command pwd -P)" -{%- else if resolve_symlinks %} - \command pwd -P +if \command -v cygpath >/dev/null +then + __zoxide_pwd() { + \command cygpath -w "$({{ pwd }})" + } +else + __zoxide_pwd() { + {{ pwd }} + } +fi {%- else %} - \command pwd -L -{%- endif %} +__zoxide_pwd() { + {{ pwd }} } +{%- endif %} # cd + custom logic based on the value of _ZO_ECHO. __zoxide_cd() { diff --git a/templates/zsh.txt b/templates/zsh.txt index 80cd428..a66f960 100644 --- a/templates/zsh.txt +++ b/templates/zsh.txt @@ -9,12 +9,16 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd() { +{%- let pwd -%} +{%- if resolve_symlinks -%} +{%- let pwd = "\\builtin pwd -P" -%} +{%- else -%} +{%- let pwd = "\\builtin pwd -L" -%} +{%- endif -%} {%- if cfg!(windows) %} - \command cygpath -w "$(\builtin pwd -P)" -{%- else if resolve_symlinks %} - \builtin pwd -P + \command cygpath -w "{{ pwd }}" {%- else %} - \builtin pwd -L + {{ pwd }} {%- endif %} } From d208a66f585daff115424fa44a2afe254879aa34 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Sat, 7 Feb 2026 11:59:53 +0530 Subject: [PATCH 12/30] install.sh: early exit on error --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 3108dd4..ba894c3 100755 --- a/install.sh +++ b/install.sh @@ -19,7 +19,7 @@ main() { parse_args "$@" local _arch - _arch="${ARCH:-$(ensure get_architecture)}" + _arch="${ARCH:-$(get_architecture)}" || exit $? assert_nz "${_arch}" "arch" echo "Detected architecture: ${_arch}" @@ -36,7 +36,7 @@ main() { # Download and extract zoxide. local _package - _package="$(ensure download_zoxide "${_arch}")" + _package="$(download_zoxide "${_arch}")" || exit $? assert_nz "${_package}" "package" echo "Downloaded package: ${_package}" case "${_package}" in From ce469159012efac2c4e005c6023e7f730ba65047 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Sat, 7 Feb 2026 12:15:06 +0530 Subject: [PATCH 13/30] install.sh: Prefix global variables --- install.sh | 62 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/install.sh b/install.sh index ba894c3..39ff854 100755 --- a/install.sh +++ b/install.sh @@ -19,7 +19,7 @@ main() { parse_args "$@" local _arch - _arch="${ARCH:-$(get_architecture)}" || exit $? + _arch="${_ZOXIDE_ARCH:-$(get_architecture)}" || exit $? assert_nz "${_arch}" "arch" echo "Detected architecture: ${_arch}" @@ -54,44 +54,44 @@ main() { esac # Install binary. - ensure try_sudo mkdir -p -- "${BIN_DIR}" - ensure try_sudo cp -- "${_bin_name}" "${BIN_DIR}/${_bin_name}" - ensure try_sudo chmod +x "${BIN_DIR}/${_bin_name}" - echo "Installed zoxide to ${BIN_DIR}" + ensure try_sudo mkdir -p -- "${_ZOXIDE_BIN_DIR}" + ensure try_sudo cp -- "${_bin_name}" "${_ZOXIDE_BIN_DIR}/${_bin_name}" + ensure try_sudo chmod +x "${_ZOXIDE_BIN_DIR}/${_bin_name}" + echo "Installed zoxide to ${_ZOXIDE_BIN_DIR}" # Install manpages. - ensure try_sudo mkdir -p -- "${MAN_DIR}/man1" - ensure try_sudo cp -- "man/man1/"* "${MAN_DIR}/man1/" - echo "Installed manpages to ${MAN_DIR}" + ensure try_sudo mkdir -p -- "${_ZOXIDE_MAN_DIR}/man1" + ensure try_sudo cp -- "man/man1/"* "${_ZOXIDE_MAN_DIR}/man1/" + echo "Installed manpages to ${_ZOXIDE_MAN_DIR}" # Print success message and check $PATH. echo "" echo "zoxide is installed!" - if ! echo ":${PATH}:" | grep -Fq ":${BIN_DIR}:"; then - echo "Note: ${BIN_DIR} is not on your \$PATH. zoxide will not work unless it is added to \$PATH." + if ! echo ":${PATH}:" | grep -Fq ":${_ZOXIDE_BIN_DIR}:"; then + echo "Note: ${_ZOXIDE_BIN_DIR} is not on your \$PATH. zoxide will not work unless it is added to \$PATH." fi } # Parse the arguments passed and set variables accordingly. parse_args() { - BIN_DIR_DEFAULT="${HOME}/.local/bin" - MAN_DIR_DEFAULT="${HOME}/.local/share/man" - SUDO_DEFAULT="sudo" + _ZOXIDE_BIN_DIR_DEFAULT="${HOME}/.local/bin" + _ZOXIDE_MAN_DIR_DEFAULT="${HOME}/.local/share/man" + _ZOXIDE_SUDO_DEFAULT="sudo" - BIN_DIR="${BIN_DIR_DEFAULT}" - MAN_DIR="${MAN_DIR_DEFAULT}" - SUDO="${SUDO_DEFAULT}" + _ZOXIDE_BIN_DIR="${_ZOXIDE_BIN_DIR_DEFAULT}" + _ZOXIDE_MAN_DIR="${_ZOXIDE_MAN_DIR_DEFAULT}" + _ZOXIDE_SUDO="${_ZOXIDE_SUDO_DEFAULT}" while [ "$#" -gt 0 ]; do case "$1" in - --arch) ARCH="$2" && shift 2 ;; - --arch=*) ARCH="${1#*=}" && shift 1 ;; - --bin-dir) BIN_DIR="$2" && shift 2 ;; - --bin-dir=*) BIN_DIR="${1#*=}" && shift 1 ;; - --man-dir) MAN_DIR="$2" && shift 2 ;; - --man-dir=*) MAN_DIR="${1#*=}" && shift 1 ;; - --sudo) SUDO="$2" && shift 2 ;; - --sudo=*) SUDO="${1#*=}" && shift 1 ;; + --arch) _ZOXIDE_ARCH="$2" && shift 2 ;; + --arch=*) _ZOXIDE_ARCH="${1#*=}" && shift 1 ;; + --bin-dir) _ZOXIDE_BIN_DIR="$2" && shift 2 ;; + --bin-dir=*) _ZOXIDE_BIN_DIR="${1#*=}" && shift 1 ;; + --man-dir) _ZOXIDE_MAN_DIR="$2" && shift 2 ;; + --man-dir=*) _ZOXIDE_MAN_DIR="${1#*=}" && shift 1 ;; + --sudo) _ZOXIDE_SUDO="$2" && shift 2 ;; + --sudo=*) _ZOXIDE_SUDO="${1#*=}" && shift 1 ;; -h | --help) usage && exit 0 ;; *) err "Unknown option: $1" ;; esac @@ -119,9 +119,9 @@ ${_text_heading}Usage:${_text_reset} ${_text_heading}Options:${_text_reset} --arch Override the architecture identified by the installer [current: ${_arch}] - --bin-dir Override the installation directory [default: ${BIN_DIR_DEFAULT}] - --man-dir Override the manpage installation directory [default: ${MAN_DIR_DEFAULT}] - --sudo Override the command used to elevate to root privileges [default: ${SUDO_DEFAULT}] + --bin-dir Override the installation directory [default: ${_ZOXIDE_BIN_DIR_DEFAULT}] + --man-dir Override the manpage installation directory [default: ${_ZOXIDE_MAN_DIR_DEFAULT}] + --sudo Override the command used to elevate to root privileges [default: ${_ZOXIDE_SUDO_DEFAULT}] -h, --help Print help" } @@ -176,19 +176,19 @@ try_sudo() { fi need_sudo - "${SUDO}" "$@" + "${_ZOXIDE_SUDO}" "$@" } need_sudo() { - if ! check_cmd "${SUDO}"; then + if ! check_cmd "${_ZOXIDE_SUDO}"; then err "\ -could not find the command \`${SUDO}\` needed to get permissions for install. +could not find the command \`${_ZOXIDE_SUDO}\` needed to get permissions for install. If you are on Windows, please run your shell as an administrator, then rerun this script. Otherwise, please run this script as root, or install \`sudo\`." fi - if ! "${SUDO}" -v; then + if ! "${_ZOXIDE_SUDO}" -v; then err "sudo permissions not granted, aborting installation" fi } From f3a07cd3d199d464ff1a65c8df17ab382e17e5e4 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 19 Feb 2026 01:04:43 +0530 Subject: [PATCH 14/30] Update README.md --- README.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b397f82..ed45205 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,28 @@ Special thanks to: - -
Sponsored by Warp
-
Warp, built for coding with multiple AI agents.
-
Available for macOS, Linux, and Windows.
-
- Visit - warp.dev - to learn more. -
+ + + + + +
+ + Sponsored by Warp +
Warp, built for coding with multiple AI agents.
+
Available for macOS, Linux, and Windows.
+
+ Visit + warp.dev + to learn more. +
+
+ + Sponsored by Recall.ai +
Processing over 3TB/s of video at peak load,
+ + +

From f07a76e115ed47677b6ee0428226e6bde62ad4e0 Mon Sep 17 00:00:00 2001 From: Chawye Hsu Date: Sun, 1 Mar 2026 15:13:50 +0800 Subject: [PATCH 15/30] pwsh: handling `z ~` and `z` separately (#1161) * pwsh: handling `z ~` and `z` separately This patch enables the capability of navigating to the current user's home directory with `z` when cwd is on a PSDrive that does not have a definition of the `HOME` location. Context: The fact that `~` can be counterintuitive on PowerShell, as it's relative to the cwd, **and its value is defined with a `.Home` property of cwd's PSProvider\[1]. Not all PSProviders however define this property, leaving that sometimes you cannot navigate to the undefined `HOME` location with `~`. To validate this, you can use `Get-PSDrive` to iterate your PSDrives and see which providers define a `Home` property. On Windows, ```plain Get-PSDrive C,HKLM | select Name,{$_.Provider.Name},{$_.Provider.Home} Name $_.Provider.Name $_.Provider.Home ---- ---------------- ---------------- C FileSystem C:\Users\ HKLM Registry ``` or on Linux/macOS, ```plain Get-PSDrive /,Function | select Name,{$_.Provider.Name},{$_.Provider.Home} Name $_.Provider.Name $_.Provider.Home ---- ---------------- ---------------- / FileSystem /Users/ Function Function ``` When cwd is on a PSDrive without a defined `HOME` location, the original `Set-Location` alias `cd` in PowerShell handles this case by falling back to the user's home directory when no argument is provided\[2], and when `~` is explicitly provided, it results in an error. ```plain PS C:\> Set-Location Function: PS Function:\> cd ~ Home location for this provider is not set. To set the home location, call "(get-psprovider 'Function').Home = 'path'". PS Function:\> cd PS C:\Users\\> ``` This patch implements the same behavior for `z` by handling `z ~` and `z` separately. \[1]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_providers \[2]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-location?#-path Signed-off-by: Chawye Hsu * No explicit case needed for ~ --------- Signed-off-by: Chawye Hsu Co-authored-by: Ajeet D'Souza <98ajeet@gmail.com> --- templates/powershell.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/templates/powershell.txt b/templates/powershell.txt index 046061c..bc877c0 100644 --- a/templates/powershell.txt +++ b/templates/powershell.txt @@ -28,7 +28,11 @@ function global:__zoxide_pwd { # cd + custom logic based on the value of _ZO_ECHO. function global:__zoxide_cd($dir, $literal) { $dir = if ($literal) { - Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop + if ($null -eq $dir) { + Set-Location + } else { + Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop + } } else { if ($dir -eq '-' -and ($PSVersionTable.PSVersion -lt 6.1)) { Write-Error "cd - is not supported below PowerShell 6.1. Please upgrade your version of PowerShell." @@ -101,7 +105,7 @@ if ($global:__zoxide_hooked -ne 1) { # Jump to a directory using only keywords. function global:__zoxide_z { if ($args.Length -eq 0) { - __zoxide_cd ~ $true + __zoxide_cd $null $true } elseif ($args.Length -eq 1 -and ($args[0] -eq '-' -or $args[0] -eq '+')) { __zoxide_cd $args[0] $false From e10ebcc2bdc15da33548a70f7a0ee873ae78d240 Mon Sep 17 00:00:00 2001 From: "Helmut K. C. Tessarek" Date: Sun, 1 Mar 2026 02:32:36 -0500 Subject: [PATCH 16/30] ci: add workflow to publish to crates.io (#1169) Thanks! --- .github/workflows/cd.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/cd.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..0c979a7 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,16 @@ +name: Continuous Deployment +on: + push: + tags: + - "v*.*.*" +jobs: + publish-crates-io: + name: Publish on crates.io + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v5 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Publish + run: cargo publish --token ${{ secrets.CARGO_TOKEN }} From a461c9585f92759b86ed51e67488840ee14cd93b Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Sun, 1 Mar 2026 13:57:43 +0530 Subject: [PATCH 17/30] Update README --- README.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ed45205..29330cb 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,6 @@ to learn more. - - - Sponsored by Recall.ai -
Processing over 3TB/s of video at peak load,
- - - @@ -235,7 +228,7 @@ zoxide can be installed in 4 easy steps: > eval (zoxide init elvish | slurp) > ``` > - > **Note** + > **Note:** > zoxide only supports elvish v0.18.0 and above. @@ -269,7 +262,7 @@ zoxide can be installed in 4 easy steps: > source ~/.zoxide.nu > ``` > - > **Note** + > **Note:** > zoxide only supports Nushell v0.89.0+. @@ -335,12 +328,16 @@ zoxide can be installed in 4 easy steps: + > **Note:** + > [Warp Terminal] users need to set `Input Type` to `Shell (PS1)` under + > `Settings > Appearance > Input` for completions to work. + 3. **Install fzf** (optional) [fzf] is a command-line fuzzy finder, used by zoxide for completions / interactive selection. It can be installed from [here][fzf-installation]. - > **Note** + > **Note:** > The minimum supported fzf version is v0.51.0. 4. **Import your data** (optional) @@ -567,6 +564,7 @@ Environment variables[^2] can be used for configuration. They must be set before [ubuntu packages]: https://packages.ubuntu.com/jammy/zoxide [vim]: https://github.com/vim/vim [void linux packages]: https://github.com/void-linux/void-packages/tree/master/srcpkgs/zoxide +[warp terminal]: https://www.warp.dev [wiki-env]: https://github.com/ajeetdsouza/zoxide/wiki/HOWTO:-set-environment-variables "HOWTO: set environment variables" [xplr]: https://github.com/sayanarijit/xplr [xxh-plugin-prerun-zoxide]: https://github.com/xxh/xxh-plugin-prerun-zoxide From fb1495b0ad75b69aba98bf3e39d3cce06059ef3a Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Sun, 1 Mar 2026 15:32:40 +0530 Subject: [PATCH 18/30] Handle prompts ending in space (#1189) --- templates/bash.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/bash.txt b/templates/bash.txt index 86a2884..068ebea 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -63,7 +63,7 @@ if [[ ${PROMPT_COMMAND:=} != *'__zoxide_hook'* ]]; then PROMPT_COMMAND=("${PROMPT_COMMAND[@]}" __zoxide_hook) else # shellcheck disable=SC2128,SC2178 - PROMPT_COMMAND="${PROMPT_COMMAND%"${PROMPT_COMMAND##*[![:space:]]}"}" + PROMPT_COMMAND="${PROMPT_COMMAND%"${PROMPT_COMMAND##*[![:space:];]}"}" # shellcheck disable=SC2128,SC2178 PROMPT_COMMAND="${PROMPT_COMMAND:+${PROMPT_COMMAND};}__zoxide_hook" fi From 7e4cbb83806cebd5ad60daede8d4da2192044cb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 03:32:43 +0530 Subject: [PATCH 19/30] Bump actions/checkout from 5 to 6 (#1191) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 0c979a7..debc0cf 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Publish From a970320caf1d5ff4d8e59337466bbb98a53bdbc0 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 5 Mar 2026 08:02:31 +0530 Subject: [PATCH 20/30] Update README --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 29330cb..7ee1ef1 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ z - # cd into previous directory zi foo # cd with interactive selection (using fzf) -z foo # show interactive completions (zoxide v0.8.0+, bash 4.4+/fish/zsh only) +z foo # show interactive completions (bash 4.4+/fish/zsh only) ``` Read more about the matching algorithm [here][algorithm-matching]. @@ -329,8 +329,7 @@ zoxide can be installed in 4 easy steps: > **Note:** - > [Warp Terminal] users need to set `Input Type` to `Shell (PS1)` under - > `Settings > Appearance > Input` for completions to work. + > [Warp] provides its own completions, so `Space+Tab` completions are not supported there. 3. **Install fzf** (optional) @@ -564,7 +563,7 @@ Environment variables[^2] can be used for configuration. They must be set before [ubuntu packages]: https://packages.ubuntu.com/jammy/zoxide [vim]: https://github.com/vim/vim [void linux packages]: https://github.com/void-linux/void-packages/tree/master/srcpkgs/zoxide -[warp terminal]: https://www.warp.dev +[warp]: https://www.warp.dev [wiki-env]: https://github.com/ajeetdsouza/zoxide/wiki/HOWTO:-set-environment-variables "HOWTO: set environment variables" [xplr]: https://github.com/sayanarijit/xplr [xxh-plugin-prerun-zoxide]: https://github.com/xxh/xxh-plugin-prerun-zoxide From 61f19a60d91b7181bfdc88470e72bcd1befc7c6a Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 5 Mar 2026 11:11:54 +0530 Subject: [PATCH 21/30] Update README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ee1ef1..05981d5 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,13 @@ to learn more. + + + Sponsored by Recall.ai +
Processing over 3TB/s of video at peak load,
+ + + @@ -329,7 +336,8 @@ zoxide can be installed in 4 easy steps: > **Note:** - > [Warp] provides its own completions, so `Space+Tab` completions are not supported there. + > [Warp] provides its own completions, so `Space+Tab` completions are not + > supported there. 3. **Install fzf** (optional) From 108c41ac822c7dcfe7d8e3129913e64e0827c625 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 01:49:29 +0530 Subject: [PATCH 22/30] Bump Swatinem/rust-cache from 2.8.2 to 2.9.1 (#1196) Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.8.2 to 2.9.1. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.8.2...v2.9.1) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-version: 2.9.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f35ac3..f73058f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: authToken: ${{ env.CACHIX_AUTH_TOKEN }} name: zoxide - name: Setup cache - uses: Swatinem/rust-cache@v2.8.2 + uses: Swatinem/rust-cache@v2.9.1 with: key: ${{ matrix.os }} - name: Install just diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 27a5166..37b3180 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: override: true target: ${{ matrix.target }} - name: Setup cache - uses: Swatinem/rust-cache@v2.8.2 + uses: Swatinem/rust-cache@v2.9.1 with: key: ${{ matrix.target }} - name: Install cross From f74ed040fed9ab50593f0ff9e29983bca54e4fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 22 Mar 2026 03:45:35 +0530 Subject: [PATCH 23/30] Bump actions/upload-artifact from 6 to 7 (#1190) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 37b3180..6680da6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,7 +102,7 @@ jobs: CHANGELOG.md LICENSE README.md ./man/ ./contrib/completions/ ` ./target/${{ matrix.target }}/release/zoxide.exe - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: | From 4f04fd4167e02de7a98139ed22eec297c75b3c22 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Mon, 23 Mar 2026 16:34:59 +0100 Subject: [PATCH 24/30] ci: add riscv64 to release build matrix (#1201) --------- Signed-off-by: Bruno Verachten Co-authored-by: Ajeet D'Souza <98ajeet@gmail.com> --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6680da6..625ca1b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,6 +30,9 @@ jobs: - os: ubuntu-latest target: i686-unknown-linux-musl deb: true + - os: ubuntu-latest + target: riscv64gc-unknown-linux-musl + deb: true - os: ubuntu-latest target: aarch64-linux-android - os: ubuntu-latest From 67ca1bc9592854dd4957b8b02f16292638475659 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 03:50:23 +0530 Subject: [PATCH 25/30] Bump cachix/cachix-action from 16 to 17 (#1202) Bumps [cachix/cachix-action](https://github.com/cachix/cachix-action) from 16 to 17. - [Release notes](https://github.com/cachix/cachix-action/releases) - [Commits](https://github.com/cachix/cachix-action/compare/v16...v17) --- updated-dependencies: - dependency-name: cachix/cachix-action dependency-version: '17' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f73058f..dbe85d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: if: ${{ matrix.os != 'windows-latest' }} with: nix_path: nixpkgs=channel:nixos-unstable - - uses: cachix/cachix-action@v16 + - uses: cachix/cachix-action@v17 if: ${{ matrix.os != 'windows-latest' && env.CACHIX_AUTH_TOKEN != '' }} with: authToken: ${{ env.CACHIX_AUTH_TOKEN }} From 0cc031e98ef8dd4274ea53c10d9ad9d85c4d8c57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 04:00:24 +0530 Subject: [PATCH 26/30] Bump softprops/action-gh-release from 2 to 3 (#1220) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 625ca1b..6988915 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -115,7 +115,7 @@ jobs: - name: Create release if: | github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'chore(release)') - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: draft: true files: | From 1683e7b8edf187dedd38b8eb5f99c6423f47b728 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Mon, 11 May 2026 00:24:43 +0530 Subject: [PATCH 27/30] import: auto-detect databases; add Atuin support (#1232) --- CHANGELOG.md | 5 + Cargo.lock | 674 ++++++++++++++++++++------------ Cargo.toml | 9 +- README.md | 66 +--- contrib/completions/_zoxide | 149 +++++-- contrib/completions/_zoxide.ps1 | 55 ++- contrib/completions/zoxide.bash | 156 ++++++-- contrib/completions/zoxide.elv | 49 ++- contrib/completions/zoxide.fish | 32 +- contrib/completions/zoxide.nu | 62 ++- contrib/completions/zoxide.ts | 124 +++++- shell.nix | 2 +- src/cmd/cmd.rs | 23 +- src/cmd/import.rs | 157 +------- src/import.rs | 75 ++++ src/import/atuin.rs | 116 ++++++ src/import/autojump.rs | 124 ++++++ src/import/fasd.rs | 39 ++ src/import/z.rs | 103 +++++ src/import/z_lua.rs | 108 +++++ src/import/zsh_z.rs | 41 ++ src/main.rs | 1 + templates/bash.txt | 2 +- templates/fish.txt | 2 +- templates/posix.txt | 2 +- templates/tcsh.txt | 2 +- templates/zsh.txt | 2 +- 27 files changed, 1629 insertions(+), 551 deletions(-) create mode 100644 src/import.rs create mode 100644 src/import/atuin.rs create mode 100644 src/import/autojump.rs create mode 100644 src/import/fasd.rs create mode 100644 src/import/z.rs create mode 100644 src/import/z_lua.rs create mode 100644 src/import/zsh_z.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b38fe2..34e0ce9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - POSIX: support for non-Cygwin Windows environments (e.g. Busybox). +- `import` now supports fetching entries from `atuin`. + +### Changed + +- `import` now auto-detects database files. ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 27da609..d821298 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -19,9 +19,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "anstream" -version = "0.6.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -34,33 +34,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", @@ -69,17 +69,17 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "askama" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" dependencies = [ - "askama_derive", + "askama_macros", "itoa", "percent-encoding", "serde", @@ -88,9 +88,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" dependencies = [ "askama_parser", "memchr", @@ -101,24 +101,33 @@ dependencies = [ ] [[package]] -name = "askama_parser" -version = "0.14.0" +name = "askama_macros" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" dependencies = [ - "memchr", + "askama_derive", +] + +[[package]] +name = "askama_parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +dependencies = [ + "rustc-hash", + "unicode-ident", "winnow", ] [[package]] name = "assert_cmd" -version = "2.0.17" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +checksum = "39bae1d3fa576f7c6519514180a72559268dd7d1fe104070956cb687bc6673bd" dependencies = [ "anstyle", "bstr", - "doc-comment", "libc", "predicates", "predicates-core", @@ -137,15 +146,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", @@ -154,9 +163,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -166,9 +175,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.38" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -176,9 +185,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.38" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -188,9 +197,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.50" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91d3baa3bcd889d60e6ef28874126a0b384fd225ab83aa6d8a801c519194ce1" +checksum = "e3e962dae2b1e5007fe9e3db363ddc43a8bf25546d279f7a8a4401204690e80c" dependencies = [ "clap", ] @@ -207,9 +216,9 @@ dependencies = [ [[package]] name = "clap_complete_nushell" -version = "4.5.5" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a8b1593457dfc2fe539002b795710d022dc62a65bf15023f039f9760c7b18a" +checksum = "fbb9e9715d29a754b468591be588f6b926f5b0a1eb6a8b62acabeb66ff84d897" dependencies = [ "clap", "clap_complete", @@ -217,9 +226,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -229,9 +238,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "color-print" @@ -256,9 +265,18 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] [[package]] name = "difflib" @@ -287,12 +305,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "dunce" version = "1.0.5" @@ -300,22 +312,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "either" -version = "1.15.0" +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", @@ -323,38 +329,60 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", + "wasip3", ] [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -369,44 +397,73 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "is_terminal_polyfill" -version = "1.70.1" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "minimal-lexical" @@ -416,9 +473,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ "bitflags", "cfg-if", @@ -437,16 +494,22 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.21.3" +name = "num-conv" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "option-ext" @@ -480,9 +543,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -495,9 +564,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "difflib", @@ -506,25 +575,35 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", ] [[package]] -name = "proc-macro2" -version = "1.0.95" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -544,24 +623,24 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha", @@ -584,25 +663,25 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -612,9 +691,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -623,9 +702,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "relative-path" @@ -672,9 +751,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -687,9 +766,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -698,32 +777,36 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "semver" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[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.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -732,14 +815,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -756,9 +840,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -767,12 +851,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys", @@ -786,18 +870,18 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -805,10 +889,46 @@ dependencies = [ ] [[package]] -name = "unicode-ident" -version = "1.0.18" +name = "time" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" @@ -833,126 +953,187 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", ] [[package]] name = "which" -version = "7.0.3" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459" dependencies = [ - "either", - "env_home", - "rustix", - "winsafe", + "libc", ] +[[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.59.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-targets", + "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "winnow" -version = "0.7.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] [[package]] -name = "winsafe" -version = "0.0.19" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] [[package]] @@ -963,24 +1144,30 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zoxide" version = "0.9.9" @@ -1004,5 +1191,6 @@ dependencies = [ "rstest_reuse", "serde", "tempfile", + "time", "which", ] diff --git a/Cargo.toml b/Cargo.toml index d137115..25227ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" name = "zoxide" readme = "README.md" repository = "https://github.com/ajeetdsouza/zoxide" -rust-version = "1.85.0" +rust-version = "1.88.0" version = "0.9.9" [badges] @@ -17,7 +17,7 @@ maintenance = { status = "actively-developed" } [dependencies] anyhow = "1.0.32" -askama = { version = "0.14.0", default-features = false, features = [ +askama = { version = "0.16.0", default-features = false, features = [ "derive", "std", ] } @@ -30,15 +30,16 @@ fastrand = "2.0.0" glob = "0.3.0" ouroboros = "0.18.3" serde = { version = "1.0.116", features = ["derive"] } +time = { version = "0.3.47", default-features = false, features = ["parsing", "macros", "std"] } [target.'cfg(unix)'.dependencies] -nix = { version = "0.30.1", default-features = false, features = [ +nix = { version = "0.31.2", default-features = false, features = [ "fs", "user", ] } [target.'cfg(windows)'.dependencies] -which = "7.0.3" +which = "8.0.2" [build-dependencies] clap = { version = "4.3.0", features = ["derive"] } diff --git a/README.md b/README.md index 05981d5..878fba0 100644 --- a/README.md +++ b/README.md @@ -350,61 +350,21 @@ zoxide can be installed in 4 easy steps: 4. **Import your data** (optional) If you currently use any of these plugins, you may want to import your data - into zoxide: + into zoxide. The data file is auto-detected using each plugin's standard + conventions. -
- autojump + ```sh + zoxide import + ``` - > Run this command in your terminal: - > - > ```sh - > zoxide import --from=autojump "/path/to/autojump/db" - > ``` - > - > The path usually varies according to your system: - > - > | OS | Path | Example | - > | ------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------ | - > | Linux | `$XDG_DATA_HOME/autojump/autojump.txt` or `$HOME/.local/share/autojump/autojump.txt` | `/home/alice/.local/share/autojump/autojump.txt` | - > | macOS | `$HOME/Library/autojump/autojump.txt` | `/Users/Alice/Library/autojump/autojump.txt` | - > | Windows | `%APPDATA%\autojump\autojump.txt` | `C:\Users\Alice\AppData\Roaming\autojump\autojump.txt` | - -
- -
- fasd, z, z.lua, zsh-z - - > Run this command in your terminal: - > - > ```sh - > zoxide import --from=z "path/to/z/db" - > ``` - > - > The path usually varies according to your system: - > - > | Plugin | Path | - > | ---------------- | ----------------------------------------------------------------------------------- | - > | fasd | `$_FASD_DATA` or `$HOME/.fasd` | - > | z (bash/zsh) | `$_Z_DATA` or `$HOME/.z` | - > | z (fish) | `$Z_DATA` or `$XDG_DATA_HOME/z/data` or `$HOME/.local/share/z/data` | - > | z.lua (bash/zsh) | `$_ZL_DATA` or `$HOME/.zlua` | - > | z.lua (fish) | `$XDG_DATA_HOME/zlua/zlua.txt` or `$HOME/.local/share/zlua/zlua.txt` or `$_ZL_DATA` | - > | zsh-z | `$ZSHZ_DATA` or `$_Z_DATA` or `$HOME/.z` | - -
- -
- ZLocation - - > Run this command in PowerShell: - > - > ```powershell - > $db = New-TemporaryFile - > (Get-ZLocation).GetEnumerator() | ForEach-Object { Write-Output ($_.Name+'|'+$_.Value+'|0') } | Out-File $db - > zoxide import --from=z $db - > ``` - -
+ | Plugin | Command | + | ---------- | ------------------------- | + | atuin | `zoxide import atuin` | + | autojump | `zoxide import autojump` | + | fasd | `zoxide import fasd` | + | z | `zoxide import z` | + | z.lua | `zoxide import z.lua` | + | zsh-z | `zoxide import zsh-z` | ## Configuration diff --git a/contrib/completions/_zoxide b/contrib/completions/_zoxide index 97e654f..2f4c9f0 100644 --- a/contrib/completions/_zoxide +++ b/contrib/completions/_zoxide @@ -45,7 +45,7 @@ _arguments "${_arguments_options[@]}" : \ '--help[Print help]' \ '-V[Print version]' \ '--version[Print version]' \ -":: :_zoxide__edit_commands" \ +":: :_zoxide__subcmd__edit_commands" \ "*::: :->edit" \ && ret=0 @@ -96,14 +96,78 @@ esac ;; (import) _arguments "${_arguments_options[@]}" : \ -'--from=[Application to import from]:FROM:(autojump z)' \ '--merge[Merge into existing database]' \ '-h[Print help]' \ '--help[Print help]' \ '-V[Print version]' \ '--version[Print version]' \ -':path:_files' \ +":: :_zoxide__subcmd__import_commands" \ +"*::: :->import" \ && ret=0 + + case $state in + (import) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:zoxide-import-command-$line[1]:" + case $line[1] in + (atuin) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; +(autojump) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; +(fasd) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; +(z) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; +(z.lua) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; +(zsh-z) +_arguments "${_arguments_options[@]}" : \ +'--merge[Merge into existing database]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +&& ret=0 +;; + esac + ;; +esac ;; (init) _arguments "${_arguments_options[@]}" : \ @@ -162,13 +226,13 @@ _zoxide_commands() { ) _describe -t commands 'zoxide commands' commands "$@" } -(( $+functions[_zoxide__add_commands] )) || -_zoxide__add_commands() { +(( $+functions[_zoxide__subcmd__add_commands] )) || +_zoxide__subcmd__add_commands() { local commands; commands=() _describe -t commands 'zoxide add commands' commands "$@" } -(( $+functions[_zoxide__edit_commands] )) || -_zoxide__edit_commands() { +(( $+functions[_zoxide__subcmd__edit_commands] )) || +_zoxide__subcmd__edit_commands() { local commands; commands=( 'decrement:' \ 'delete:' \ @@ -177,43 +241,80 @@ _zoxide__edit_commands() { ) _describe -t commands 'zoxide edit commands' commands "$@" } -(( $+functions[_zoxide__edit__decrement_commands] )) || -_zoxide__edit__decrement_commands() { +(( $+functions[_zoxide__subcmd__edit__subcmd__decrement_commands] )) || +_zoxide__subcmd__edit__subcmd__decrement_commands() { local commands; commands=() _describe -t commands 'zoxide edit decrement commands' commands "$@" } -(( $+functions[_zoxide__edit__delete_commands] )) || -_zoxide__edit__delete_commands() { +(( $+functions[_zoxide__subcmd__edit__subcmd__delete_commands] )) || +_zoxide__subcmd__edit__subcmd__delete_commands() { local commands; commands=() _describe -t commands 'zoxide edit delete commands' commands "$@" } -(( $+functions[_zoxide__edit__increment_commands] )) || -_zoxide__edit__increment_commands() { +(( $+functions[_zoxide__subcmd__edit__subcmd__increment_commands] )) || +_zoxide__subcmd__edit__subcmd__increment_commands() { local commands; commands=() _describe -t commands 'zoxide edit increment commands' commands "$@" } -(( $+functions[_zoxide__edit__reload_commands] )) || -_zoxide__edit__reload_commands() { +(( $+functions[_zoxide__subcmd__edit__subcmd__reload_commands] )) || +_zoxide__subcmd__edit__subcmd__reload_commands() { local commands; commands=() _describe -t commands 'zoxide edit reload commands' commands "$@" } -(( $+functions[_zoxide__import_commands] )) || -_zoxide__import_commands() { - local commands; commands=() +(( $+functions[_zoxide__subcmd__import_commands] )) || +_zoxide__subcmd__import_commands() { + local commands; commands=( +'atuin:Import from atuin' \ +'autojump:Import from autojump' \ +'fasd:Import from fasd' \ +'z:Import from z' \ +'z.lua:Import from z.lua' \ +'zsh-z:Import from zsh-z' \ + ) _describe -t commands 'zoxide import commands' commands "$@" } -(( $+functions[_zoxide__init_commands] )) || -_zoxide__init_commands() { +(( $+functions[_zoxide__subcmd__import__subcmd__atuin_commands] )) || +_zoxide__subcmd__import__subcmd__atuin_commands() { + local commands; commands=() + _describe -t commands 'zoxide import atuin commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__import__subcmd__autojump_commands] )) || +_zoxide__subcmd__import__subcmd__autojump_commands() { + local commands; commands=() + _describe -t commands 'zoxide import autojump commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__import__subcmd__fasd_commands] )) || +_zoxide__subcmd__import__subcmd__fasd_commands() { + local commands; commands=() + _describe -t commands 'zoxide import fasd commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__import__subcmd__z_commands] )) || +_zoxide__subcmd__import__subcmd__z_commands() { + local commands; commands=() + _describe -t commands 'zoxide import z commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__import__subcmd__z.lua_commands] )) || +_zoxide__subcmd__import__subcmd__z.lua_commands() { + local commands; commands=() + _describe -t commands 'zoxide import z.lua commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__import__subcmd__zsh-z_commands] )) || +_zoxide__subcmd__import__subcmd__zsh-z_commands() { + local commands; commands=() + _describe -t commands 'zoxide import zsh-z commands' commands "$@" +} +(( $+functions[_zoxide__subcmd__init_commands] )) || +_zoxide__subcmd__init_commands() { local commands; commands=() _describe -t commands 'zoxide init commands' commands "$@" } -(( $+functions[_zoxide__query_commands] )) || -_zoxide__query_commands() { +(( $+functions[_zoxide__subcmd__query_commands] )) || +_zoxide__subcmd__query_commands() { local commands; commands=() _describe -t commands 'zoxide query commands' commands "$@" } -(( $+functions[_zoxide__remove_commands] )) || -_zoxide__remove_commands() { +(( $+functions[_zoxide__subcmd__remove_commands] )) || +_zoxide__subcmd__remove_commands() { local commands; commands=() _describe -t commands 'zoxide remove commands' commands "$@" } diff --git a/contrib/completions/_zoxide.ps1 b/contrib/completions/_zoxide.ps1 index bb47d3a..a76c12c 100644 --- a/contrib/completions/_zoxide.ps1 +++ b/contrib/completions/_zoxide.ps1 @@ -82,7 +82,60 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { break } 'zoxide;import' { - [CompletionResult]::new('--from', '--from', [CompletionResultType]::ParameterName, 'Application to import from') + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('atuin', 'atuin', [CompletionResultType]::ParameterValue, 'Import from atuin') + [CompletionResult]::new('autojump', 'autojump', [CompletionResultType]::ParameterValue, 'Import from autojump') + [CompletionResult]::new('fasd', 'fasd', [CompletionResultType]::ParameterValue, 'Import from fasd') + [CompletionResult]::new('z', 'z', [CompletionResultType]::ParameterValue, 'Import from z') + [CompletionResult]::new('z.lua', 'z.lua', [CompletionResultType]::ParameterValue, 'Import from z.lua') + [CompletionResult]::new('zsh-z', 'zsh-z', [CompletionResultType]::ParameterValue, 'Import from zsh-z') + break + } + 'zoxide;import;atuin' { + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + 'zoxide;import;autojump' { + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + 'zoxide;import;fasd' { + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + 'zoxide;import;z' { + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + 'zoxide;import;z.lua' { + [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + 'zoxide;import;zsh-z' { [CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') diff --git a/contrib/completions/zoxide.bash b/contrib/completions/zoxide.bash index 82b174e..1e6fdcf 100644 --- a/contrib/completions/zoxide.bash +++ b/contrib/completions/zoxide.bash @@ -17,34 +17,52 @@ _zoxide() { cmd="zoxide" ;; zoxide,add) - cmd="zoxide__add" + cmd="zoxide__subcmd__add" ;; zoxide,edit) - cmd="zoxide__edit" + cmd="zoxide__subcmd__edit" ;; zoxide,import) - cmd="zoxide__import" + cmd="zoxide__subcmd__import" ;; zoxide,init) - cmd="zoxide__init" + cmd="zoxide__subcmd__init" ;; zoxide,query) - cmd="zoxide__query" + cmd="zoxide__subcmd__query" ;; zoxide,remove) - cmd="zoxide__remove" + cmd="zoxide__subcmd__remove" ;; - zoxide__edit,decrement) - cmd="zoxide__edit__decrement" + zoxide__subcmd__edit,decrement) + cmd="zoxide__subcmd__edit__subcmd__decrement" ;; - zoxide__edit,delete) - cmd="zoxide__edit__delete" + zoxide__subcmd__edit,delete) + cmd="zoxide__subcmd__edit__subcmd__delete" ;; - zoxide__edit,increment) - cmd="zoxide__edit__increment" + zoxide__subcmd__edit,increment) + cmd="zoxide__subcmd__edit__subcmd__increment" ;; - zoxide__edit,reload) - cmd="zoxide__edit__reload" + zoxide__subcmd__edit,reload) + cmd="zoxide__subcmd__edit__subcmd__reload" + ;; + zoxide__subcmd__import,atuin) + cmd="zoxide__subcmd__import__subcmd__atuin" + ;; + zoxide__subcmd__import,autojump) + cmd="zoxide__subcmd__import__subcmd__autojump" + ;; + zoxide__subcmd__import,fasd) + cmd="zoxide__subcmd__import__subcmd__fasd" + ;; + zoxide__subcmd__import,z) + cmd="zoxide__subcmd__import__subcmd__z" + ;; + zoxide__subcmd__import,z.lua) + cmd="zoxide__subcmd__import__subcmd__z.lua" + ;; + zoxide__subcmd__import,zsh-z) + cmd="zoxide__subcmd__import__subcmd__zsh__subcmd__z" ;; *) ;; @@ -66,7 +84,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__add) + zoxide__subcmd__add) opts="-s -h -V --score --help --version ..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -88,7 +106,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__edit) + zoxide__subcmd__edit) opts="-h -V --help --version decrement delete increment reload" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -102,7 +120,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__edit__decrement) + zoxide__subcmd__edit__subcmd__decrement) opts="-h -V --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -116,7 +134,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__edit__delete) + zoxide__subcmd__edit__subcmd__delete) opts="-h -V --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -130,7 +148,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__edit__increment) + zoxide__subcmd__edit__subcmd__increment) opts="-h -V --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -144,7 +162,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__edit__reload) + zoxide__subcmd__edit__subcmd__reload) opts="-h -V --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -158,17 +176,13 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__import) - opts="-h -V --from --merge --help --version " + zoxide__subcmd__import) + opts="-h -V --merge --help --version atuin autojump fasd z z.lua zsh-z" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in - --from) - COMPREPLY=($(compgen -W "autojump z" -- "${cur}")) - return 0 - ;; *) COMPREPLY=() ;; @@ -176,7 +190,91 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__init) + zoxide__subcmd__import__subcmd__atuin) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__import__subcmd__autojump) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__import__subcmd__fasd) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__import__subcmd__z) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__import__subcmd__z.lua) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__import__subcmd__zsh__subcmd__z) + opts="-h -V --merge --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__subcmd__init) opts="-h -V --no-cmd --cmd --hook --help --version bash elvish fish nushell posix powershell tcsh xonsh zsh" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -198,7 +296,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__query) + zoxide__subcmd__query) opts="-a -i -l -s -h -V --all --interactive --list --score --exclude --base-dir --help --version [KEYWORDS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) @@ -226,7 +324,7 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; - zoxide__remove) + zoxide__subcmd__remove) opts="-h -V --help --version [PATHS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) diff --git a/contrib/completions/zoxide.elv b/contrib/completions/zoxide.elv index 93c57af..5ba33fa 100644 --- a/contrib/completions/zoxide.elv +++ b/contrib/completions/zoxide.elv @@ -72,7 +72,54 @@ set edit:completion:arg-completer[zoxide] = {|@words| cand --version 'Print version' } &'zoxide;import'= { - cand --from 'Application to import from' + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + cand atuin 'Import from atuin' + cand autojump 'Import from autojump' + cand fasd 'Import from fasd' + cand z 'Import from z' + cand z.lua 'Import from z.lua' + cand zsh-z 'Import from zsh-z' + } + &'zoxide;import;atuin'= { + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + &'zoxide;import;autojump'= { + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + &'zoxide;import;fasd'= { + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + &'zoxide;import;z'= { + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + &'zoxide;import;z.lua'= { + cand --merge 'Merge into existing database' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + &'zoxide;import;zsh-z'= { cand --merge 'Merge into existing database' cand -h 'Print help' cand --help 'Print help' diff --git a/contrib/completions/zoxide.fish b/contrib/completions/zoxide.fish index 3a0bfe7..6d7e5b2 100644 --- a/contrib/completions/zoxide.fish +++ b/contrib/completions/zoxide.fish @@ -49,11 +49,33 @@ complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subc complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from increment" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from reload" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from reload" -s V -l version -d 'Print version' -complete -c zoxide -n "__fish_zoxide_using_subcommand import" -l from -d 'Application to import from' -r -f -a "autojump\t'' -z\t''" -complete -c zoxide -n "__fish_zoxide_using_subcommand import" -l merge -d 'Merge into existing database' -complete -c zoxide -n "__fish_zoxide_using_subcommand import" -s h -l help -d 'Print help' -complete -c zoxide -n "__fish_zoxide_using_subcommand import" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "atuin" -d 'Import from atuin' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "autojump" -d 'Import from autojump' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "fasd" -d 'Import from fasd' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "z" -d 'Import from z' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "z.lua" -d 'Import from z.lua' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and not __fish_seen_subcommand_from atuin autojump fasd z z.lua zsh-z" -f -a "zsh-z" -d 'Import from zsh-z' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from atuin" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from atuin" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from atuin" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from autojump" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from autojump" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from autojump" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from fasd" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from fasd" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from fasd" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z.lua" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z.lua" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from z.lua" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from zsh-z" -l merge -d 'Merge into existing database' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from zsh-z" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand import; and __fish_seen_subcommand_from zsh-z" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_zoxide_using_subcommand init" -l cmd -d 'Changes the prefix of the `z` and `zi` commands' -r complete -c zoxide -n "__fish_zoxide_using_subcommand init" -l hook -d 'Changes how often zoxide increments a directory\'s score' -r -f -a "none\t'' prompt\t'' diff --git a/contrib/completions/zoxide.nu b/contrib/completions/zoxide.nu index 642908e..4d07049 100644 --- a/contrib/completions/zoxide.nu +++ b/contrib/completions/zoxide.nu @@ -8,10 +8,10 @@ module completions { # Add a new directory or increment its rank export extern "zoxide add" [ - ...paths: path --score(-s): string # The rank to increment the entry if it exists or initialize it with if it doesn't --help(-h) # Print help --version(-V) # Print version + ...paths: path ] # Edit the database @@ -21,21 +21,21 @@ module completions { ] export extern "zoxide edit decrement" [ - path: string --help(-h) # Print help --version(-V) # Print version + path: string ] export extern "zoxide edit delete" [ - path: string --help(-h) # Print help --version(-V) # Print version + path: string ] export extern "zoxide edit increment" [ - path: string --help(-h) # Print help --version(-V) # Print version + path: string ] export extern "zoxide edit reload" [ @@ -43,14 +43,50 @@ module completions { --version(-V) # Print version ] - def "nu-complete zoxide import from" [] { - [ "autojump" "z" ] - } - # Import entries from another application export extern "zoxide import" [ - path: path - --from: string@"nu-complete zoxide import from" # Application to import from + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from atuin + export extern "zoxide import atuin" [ + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from autojump + export extern "zoxide import autojump" [ + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from fasd + export extern "zoxide import fasd" [ + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from z + export extern "zoxide import z" [ + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from z.lua + export extern "zoxide import z.lua" [ + --merge # Merge into existing database + --help(-h) # Print help + --version(-V) # Print version + ] + + # Import from zsh-z + export extern "zoxide import zsh-z" [ --merge # Merge into existing database --help(-h) # Print help --version(-V) # Print version @@ -66,17 +102,16 @@ module completions { # Generate shell configuration export extern "zoxide init" [ - shell: string@"nu-complete zoxide init shell" --no-cmd # Prevents zoxide from defining the `z` and `zi` commands --cmd: string # Changes the prefix of the `z` and `zi` commands --hook: string@"nu-complete zoxide init hook" # Changes how often zoxide increments a directory's score --help(-h) # Print help --version(-V) # Print version + shell: string@"nu-complete zoxide init shell" ] # Search for a directory in the database export extern "zoxide query" [ - ...keywords: string --all(-a) # Show unavailable directories --interactive(-i) # Use interactive selection --list(-l) # List all matching directories @@ -85,13 +120,14 @@ module completions { --base-dir: path # Only search within this directory --help(-h) # Print help --version(-V) # Print version + ...keywords: string ] # Remove a directory from the database export extern "zoxide remove" [ - ...paths: path --help(-h) # Print help --version(-V) # Print version + ...paths: path ] } diff --git a/contrib/completions/zoxide.ts b/contrib/completions/zoxide.ts index 1e0d404..207da2f 100644 --- a/contrib/completions/zoxide.ts +++ b/contrib/completions/zoxide.ts @@ -114,19 +114,117 @@ const completion: Fig.Spec = { { name: "import", description: "Import entries from another application", - options: [ + subcommands: [ { - name: "--from", - description: "Application to import from", - isRepeatable: true, - args: { - name: "from", - suggestions: [ - "autojump", - "z", - ], - }, + name: "atuin", + description: "Import from atuin", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], }, + { + name: "autojump", + description: "Import from autojump", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + }, + { + name: "fasd", + description: "Import from fasd", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + }, + { + name: "z", + description: "Import from z", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + }, + { + name: "z.lua", + description: "Import from z.lua", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + }, + { + name: "zsh-z", + description: "Import from zsh-z", + options: [ + { + name: "--merge", + description: "Merge into existing database", + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + }, + ], + options: [ { name: "--merge", description: "Merge into existing database", @@ -140,10 +238,6 @@ const completion: Fig.Spec = { description: "Print version", }, ], - args: { - name: "path", - template: "filepaths", - }, }, { name: "init", diff --git a/shell.nix b/shell.nix index b7b7400..05f270c 100644 --- a/shell.nix +++ b/shell.nix @@ -4,7 +4,7 @@ let overlays = [ rust ]; }; rust = import (builtins.fetchTarball - "https://github.com/oxalica/rust-overlay/archive/026e8fedefd6b167d92ed04b195c658d95ffc7a5.tar.gz"); + "https://github.com/oxalica/rust-overlay/archive/4568a557ca325ff81fb354382d4a9968daa1001a.tar.gz"); rust-nightly = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal); diff --git a/src/cmd/cmd.rs b/src/cmd/cmd.rs index 7359786..0de2ee5 100644 --- a/src/cmd/cmd.rs +++ b/src/cmd/cmd.rs @@ -95,23 +95,30 @@ pub enum EditCommand { help_template = HelpTemplate, )] pub struct Import { - #[clap(value_hint = ValueHint::FilePath)] - pub path: PathBuf, - - /// Application to import from - #[clap(value_enum, long)] + #[clap(subcommand)] pub from: ImportFrom, /// Merge into existing database - #[clap(long)] + #[clap(long, global = true)] pub merge: bool, } -#[derive(ValueEnum, Clone, Debug)] +#[derive(Subcommand, Clone, Debug)] pub enum ImportFrom { + /// Import from atuin + Atuin, + /// Import from autojump Autojump, - #[clap(alias = "fasd")] + /// Import from fasd + Fasd, + /// Import from z Z, + /// Import from z.lua + #[clap(name = "z.lua")] + ZLua, + /// Import from zsh-z + #[clap(name = "zsh-z")] + ZshZ, } /// Generate shell configuration diff --git a/src/cmd/import.rs b/src/cmd/import.rs index ac0777a..1a53eed 100644 --- a/src/cmd/import.rs +++ b/src/cmd/import.rs @@ -1,166 +1,25 @@ -use std::fs; - -use anyhow::{Context, Result, bail}; +use anyhow::{Result, bail}; use crate::cmd::{Import, ImportFrom, Run}; use crate::db::Database; +use crate::import; impl Run for Import { fn run(&self) -> Result<()> { - let buffer = fs::read_to_string(&self.path).with_context(|| { - format!("could not open database for importing: {}", &self.path.display()) - })?; - let mut db = Database::open()?; if !self.merge && !db.dirs().is_empty() { bail!("current database is not empty, specify --merge to continue anyway"); } match self.from { - ImportFrom::Autojump => import_autojump(&mut db, &buffer), - ImportFrom::Z => import_z(&mut db, &buffer), + ImportFrom::Atuin => import::run(&import::Atuin {}, &mut db)?, + ImportFrom::Autojump => import::run(&import::Autojump {}, &mut db)?, + ImportFrom::Fasd => import::run(&import::Fasd {}, &mut db)?, + ImportFrom::Z => import::run(&import::Z {}, &mut db)?, + ImportFrom::ZLua => import::run(&import::ZLua {}, &mut db)?, + ImportFrom::ZshZ => import::run(&import::ZshZ {}, &mut db)?, } - .context("import error")?; db.save() } } - -fn import_autojump(db: &mut Database, buffer: &str) -> Result<()> { - for line in buffer.lines() { - if line.is_empty() { - continue; - } - let (rank, path) = - line.split_once('\t').with_context(|| format!("invalid entry: {line}"))?; - - let mut rank = rank.parse::().with_context(|| format!("invalid rank: {rank}"))?; - // Normalize the rank using a sigmoid function. Don't import actual ranks from - // autojump, since its scoring algorithm is very different and might - // take a while to normalize. - rank = sigmoid(rank); - - db.add_unchecked(path, rank, 0); - } - - if db.dirty() { - db.dedup(); - } - Ok(()) -} - -fn import_z(db: &mut Database, buffer: &str) -> Result<()> { - for line in buffer.lines() { - if line.is_empty() { - continue; - } - let mut split = line.rsplitn(3, '|'); - - let last_accessed = split.next().with_context(|| format!("invalid entry: {line}"))?; - let last_accessed = - last_accessed.parse().with_context(|| format!("invalid epoch: {last_accessed}"))?; - - let rank = split.next().with_context(|| format!("invalid entry: {line}"))?; - let rank = rank.parse().with_context(|| format!("invalid rank: {rank}"))?; - - let path = split.next().with_context(|| format!("invalid entry: {line}"))?; - - db.add_unchecked(path, rank, last_accessed); - } - - if db.dirty() { - db.dedup(); - } - Ok(()) -} - -fn sigmoid(x: f64) -> f64 { - 1.0 / (1.0 + (-x).exp()) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::db::Dir; - - #[test] - fn from_autojump() { - let data_dir = tempfile::tempdir().unwrap(); - let mut db = Database::open_dir(data_dir.path()).unwrap(); - for (path, rank, last_accessed) in [ - ("/quux/quuz", 1.0, 100), - ("/corge/grault/garply", 6.0, 600), - ("/waldo/fred/plugh", 3.0, 300), - ("/xyzzy/thud", 8.0, 800), - ("/foo/bar", 9.0, 900), - ] { - db.add_unchecked(path, rank, last_accessed); - } - - let buffer = "\ -7.0 /baz -2.0 /foo/bar -5.0 /quux/quuz"; - import_autojump(&mut db, buffer).unwrap(); - - db.sort_by_path(); - println!("got: {:?}", &db.dirs()); - - let exp = [ - Dir { path: "/baz".into(), rank: sigmoid(7.0), last_accessed: 0 }, - Dir { path: "/corge/grault/garply".into(), rank: 6.0, last_accessed: 600 }, - Dir { path: "/foo/bar".into(), rank: 9.0 + sigmoid(2.0), last_accessed: 900 }, - Dir { path: "/quux/quuz".into(), rank: 1.0 + sigmoid(5.0), last_accessed: 100 }, - Dir { path: "/waldo/fred/plugh".into(), rank: 3.0, last_accessed: 300 }, - Dir { path: "/xyzzy/thud".into(), rank: 8.0, last_accessed: 800 }, - ]; - println!("exp: {exp:?}"); - - for (dir1, dir2) in db.dirs().iter().zip(exp) { - assert_eq!(dir1.path, dir2.path); - assert!((dir1.rank - dir2.rank).abs() < 0.01); - assert_eq!(dir1.last_accessed, dir2.last_accessed); - } - } - - #[test] - fn from_z() { - let data_dir = tempfile::tempdir().unwrap(); - let mut db = Database::open_dir(data_dir.path()).unwrap(); - for (path, rank, last_accessed) in [ - ("/quux/quuz", 1.0, 100), - ("/corge/grault/garply", 6.0, 600), - ("/waldo/fred/plugh", 3.0, 300), - ("/xyzzy/thud", 8.0, 800), - ("/foo/bar", 9.0, 900), - ] { - db.add_unchecked(path, rank, last_accessed); - } - - let buffer = "\ -/baz|7|700 -/quux/quuz|4|400 -/foo/bar|2|200 -/quux/quuz|5|500"; - import_z(&mut db, buffer).unwrap(); - - db.sort_by_path(); - println!("got: {:?}", &db.dirs()); - - let exp = [ - Dir { path: "/baz".into(), rank: 7.0, last_accessed: 700 }, - Dir { path: "/corge/grault/garply".into(), rank: 6.0, last_accessed: 600 }, - Dir { path: "/foo/bar".into(), rank: 11.0, last_accessed: 900 }, - Dir { path: "/quux/quuz".into(), rank: 10.0, last_accessed: 500 }, - Dir { path: "/waldo/fred/plugh".into(), rank: 3.0, last_accessed: 300 }, - Dir { path: "/xyzzy/thud".into(), rank: 8.0, last_accessed: 800 }, - ]; - println!("exp: {exp:?}"); - - for (dir1, dir2) in db.dirs().iter().zip(exp) { - assert_eq!(dir1.path, dir2.path); - assert!((dir1.rank - dir2.rank).abs() < 0.01); - assert_eq!(dir1.last_accessed, dir2.last_accessed); - } - } -} diff --git a/src/import.rs b/src/import.rs new file mode 100644 index 0000000..de23adc --- /dev/null +++ b/src/import.rs @@ -0,0 +1,75 @@ +pub(crate) use crate::import::atuin::Atuin; +pub(crate) use crate::import::autojump::Autojump; +pub(crate) use crate::import::fasd::Fasd; +pub(crate) use crate::import::z::Z; +pub(crate) use crate::import::z_lua::ZLua; +pub(crate) use crate::import::zsh_z::ZshZ; + +mod atuin; +mod autojump; +mod fasd; +mod z; +mod z_lua; +mod zsh_z; + +use std::io::{self, Write}; +use std::path::PathBuf; + +use anyhow::Result; + +use crate::config; +use crate::db::{Database, Dir}; + +pub(crate) trait Importer { + /// Yields directory entries to be imported. + /// + /// The outer `Result` reports failure to fetch the input (e.g. missing + /// file, subprocess errored). The per-item `Result` reports a malformed + /// row, which doesn't necessarily abort the whole import. + fn dirs(&self) -> Result, ImportError>>>; +} + +/// A single record that failed to import. +#[derive(Debug)] +pub(crate) struct ImportError { + /// Path of the source file containing the offending record. `None` if the + /// importer is not file-based (e.g. atuin streams from a subprocess). + pub path: Option, + + /// 1-indexed line number of the offending input. + pub line_num: usize, + + /// Underlying reason the record could not be imported. + pub source: anyhow::Error, +} + +/// Drives a single importer end-to-end: writes each `Ok` dir into the +/// database and prints each `Err` to stderr in `:: ` +/// format. Doesn't abort on per-record errors — bad rows are skipped, the +/// rest of the import continues. After the iteration completes successfully, +/// the database is deduplicated and aged. +pub(crate) fn run(importer: &I, db: &mut Database) -> Result<()> { + let stderr = io::stderr(); + let mut stderr = stderr.lock(); + + for entry in importer.dirs()? { + match entry { + Ok(dir) => db.add_unchecked(dir.path, dir.rank, dir.last_accessed), + Err(e) => { + let location = match &e.path { + Some(path) => format!("{}:{}", path.display(), e.line_num), + None => format!("line {}", e.line_num), + }; + let _ = writeln!(stderr, "{location}: {:#}", e.source); + } + } + } + + if db.dirty() { + db.dedup(); + let max_age = config::maxage()?; + db.age(max_age); + } + + Ok(()) +} diff --git a/src/import/atuin.rs b/src/import/atuin.rs new file mode 100644 index 0000000..11b2e82 --- /dev/null +++ b/src/import/atuin.rs @@ -0,0 +1,116 @@ +use std::borrow::Cow; +use std::io::{BufRead, BufReader}; +use std::process::{Child, ChildStdout, Command, Stdio}; +use std::str; + +use anyhow::{Context, Result, anyhow}; + +use crate::db::{Dir, Epoch}; +use crate::import::{ImportError, Importer}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct Atuin {} + +impl Importer for Atuin { + fn dirs(&self) -> Result, ImportError>>> { + // atuin renders `{time}` as `YYYY-MM-DD HH:MM:SS` in UTC. + let mut child = Command::new("atuin") + .args(["history", "list", "--format={time}\t{directory}", "--print0"]) + .stdout(Stdio::piped()) + .spawn() + .context("failed to run `atuin`; is it installed and on PATH?")?; + let stdout = child.stdout.take().expect("stdout piped"); + let reader = BufReader::new(stdout); + Ok(Iter::new(reader, child)) + } +} + +/// Iterates atuin's NUL-separated `{time}\t{directory}` records, emitting one +/// `Dir` per directory transition (consecutive same-path records collapse). +/// Owns the `Child` handle so the subprocess is reaped on Drop. +struct Iter { + reader: BufReader, + buf: Vec, + line_num: usize, + + child: Child, + prev_cwd: Option, +} + +impl Iter { + fn new(reader: BufReader, child: Child) -> Self { + Self { reader, buf: Vec::new(), line_num: 0, child, prev_cwd: None } + } + + fn err(&self, source: anyhow::Error) -> ImportError { + ImportError { path: None, line_num: self.line_num, source } + } + + fn parse_line(&self, line: &[u8]) -> Result, ImportError> { + let line = + str::from_utf8(line).map_err(|e| self.err(anyhow!(e).context("invalid utf-8")))?; + + let (timestamp, path) = + line.split_once('\t').ok_or_else(|| self.err(anyhow!("invalid entry: {line}")))?; + + let timestamp_format = + time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); + let timestamp = time::PrimitiveDateTime::parse(timestamp, timestamp_format) + .map_err(|e| self.err(anyhow!(e).context(format!("invalid timestamp: {timestamp:?}"))))? + .assume_utc() + .unix_timestamp(); + + let dir = Dir { + path: Cow::Owned(path.to_string()), + rank: 1.0, + last_accessed: timestamp as Epoch, + }; + Ok(dir) + } +} + +impl Iterator for Iter { + type Item = Result, ImportError>; + + fn next(&mut self) -> Option { + loop { + self.buf.clear(); + self.line_num += 1; + + match self.reader.read_until(b'\0', &mut self.buf) { + Ok(0) => return None, + Ok(_) => { + if self.buf.last() == Some(&b'\0') { + self.buf.pop(); + } + if self.buf.is_empty() { + continue; + } + + let result = self.parse_line(&self.buf); + match &result { + Ok(dir) => { + let path = dir.path.as_ref(); + if self.prev_cwd.as_deref() == Some(path) { + continue; // dedup consecutive same-path entries + } + self.prev_cwd = Some(path.to_string()); + return Some(result); + } + Err(_) => return Some(result), + } + } + Err(e) => { + return Some(Err(self.err(anyhow!(e).context("could not read from atuin")))); + } + } + } + } +} + +impl Drop for Iter { + fn drop(&mut self) { + let _ = self.child.kill(); + let _ = self.child.wait(); + } +} diff --git a/src/import/autojump.rs b/src/import/autojump.rs new file mode 100644 index 0000000..f269e1f --- /dev/null +++ b/src/import/autojump.rs @@ -0,0 +1,124 @@ +use std::borrow::Cow; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::PathBuf; +use std::{env, str}; + +use anyhow::{Context, Result, anyhow}; + +use crate::db::Dir; +use crate::import::{ImportError, Importer}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct Autojump {} + +impl Importer for Autojump { + fn dirs(&self) -> Result, ImportError>>> { + let path = data_path()?; + let file = File::open(&path).with_context(|| format!("could not read {path:?}"))?; + let reader = BufReader::new(file); + Ok(Iter::new(reader, path)) + } +} + +struct Iter { + reader: R, + buf: Vec, + line_num: usize, + path: PathBuf, +} + +impl Iter { + fn new(reader: R, path: PathBuf) -> Self { + Self { reader, buf: Vec::new(), line_num: 0, path } + } + + fn err(&self, source: anyhow::Error) -> ImportError { + ImportError { path: Some(self.path.clone()), line_num: self.line_num, source } + } + + fn parse_line(&self, line: &[u8]) -> Result, ImportError> { + let line = + str::from_utf8(line).map_err(|e| self.err(anyhow!(e).context("invalid utf-8")))?; + + let (rank, path) = + line.split_once('\t').ok_or_else(|| self.err(anyhow!("invalid entry: {line}")))?; + let rank = rank + .parse::() + .map_err(|e| self.err(anyhow!(e).context(format!("invalid rank: {rank}"))))?; + + // Normalize the rank using a sigmoid function. Don't import actual ranks from + // autojump, since its scoring algorithm is very different and might + // take a while to normalize. + let rank = sigmoid(rank); + + Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed: 0 }) + } +} + +impl Iterator for Iter { + type Item = Result, ImportError>; + + fn next(&mut self) -> Option { + loop { + self.buf.clear(); + self.line_num += 1; + + match self.reader.read_until(b'\n', &mut self.buf) { + Ok(0) => return None, + Ok(_) => { + if self.buf.last() == Some(&b'\n') { + self.buf.pop(); + } + if self.buf.last() == Some(&b'\r') { + self.buf.pop(); + } + if self.buf.is_empty() { + continue; + } + return Some(self.parse_line(&self.buf)); + } + Err(e) => return Some(Err(self.err(anyhow::Error::from(e)))), + } + } + } +} + +/// Mirrors autojump's path logic: +/// +/// ```python +/// if is_osx(): +/// data_home = os.path.join(os.path.expanduser('~'), 'Library') +/// elif is_windows(): +/// data_home = os.getenv('APPDATA') +/// else: +/// data_home = os.getenv( +/// 'XDG_DATA_HOME', +/// os.path.join(os.path.expanduser('~'), '.local', 'share'), +/// ) +/// data_path = os.path.join(data_home, 'autojump', 'autojump.txt') +/// ``` +fn data_path() -> Result { + let mut path = if cfg!(target_os = "macos") { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push("Library"); + path + } else if cfg!(target_os = "windows") { + let appdata = env::var_os("APPDATA").context("%APPDATA% is not set")?; + PathBuf::from(appdata) + } else if let Some(xdg) = env::var_os("XDG_DATA_HOME") { + PathBuf::from(xdg) + } else { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".local"); + path.push("share"); + path + }; + path.push("autojump"); + path.push("autojump.txt"); + Ok(path) +} + +fn sigmoid(x: f64) -> f64 { + 1.0 / (1.0 + (-x).exp()) +} diff --git a/src/import/fasd.rs b/src/import/fasd.rs new file mode 100644 index 0000000..ab0788d --- /dev/null +++ b/src/import/fasd.rs @@ -0,0 +1,39 @@ +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::path::PathBuf; + +use anyhow::{Context, Result}; + +use crate::db::Dir; +use crate::import::{ImportError, Importer, z}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct Fasd {} + +impl Importer for Fasd { + fn dirs(&self) -> Result, ImportError>>> { + let path = data_path()?; + let file = File::open(&path).with_context(|| format!("could not read {path:?}"))?; + let reader = BufReader::new(file); + // fasd uses the same `path|rank|last_accessed` line format as z, so reuse z's + // iterator. + Ok(z::Iter::new(reader, path)) + } +} + +/// Mirrors fasd's path logic: +/// +/// ```sh +/// [ -z "$_FASD_DATA" ] && _FASD_DATA="$HOME/.fasd" +/// ``` +fn data_path() -> Result { + match env::var_os("_FASD_DATA") { + Some(path) => Ok(PathBuf::from(path)), + None => { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".fasd"); + Ok(path) + } + } +} diff --git a/src/import/z.rs b/src/import/z.rs new file mode 100644 index 0000000..511980c --- /dev/null +++ b/src/import/z.rs @@ -0,0 +1,103 @@ +use std::borrow::Cow; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::PathBuf; +use std::{env, str}; + +use anyhow::{Context, Result, anyhow}; + +use crate::db::Dir; +use crate::import::{ImportError, Importer}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct Z {} + +impl Importer for Z { + fn dirs(&self) -> Result, ImportError>>> { + let path = data_path()?; + let file = File::open(&path).with_context(|| format!("could not read {path:?}"))?; + let reader = BufReader::new(file); + Ok(Iter::new(reader, path)) + } +} + +pub(crate) struct Iter { + reader: R, + buf: Vec, + line_num: usize, + path: PathBuf, +} + +impl Iter { + pub(crate) fn new(reader: R, path: PathBuf) -> Self { + Self { reader, buf: Vec::new(), line_num: 0, path } + } + + fn err(&self, source: anyhow::Error) -> ImportError { + ImportError { path: Some(self.path.clone()), line_num: self.line_num, source } + } + + fn parse_line(&self, line: &[u8]) -> Result, ImportError> { + let line = + str::from_utf8(line).map_err(|e| self.err(anyhow!(e).context("invalid utf-8")))?; + let err = || self.err(anyhow!("invalid entry: {line}")); + + // z stores entries as `path|rank|last_accessed`. Use `rsplitn` so paths + // containing `|` are preserved. + let mut split = line.rsplitn(3, '|'); + + let last_accessed = split.next().ok_or_else(err)?; + let last_accessed = last_accessed.parse::().map_err(|_| err())?; + + let rank = split.next().ok_or_else(err)?; + let rank = rank.parse::().map_err(|_| err())?; + + let path = split.next().ok_or_else(err)?; + + Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed }) + } +} + +impl Iterator for Iter { + type Item = Result, ImportError>; + + fn next(&mut self) -> Option { + loop { + self.buf.clear(); + self.line_num += 1; + + match self.reader.read_until(b'\n', &mut self.buf) { + Ok(0) => return None, + Ok(_) => { + if self.buf.last() == Some(&b'\n') { + self.buf.pop(); + } + if self.buf.last() == Some(&b'\r') { + self.buf.pop(); + } + if self.buf.is_empty() { + continue; + } + return Some(self.parse_line(&self.buf)); + } + Err(e) => return Some(Err(self.err(anyhow::Error::from(e)))), + } + } + } +} + +/// Mirrors z's path logic: +/// +/// ```sh +/// local datafile="${_Z_DATA:-$HOME/.z}" +/// ``` +fn data_path() -> Result { + match env::var_os("_Z_DATA") { + Some(path) => Ok(PathBuf::from(path)), + None => { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".z"); + Ok(path) + } + } +} diff --git a/src/import/z_lua.rs b/src/import/z_lua.rs new file mode 100644 index 0000000..0ea4584 --- /dev/null +++ b/src/import/z_lua.rs @@ -0,0 +1,108 @@ +use std::env; +use std::ffi::OsStr; +use std::fs::File; +use std::io::{self, BufReader}; +use std::path::PathBuf; + +use anyhow::{Context, Result}; + +use crate::db::Dir; +use crate::import::{ImportError, Importer, z}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct ZLua {} + +impl Importer for ZLua { + fn dirs(&self) -> Result, ImportError>>> { + let path = data_path()?; + let err = match File::open(&path) { + Ok(file) => return Ok(z::Iter::new(BufReader::new(file), path)), + Err(e) if e.kind() == io::ErrorKind::NotFound => e, + Err(e) => return Err(e).with_context(|| format!("could not read {path:?}")), + }; + + let fish_path = data_path_fish()?; + let file = match File::open(&fish_path) { + Ok(file) => file, + // Both paths missing - report the original path's error. + Err(e) if e.kind() == io::ErrorKind::NotFound => { + return Err(err).with_context(|| format!("could not read {path:?}")); + } + // Fish path failed for some other reason (permissions, etc.) + Err(e) => return Err(e).with_context(|| format!("could not read {fish_path:?}")), + }; + // z.lua uses the same `path|rank|last_accessed` line format as z. + Ok(z::Iter::new(BufReader::new(file), fish_path)) + } +} + +/// Mirrors z.lua's path logic: +/// +/// ```lua +/// DATA_FILE = '~/.zlua' -- default +/// +/// -- in z_init(): +/// local _zl_data = os.getenv('_ZL_DATA') +/// if _zl_data ~= nil and _zl_data ~= "" then +/// if windows then +/// DATA_FILE = _zl_data +/// else +/// -- avoid windows environments affect cygwin & msys +/// if not string.match(_zl_data, '^%a:[/\\]') then +/// DATA_FILE = _zl_data +/// end +/// end +/// end +/// ``` +fn data_path() -> Result { + if let Some(path) = env::var_os("_ZL_DATA") + // Skip empty paths. + .filter(|path| !path.is_empty()) + // On non-Windows, skip values that look like a Windows path (`C:\...`) + // — guards against Cygwin/MSYS environments leaking through. + .filter(|path| cfg!(target_os = "windows") || !looks_like_windows_path(path)) + { + return Ok(PathBuf::from(path)); + } + + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".zlua"); + + Ok(path) +} + +/// Mirrors z.lua's path logic on Fish: +/// +/// ```fish +/// if test -z "$XDG_DATA_HOME" +/// set -U _ZL_DATA_DIR "$HOME/.local/share/zlua" +/// else +/// set -U _ZL_DATA_DIR "$XDG_DATA_HOME/zlua" +/// end +/// set -x _ZL_DATA "$_ZL_DATA_DIR/zlua.txt" +/// ``` +fn data_path_fish() -> Result { + let mut path = match env::var_os("XDG_DATA_HOME") { + Some(xdg) => PathBuf::from(xdg), + None => { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".local"); + path.push("share"); + path + } + }; + + path.push("zlua"); + path.push("zlua.txt"); + + Ok(path) +} + +/// Matches Lua's `^%a:[/\\]` — ASCII letter, colon, slash-or-backslash. +fn looks_like_windows_path(s: &OsStr) -> bool { + let bytes = s.as_encoded_bytes(); + bytes.len() >= 3 + && bytes[0].is_ascii_alphabetic() + && bytes[1] == b':' + && (bytes[2] == b'/' || bytes[2] == b'\\') +} diff --git a/src/import/zsh_z.rs b/src/import/zsh_z.rs new file mode 100644 index 0000000..652faf8 --- /dev/null +++ b/src/import/zsh_z.rs @@ -0,0 +1,41 @@ +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::path::PathBuf; + +use anyhow::{Context, Result}; + +use crate::db::Dir; +use crate::import::{ImportError, Importer, z}; + +#[derive(clap::Args, Clone, Debug)] +pub(crate) struct ZshZ {} + +impl Importer for ZshZ { + fn dirs(&self) -> Result, ImportError>>> { + let path = data_path()?; + let file = File::open(&path).with_context(|| format!("could not read {path:?}"))?; + let reader = BufReader::new(file); + // zsh-z uses the same `path|rank|last_accessed` line format as z. + Ok(z::Iter::new(reader, path)) + } +} + +/// Mirrors zsh-z's path logic: +/// +/// ```sh +/// # Allow the user to specify a custom datafile in $ZSHZ_DATA (or legacy $_Z_DATA) +/// local custom_datafile="${ZSHZ_DATA:-$_Z_DATA}" +/// # If the user specified a datafile, use that or default to ~/.z +/// local datafile=${${custom_datafile:-$HOME/.z}:A} +/// ``` +fn data_path() -> Result { + match env::var_os("ZSHZ_DATA").or_else(|| env::var_os("_Z_DATA")) { + Some(path) => Ok(PathBuf::from(path)), + None => { + let mut path = dirs::home_dir().context("could not find home directory")?; + path.push(".z"); + Ok(path) + } + } +} diff --git a/src/main.rs b/src/main.rs index d4ddd6e..e432b12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod cmd; mod config; mod db; mod error; +mod import; mod shell; mod util; diff --git a/templates/bash.txt b/templates/bash.txt index 068ebea..1888fe3 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -9,7 +9,7 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd() { -{%- let pwd -%} +{%- decl pwd -%} {%- if resolve_symlinks -%} {%- let pwd = "\\builtin pwd -P" -%} {%- else -%} diff --git a/templates/fish.txt b/templates/fish.txt index a13edc7..f5d4aa4 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -7,7 +7,7 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd -{%- let pwd -%} +{%- decl pwd -%} {%- if resolve_symlinks -%} {%- let pwd = "builtin pwd -P" -%} {%- else -%} diff --git a/templates/posix.txt b/templates/posix.txt index b3f660c..7a1b888 100644 --- a/templates/posix.txt +++ b/templates/posix.txt @@ -8,7 +8,7 @@ # # pwd based on the value of _ZO_RESOLVE_SYMLINKS. -{%- let pwd -%} +{%- decl pwd -%} {%- if resolve_symlinks -%} {%- let pwd = "\\command pwd -P" -%} {%- else -%} diff --git a/templates/tcsh.txt b/templates/tcsh.txt index b0559a0..fa00390 100644 --- a/templates/tcsh.txt +++ b/templates/tcsh.txt @@ -1,7 +1,7 @@ {%- let section = "# =============================================================================\n#" -%} {%- let not_configured = "# -- not configured --" -%} -{%- let pwd_cmd -%} +{%- decl pwd_cmd -%} {%- if resolve_symlinks -%} {%- let pwd_cmd = "pwd -P" -%} {%- else -%} diff --git a/templates/zsh.txt b/templates/zsh.txt index a66f960..f748f31 100644 --- a/templates/zsh.txt +++ b/templates/zsh.txt @@ -9,7 +9,7 @@ # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd() { -{%- let pwd -%} +{%- decl pwd -%} {%- if resolve_symlinks -%} {%- let pwd = "\\builtin pwd -P" -%} {%- else -%} From b151e6da3d9b1ed0d99ee7e8d03e7b99f77622c2 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 12 May 2026 05:12:30 +0530 Subject: [PATCH 28/30] pwsh: Use fully qualified names when invoking cmdlets (#1236) --- CHANGELOG.md | 1 + templates/powershell.txt | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34e0ce9..37a8226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- PowerShell: use fully qualified names when invoking cmdlets. - Bash/Fish/POSIX/Zsh: resolve symlinks on Windows. ## [0.9.9] - 2026-01-31 diff --git a/templates/powershell.txt b/templates/powershell.txt index bc877c0..18884fc 100644 --- a/templates/powershell.txt +++ b/templates/powershell.txt @@ -19,7 +19,7 @@ function global:__zoxide_bin { # pwd based on zoxide's format. function global:__zoxide_pwd { - $cwd = Get-Location + $cwd = Microsoft.PowerShell.Management\Get-Location if ($cwd.Provider.Name -eq "FileSystem") { $cwd.ProviderPath } @@ -29,23 +29,23 @@ function global:__zoxide_pwd { function global:__zoxide_cd($dir, $literal) { $dir = if ($literal) { if ($null -eq $dir) { - Set-Location + Microsoft.PowerShell.Management\Set-Location } else { - Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop + Microsoft.PowerShell.Management\Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop } } else { if ($dir -eq '-' -and ($PSVersionTable.PSVersion -lt 6.1)) { - Write-Error "cd - is not supported below PowerShell 6.1. Please upgrade your version of PowerShell." + Microsoft.PowerShell.Utility\Write-Error "cd - is not supported below PowerShell 6.1. Please upgrade your version of PowerShell." } elseif ($dir -eq '+' -and ($PSVersionTable.PSVersion -lt 6.2)) { - Write-Error "cd + is not supported below PowerShell 6.2. Please upgrade your version of PowerShell." + Microsoft.PowerShell.Utility\Write-Error "cd + is not supported below PowerShell 6.2. Please upgrade your version of PowerShell." } else { - Set-Location -Path $dir -Passthru -ErrorAction Stop + Microsoft.PowerShell.Management\Set-Location -Path $dir -Passthru -ErrorAction Stop } } {%- if echo %} - Write-Output $dir.Path + Microsoft.PowerShell.Utility\Write-Output $dir.Path {%- endif %} } @@ -84,7 +84,7 @@ function global:__zoxide_hook { {%- endif %} # Initialize hook. -$global:__zoxide_hooked = (Get-Variable __zoxide_hooked -ErrorAction Ignore -ValueOnly) +$global:__zoxide_hooked = (Microsoft.PowerShell.Utility\Get-Variable __zoxide_hooked -ErrorAction Ignore -ValueOnly) if ($global:__zoxide_hooked -ne 1) { $global:__zoxide_hooked = 1 $global:__zoxide_prompt_old = $function:prompt @@ -110,10 +110,10 @@ function global:__zoxide_z { elseif ($args.Length -eq 1 -and ($args[0] -eq '-' -or $args[0] -eq '+')) { __zoxide_cd $args[0] $false } - elseif ($args.Length -eq 1 -and (Test-Path -PathType Container -LiteralPath $args[0])) { + elseif ($args.Length -eq 1 -and (Microsoft.PowerShell.Management\Test-Path -PathType Container -LiteralPath $args[0])) { __zoxide_cd $args[0] $true } - elseif ($args.Length -eq 1 -and (Test-Path -PathType Container -Path $args[0] )) { + elseif ($args.Length -eq 1 -and (Microsoft.PowerShell.Management\Test-Path -PathType Container -Path $args[0] )) { __zoxide_cd $args[0] $false } else { @@ -145,8 +145,8 @@ function global:__zoxide_zi { {%- match cmd %} {%- when Some with (cmd) %} -Set-Alias -Name {{cmd}} -Value __zoxide_z -Option AllScope -Scope Global -Force -Set-Alias -Name {{cmd}}i -Value __zoxide_zi -Option AllScope -Scope Global -Force +Microsoft.PowerShell.Utility\Set-Alias -Name {{cmd}} -Value __zoxide_z -Option AllScope -Scope Global -Force +Microsoft.PowerShell.Utility\Set-Alias -Name {{cmd}}i -Value __zoxide_zi -Option AllScope -Scope Global -Force {%- when None %} From cff57b773462668d478041ab9ce443b609a7d827 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 12 May 2026 14:22:25 +0530 Subject: [PATCH 29/30] Remove nix dependency (#1237) --- Cargo.lock | 27 ++++----------------------- Cargo.toml | 6 ------ src/import.rs | 4 ++-- src/import/atuin.rs | 4 ++-- src/util.rs | 8 ++------ 5 files changed, 10 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d821298..b993b19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39bae1d3fa576f7c6519514180a72559268dd7d1fe104070956cb687bc6673bd" +checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ "anstyle", "bstr", @@ -167,12 +167,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "clap" version = "4.6.1" @@ -197,9 +191,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.4" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e962dae2b1e5007fe9e3db363ddc43a8bf25546d279f7a8a4401204690e80c" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ "clap", ] @@ -471,18 +465,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "nix" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -1185,7 +1167,6 @@ dependencies = [ "dunce", "fastrand", "glob", - "nix", "ouroboros", "rstest", "rstest_reuse", diff --git a/Cargo.toml b/Cargo.toml index 25227ee..74be3ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,12 +32,6 @@ ouroboros = "0.18.3" serde = { version = "1.0.116", features = ["derive"] } time = { version = "0.3.47", default-features = false, features = ["parsing", "macros", "std"] } -[target.'cfg(unix)'.dependencies] -nix = { version = "0.31.2", default-features = false, features = [ - "fs", - "user", -] } - [target.'cfg(windows)'.dependencies] which = "8.0.2" diff --git a/src/import.rs b/src/import.rs index de23adc..caedc4e 100644 --- a/src/import.rs +++ b/src/import.rs @@ -48,7 +48,7 @@ pub(crate) struct ImportError { /// format. Doesn't abort on per-record errors — bad rows are skipped, the /// rest of the import continues. After the iteration completes successfully, /// the database is deduplicated and aged. -pub(crate) fn run(importer: &I, db: &mut Database) -> Result<()> { +pub(crate) fn run(importer: &impl Importer, db: &mut Database) -> Result<()> { let stderr = io::stderr(); let mut stderr = stderr.lock(); @@ -60,7 +60,7 @@ pub(crate) fn run(importer: &I, db: &mut Database) -> Result<()> { Some(path) => format!("{}:{}", path.display(), e.line_num), None => format!("line {}", e.line_num), }; - let _ = writeln!(stderr, "{location}: {:#}", e.source); + _ = writeln!(stderr, "{location}: {:#}", e.source); } } } diff --git a/src/import/atuin.rs b/src/import/atuin.rs index 11b2e82..513efe5 100644 --- a/src/import/atuin.rs +++ b/src/import/atuin.rs @@ -110,7 +110,7 @@ impl Iterator for Iter { impl Drop for Iter { fn drop(&mut self) { - let _ = self.child.kill(); - let _ = self.child.wait(); + _ = self.child.kill(); + _ = self.child.wait(); } } diff --git a/src/util.rs b/src/util.rs index 996f61d..4c0a27c 100644 --- a/src/util.rs +++ b/src/util.rs @@ -168,13 +168,9 @@ pub fn write(path: impl AsRef, contents: impl AsRef<[u8]>) -> Result<()> { // Set the owner of the tmpfile (UNIX only). #[cfg(unix)] if let Ok(metadata) = path.metadata() { - use std::os::unix::fs::MetadataExt; + use std::os::unix::fs::{MetadataExt, fchown}; - use nix::unistd::{self, Gid, Uid}; - - let uid = Uid::from_raw(metadata.uid()); - let gid = Gid::from_raw(metadata.gid()); - _ = unistd::fchown(&tmp_file, Some(uid), Some(gid)); + _ = fchown(&tmp_file, Some(metadata.uid()), Some(metadata.gid())); } // Close and rename the tmpfile. From c8a47a068bd9364e93d0c7eebd8bf58bdcc33b90 Mon Sep 17 00:00:00 2001 From: Puneet Dixit Date: Fri, 22 May 2026 00:13:25 +0530 Subject: [PATCH 30/30] Skip zsh doctor in non-interactive shells (#1241) Co-authored-by: Puneet Dixit <236133619+puneetdixit200@users.noreply.github.com> Co-authored-by: Ajeet D'Souza <98ajeet@gmail.com> --- templates/zsh.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/zsh.txt b/templates/zsh.txt index f748f31..f900f3a 100644 --- a/templates/zsh.txt +++ b/templates/zsh.txt @@ -59,6 +59,7 @@ function __zoxide_doctor() { {%- else %} [[ ${_ZO_DOCTOR:-1} -ne 0 ]] || return 0 + [[ $- == *i* ]] || return 0 {%- if hook == InitHook::Prompt %} [[ ${precmd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]] || return 0