diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index debc0cf..9e3ff41 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -7,10 +7,17 @@ jobs:
publish-crates-io:
name: Publish on crates.io
runs-on: ubuntu-latest
+ permissions:
+ id-token: write
steps:
- name: Checkout the repository
- uses: actions/checkout@v6
+ uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
+ - name: Authenticate with crates.io
+ id: auth
+ uses: rust-lang/crates-io-auth-action@v1
- name: Publish
- run: cargo publish --token ${{ secrets.CARGO_TOKEN }}
+ run: cargo publish
+ env:
+ CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3f35ac3..f3ba0df 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,7 +21,7 @@ jobs:
matrix:
os: [ubuntu-latest]
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions-rs/toolchain@v1
@@ -40,13 +40,13 @@ 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 }}
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..497a108 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
@@ -44,7 +47,7 @@ jobs:
target: aarch64-pc-windows-msvc
steps:
- name: Checkout repository
- uses: actions/checkout@v6
+ uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Get version
@@ -61,7 +64,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
@@ -102,7 +105,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: |
@@ -112,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: |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b38fe2..a33d039 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,11 +11,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
+- Support for RISC-V (riscv64) Linux.
+- `import` now supports fetching entries from `atuin`.
+- `import` now skips directories matching `$_ZO_EXCLUDE_DIRS`.
- POSIX: support for non-Cygwin Windows environments (e.g. Busybox).
+- Fish: Space-Tab completions now display and run the selected command.
+
+### Changed
+
+- `import` now auto-detects database files.
+- Nushell: export commands so the init script can be imported with `use`.
### Fixed
- Bash/Fish/POSIX/Zsh: resolve symlinks on Windows.
+- Bash: handle `$PROMPT_COMMAND` values ending in a semicolon.
+- PowerShell: navigate to home directory with `z` on drives that don't define `HOME`.
+- PowerShell: use fully qualified names when invoking cmdlets.
+- Zsh: skip doctor diagnostics in non-interactive shells.
+- Zsh: avoid inserting a trailing space when cancelling interactive Space-Tab completions.
+- Bash: avoid blanking the prompt when cancelling interactive Space-Tab completions.
+- Bash/Fish/Zsh: avoid drawing a new line when Space-Tab completion finds no matches.
+- Tcsh: preserve any existing `precmd` alias instead of overwriting it.
+- Nushell: complete only directories for `z`, instead of all files.
## [0.9.9] - 2026-01-31
diff --git a/Cargo.lock b/Cargo.lock
index 27da609..b993b19 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.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66"
+checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6"
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,21 +163,15 @@ 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"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[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 +179,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 +191,9 @@ dependencies = [
[[package]]
name = "clap_complete"
-version = "4.5.50"
+version = "4.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c91d3baa3bcd889d60e6ef28874126a0b384fd225ab83aa6d8a801c519194ce1"
+checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772"
dependencies = [
"clap",
]
@@ -207,9 +210,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 +220,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 +232,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 +259,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 +299,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 +306,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 +323,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 +391,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"
@@ -414,18 +465,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-[[package]]
-name = "nix"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
-]
-
[[package]]
name = "nom"
version = "7.1.3"
@@ -437,16 +476,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 +525,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 +546,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 +557,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 +605,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 +645,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 +673,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 +684,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 +733,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 +748,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 +759,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 +797,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 +822,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 +833,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 +852,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 +871,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 +935,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 +1126,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"
@@ -998,11 +1167,11 @@ dependencies = [
"dunce",
"fastrand",
"glob",
- "nix",
"ouroboros",
"rstest",
"rstest_reuse",
"serde",
"tempfile",
+ "time",
"which",
]
diff --git a/Cargo.toml b/Cargo.toml
index d137115..74be3ef 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,10 @@ fastrand = "2.0.0"
glob = "0.3.0"
ouroboros = "0.18.3"
serde = { version = "1.0.116", features = ["derive"] }
-
-[target.'cfg(unix)'.dependencies]
-nix = { version = "0.30.1", default-features = false, features = [
- "fs",
- "user",
-] }
+time = { version = "0.3.47", default-features = false, features = ["parsing", "macros", "std"] }
[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 7750205..4c17ade 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,13 @@
to learn more.
+
+
+
+ Processing over 3TB/s of video at peak load,
+
+
+ |
@@ -64,7 +71,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].
@@ -89,30 +96,29 @@ zoxide can be installed in 4 easy steps:
>
> Or, you can use a package manager:
>
- > | Distribution | Repository | Instructions |
- > | ------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------- |
- > | **_Any_** | **[crates.io]** | `cargo install zoxide --locked` |
- > | _Any_ | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git`
`asdf install zoxide latest` |
- > | _Any_ | [conda-forge] | `conda install -c conda-forge zoxide` |
- > | _Any_ | [guix] | `guix install zoxide` |
- > | _Any_ | [Linuxbrew] | `brew install zoxide` |
- > | _Any_ | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
- > | Alpine Linux 3.13+ | [Alpine Linux Packages] | `apk add zoxide` |
- > | Arch Linux | [Arch Linux Extra] | `pacman -S zoxide` |
- > | ~Debian~[^1] | ~[Debian Packages]~ | ~`apt install zoxide`~ |
- > | Devuan 4.0+ | [Devuan Packages] | `apt install zoxide` |
- > | Exherbo Linux | [Exherbo packages] | `cave resolve -x repository/rust`
`cave resolve -x zoxide` |
- > | Fedora 32+ | [Fedora Packages] | `dnf install zoxide` |
- > | Gentoo | [Gentoo Packages] | `emerge app-shells/zoxide` |
- > | Manjaro | | `pacman -S zoxide` |
- > | openSUSE Tumbleweed | [openSUSE Factory] | `zypper install zoxide` |
- > | ~Parrot OS~[^1] | | ~`apt install zoxide`~ |
- > | ~Raspbian~[^1] | ~[Raspbian Packages]~ | ~`apt install zoxide`~ |
- > | Rhino Linux | [Pacstall Packages] | `pacstall -I zoxide-deb` |
- > | Slackware 15.0+ | [SlackBuilds] | [Instructions][slackbuilds-howto] |
- > | Solus | [Solus Packages] | `eopkg install zoxide` |
- > | ~Ubuntu~[^1] | ~[Ubuntu Packages]~ | ~`apt install zoxide`~ |
- > | Void Linux | [Void Linux Packages] | `xbps-install -S zoxide` |
+ > | Distribution | Repository | Instructions |
+ > | ------------------- | ----------------------- | ----------------------------------------------------------------- |
+ > | **_Any_** | **[crates.io]** | `cargo install zoxide --locked` |
+ > | _Any_ | [conda-forge] | `conda install -c conda-forge zoxide` |
+ > | _Any_ | [guix] | `guix install zoxide` |
+ > | _Any_ | [Linuxbrew] | `brew install zoxide` |
+ > | _Any_ | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
+ > | Alpine Linux 3.13+ | [Alpine Linux Packages] | `apk add zoxide` |
+ > | Arch Linux | [Arch Linux Extra] | `pacman -S zoxide` |
+ > | ~~Debian~~[^1] | ~~[Debian Packages]~~ | ~~`apt install zoxide`~~ |
+ > | Devuan 4.0+ | [Devuan Packages] | `apt install zoxide` |
+ > | Exherbo Linux | [Exherbo packages] | `cave resolve -x repository/rust`
`cave resolve -x zoxide` |
+ > | Fedora 32+ | [Fedora Packages] | `dnf install zoxide` |
+ > | Gentoo | [Gentoo Packages] | `emerge app-shells/zoxide` |
+ > | Manjaro | | `pacman -S zoxide` |
+ > | openSUSE Tumbleweed | [openSUSE Factory] | `zypper install zoxide` |
+ > | ~~Parrot OS~~[^1] | | ~~`apt install zoxide`~~ |
+ > | ~~Raspbian~~[^1] | ~~[Raspbian Packages]~~ | ~~`apt install zoxide`~~ |
+ > | Rhino Linux | [Pacstall Packages] | `pacstall -I zoxide-deb` |
+ > | Slackware 15.0+ | [SlackBuilds] | [Instructions][slackbuilds-howto] |
+ > | Solus | [Solus Packages] | `eopkg install zoxide` |
+ > | ~~Ubuntu~~[^1] | ~~[Ubuntu Packages]~~ | ~~`apt install zoxide`~~ |
+ > | Void Linux | [Void Linux Packages] | `xbps-install -S zoxide` |
@@ -121,14 +127,13 @@ zoxide can be installed in 4 easy steps:
> To install zoxide, use a package manager:
>
- > | Repository | Instructions |
- > | --------------- | ----------------------------------------------------------------------------------------------------- |
- > | **[crates.io]** | `cargo install zoxide --locked` |
- > | **[Homebrew]** | `brew install zoxide` |
- > | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git`
`asdf install zoxide latest` |
- > | [conda-forge] | `conda install -c conda-forge zoxide` |
- > | [MacPorts] | `port install zoxide` |
- > | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
+ > | Repository | Instructions |
+ > | --------------- | ------------------------------------- |
+ > | **[crates.io]** | `cargo install zoxide --locked` |
+ > | **[Homebrew]** | `brew install zoxide` |
+ > | [conda-forge] | `conda install -c conda-forge zoxide` |
+ > | [MacPorts] | `port install zoxide` |
+ > | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
>
> Or, run this command in your terminal:
>
@@ -329,8 +334,8 @@ 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)
@@ -343,61 +348,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
@@ -505,7 +470,6 @@ Environment variables[^2] can be used for configuration. They must be set before
[algorithm-matching]: https://github.com/ajeetdsouza/zoxide/wiki/Algorithm#matching
[alpine linux packages]: https://pkgs.alpinelinux.org/packages?name=zoxide
[arch linux extra]: https://archlinux.org/packages/extra/x86_64/zoxide/
-[asdf]: https://github.com/asdf-vm/asdf
[builtwithnix-badge]: https://img.shields.io/badge/builtwith-nix-7d81f7?logo=nixos&logoColor=white&style=flat-square
[builtwithnix]: https://builtwithnix.org/
[chocolatey]: https://community.chocolatey.org/packages/zoxide
@@ -564,7 +528,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
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..b68f564
--- /dev/null
+++ b/src/import.rs
@@ -0,0 +1,82 @@
+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: &impl Importer, db: &mut Database) -> Result<()> {
+ let exclude_dirs = config::exclude_dirs()?;
+
+ let stderr = io::stderr();
+ let mut stderr = stderr.lock();
+
+ for entry in importer.dirs()? {
+ match entry {
+ Ok(dir) => {
+ if exclude_dirs.iter().any(|glob| glob.matches(&dir.path)) {
+ continue;
+ }
+ 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),
+ };
+ _ = 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..513efe5
--- /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) {
+ _ = self.child.kill();
+ _ = 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/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.
diff --git a/templates/bash.txt b/templates/bash.txt
index 068ebea..e268a9d 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 -%}
@@ -178,7 +178,7 @@ if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VER
# If there is a space after the last word, use interactive selection.
elif [[ -z ${COMP_WORDS[-1]} ]]; then
# shellcheck disable=SC2312
- __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" && {
+ if __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}" 2>/dev/null)"; then
# In case the terminal does not respond to \e[5n or another
# mechanism steals the response, it is still worth completing
# the directory in the command line.
@@ -189,7 +189,12 @@ if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VER
# builtin "bind".
bind -x '"\e[0n": __zoxide_z_complete_helper'
\builtin printf '\e[5n' >/dev/tty
- }
+ else
+ # The interactive selection was cancelled. fzf has drawn over
+ # the prompt, so redraw the current line.
+ bind '"\e[0n": redraw-current-line'
+ \builtin printf '\e[5n' >/dev/tty
+ fi
fi
}
diff --git a/templates/fish.txt b/templates/fish.txt
index a13edc7..fab533a 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 -%}
@@ -100,9 +100,9 @@ function __zoxide_z_complete
else if test (builtin count $tokens) -eq (builtin count $curr_tokens)
# If the last argument is empty, use interactive selection.
set -l query $tokens[2..-1]
- set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query)
- and __zoxide_cd $result
- and builtin commandline --function cancel-commandline repaint
+ set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query 2>/dev/null)
+ and builtin commandline --replace -- "{{ cmd.unwrap_or("cd") }} "(string escape -- $result)
+ and builtin commandline --function repaint execute
end
end
complete --command __zoxide_z --no-files --arguments '(__zoxide_z_complete)'
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/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 %}
diff --git a/templates/tcsh.txt b/templates/tcsh.txt
index b0559a0..e892670 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 -%}
@@ -23,7 +23,15 @@ alias __zoxide_hook 'set __zoxide_pwd_tmp = "`{{ pwd_cmd }}`"; test "$__zoxide_p
{%- endif %}
# Initialize hook.
-alias precmd ';__zoxide_hook'
+set __zoxide_precmd = "`alias precmd`"
+if ( "$__zoxide_precmd" !~ *__zoxide_hook* ) then
+ if ( "$__zoxide_precmd" == "" ) then
+ alias precmd '__zoxide_hook'
+ else
+ alias precmd "$__zoxide_precmd"';__zoxide_hook'
+ endif
+endif
+unset __zoxide_precmd
{%- endif %}
diff --git a/templates/zsh.txt b/templates/zsh.txt
index a66f960..9cdbcc2 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 -%}
@@ -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
@@ -143,10 +144,10 @@ if [[ -o zle ]]; then
elif [[ "${words[-1]}" == '' ]]; then
# Show completions for Space-Tab.
# shellcheck disable=SC2086
- __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd || \builtin true)" --interactive -- ${words[2,-1]})" || __zoxide_result=''
+ __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd || \builtin true)" --interactive -- ${words[2,-1]} 2>/dev/null)" || __zoxide_result=''
# Set a result to ensure completion doesn't re-run
- compadd -Q ""
+ compadd -Q -S "" -- ""
# Bind '\e[0n' to helper function.
\builtin bindkey '\e[0n' '__zoxide_z_complete_helper'