Compare commits

..

No commits in common. "main" and "v0.9.1" have entirely different histories.
main ... v0.9.1

45 changed files with 1033 additions and 1855 deletions

1
.envrc
View File

@ -1 +0,0 @@
use nix

View File

@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly

View File

@ -8,9 +8,6 @@ env:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
CARGO_INCREMENTAL: 0 CARGO_INCREMENTAL: 0
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: permissions:
contents: read contents: read
jobs: jobs:
@ -19,9 +16,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest, windows-latest]
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
@ -36,17 +33,17 @@ jobs:
components: rustfmt components: rustfmt
profile: minimal profile: minimal
toolchain: nightly toolchain: nightly
- uses: cachix/install-nix-action@v31 - uses: cachix/install-nix-action@v20
if: ${{ matrix.os != 'windows-latest' }} if: ${{ matrix.os != 'windows-latest' }}
with: with:
nix_path: nixpkgs=channel:nixos-unstable nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v16 - uses: cachix/cachix-action@v12
if: ${{ matrix.os != 'windows-latest' && env.CACHIX_AUTH_TOKEN != '' }} if: ${{ matrix.os != 'windows-latest' && env.CACHIX_AUTH_TOKEN != '' }}
with: with:
authToken: ${{ env.CACHIX_AUTH_TOKEN }} authToken: ${{ env.CACHIX_AUTH_TOKEN }}
name: zoxide name: zoxide
- name: Setup cache - name: Setup cache
uses: Swatinem/rust-cache@v2.8.1 uses: Swatinem/rust-cache@v2
with: with:
key: ${{ matrix.os }} key: ${{ matrix.os }}
- name: Install just - name: Install just

View File

@ -4,11 +4,11 @@ on:
types: [created] types: [created]
schedule: schedule:
- cron: "0 0 * * *" # daily at 00:00 - cron: "0 0 * * *" # daily at 00:00
permissions:
issues: write
jobs: jobs:
no-response: no-response:
if: github.repository == 'ajeetdsouza/zoxide' if: github.repository == 'ajeetdsouza/zoxide'
permissions:
issues: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: lee-dohm/no-response@v0.5.0 - uses: lee-dohm/no-response@v0.5.0
@ -17,5 +17,6 @@ jobs:
daysUntilClose: 30 daysUntilClose: 30
responseRequiredLabel: waiting-for-response responseRequiredLabel: waiting-for-response
closeComment: > closeComment: >
This issue has been automatically closed due to inactivity. If you feel this is still relevant, please comment here or create a fresh issue. This issue has been automatically closed due to inactivity. If you feel
this is still relevant, please comment here or create a fresh issue.

View File

@ -23,18 +23,12 @@ jobs:
target: arm-unknown-linux-musleabihf target: arm-unknown-linux-musleabihf
- os: ubuntu-latest - os: ubuntu-latest
target: armv7-unknown-linux-musleabihf target: armv7-unknown-linux-musleabihf
deb: true
- os: ubuntu-latest - os: ubuntu-latest
target: aarch64-unknown-linux-musl target: aarch64-unknown-linux-musl
deb: true deb: true
- os: ubuntu-latest - os: macos-11
target: i686-unknown-linux-musl
deb: true
- os: ubuntu-latest
target: aarch64-linux-android
- os: macos-latest
target: x86_64-apple-darwin target: x86_64-apple-darwin
- os: macos-latest - os: macos-11
target: aarch64-apple-darwin target: aarch64-apple-darwin
- os: windows-latest - os: windows-latest
target: x86_64-pc-windows-msvc target: x86_64-pc-windows-msvc
@ -42,12 +36,12 @@ jobs:
target: aarch64-pc-windows-msvc target: aarch64-pc-windows-msvc
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Get version - name: Get version
id: get_version id: get_version
uses: SebRollen/toml-action@v1.2.0 uses: SebRollen/toml-action@v1.0.2
with: with:
file: Cargo.toml file: Cargo.toml
field: package.version field: package.version
@ -59,15 +53,9 @@ jobs:
override: true override: true
target: ${{ matrix.target }} target: ${{ matrix.target }}
- name: Setup cache - name: Setup cache
uses: Swatinem/rust-cache@v2.8.1 uses: Swatinem/rust-cache@v1.0.2
with: with:
key: ${{ matrix.target }} key: ${{ matrix.target }}
- name: Install cross
if: ${{ runner.os == 'Linux' }}
uses: actions-rs/cargo@v1
with:
command: install
args: --color=always --git=https://github.com/cross-rs/cross.git --locked --rev=e281947ca900da425e4ecea7483cfde646c8a1ea --verbose cross
- name: Build binary - name: Build binary
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
@ -100,7 +88,7 @@ jobs:
CHANGELOG.md LICENSE README.md ./man/ ./contrib/completions/ ` CHANGELOG.md LICENSE README.md ./man/ ./contrib/completions/ `
./target/${{ matrix.target }}/release/zoxide.exe ./target/${{ matrix.target }}/release/zoxide.exe
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: ${{ matrix.target }} name: ${{ matrix.target }}
path: | path: |
@ -109,8 +97,8 @@ jobs:
*.zip *.zip
- name: Create release - name: Create release
if: | if: |
github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'chore(release)') ${{ github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'chore(release)') }}
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
draft: true draft: true
files: | files: |

View File

@ -1,13 +0,0 @@
name: winget
on:
release:
types: [released]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: ajeetdsouza.zoxide
installers-regex: '-pc-windows-msvc\.zip$'
token: ${{ secrets.WINGET_TOKEN }}

View File

@ -7,108 +7,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.9.8] - 2025-05-27
### Added
- Support for Tcsh.
- Added `--score` flag to `zoxide add`.
- POSIX: add doctor to diagnose common issues.
- Nushell: add CLI completions.
### Changed
- Bash: zoxide will now automatically `cd` when selecting Space-Tab completions.
### Fixed
- Bash: doctor now handles `PROMPT_COMMAND` being an array.
- Bash: doctor now handles Visual Studio Code's shell integration.
- Bash: completions now work with `ble.sh`.
- Nushell: stop ignoring symlinks when `cd`-ing into a directory.
- Fzf: updated minimum supported version to v0.51.0.
- PowerShell: avoid setting `$error` when defining `__zoxide_hooked`.
- PowerShell: handle special characters in file paths when `cd`-ing into them.
- Database corruption issue when the filesystem is 100% full.
## [0.9.7] - 2025-02-10
### Added
- Nushell: support for 0.102.0.
- Bash / Zsh: add doctor to diagnose common issues.
### Fixed
- ksh: alias to regular POSIX implementation for better compatibility.
## [0.9.6] - 2024-09-19
### Fixed
- Fish: `builtin abbr` doesn't work on older versions.
- Zsh: make `__zoxide_z_complete` available with `--no-cmd`.
## [0.9.5] - 2024-09-13
### Added
- Zsh: improved `cd` completions.
- Lazily delete excluded directories from the database.
- Fish: detect infinite loop when using `alias cd=z`.
- Installer: added flags for `--bin-dir`, `--man-dir`, `--arch`, and `--sudo`.
- Nushell: support for v0.94.0+.
- Bash/Fish/Zsh: support for `z -- dir` style queries.
- Fish: improved Space-Tab completions.
- Ksh: added support for the Korn shell.
### Changed
- fzf: removed `--select-1` from default options. The interactive selector will
now open up even if there is only one match.
- Enforce that `$_ZO_DATA_DIR` is an absolute path.
### Fixed
- Zsh: Space-Tab completion repeating output multiple times when matching single
directory
- Fish / Nushell / PowerShell: handle queries that look like args (e.g. `z -x`).
- Elvish: `z -` now works as expected.
- Fish: generated shell code avoids using aliased builtins.
- Fish: `cd` command is now copied directly from
`$__fish_data_dir/functions/cd.fish`. This should minimize the chances of an
infinite loop when aliasing `cd=z`.
- Symlinks not getting added to the database when `$_ZO_RESOLVE_SYMLINKS=0`.
- Symlinked database files getting replaced instead of the actual files.
## [0.9.4] - 2024-02-21
### Changed
- Zsh: improved Space-Tab completions.
## [0.9.3] - 2024-02-13
### Added
- Nushell: support for v0.89.0.
## [0.9.2] - 2023-08-04
### Added
- Short option `-a` for `zoxide query --all`.
### Fixed
- PowerShell: use `global` scope for variables / functions.
## [0.9.1] - 2023-05-07 ## [0.9.1] - 2023-05-07
### Added ### Added
- Fish/Zsh: aliases on `__zoxide_z` will now use completions. - Fish/Zsh: aliases on `__zoxide_z` will now use completions.
- Nushell: support for v0.78.0. - Nushell: add support for v0.78.0.
- Fish: plugin now works on older versions. - Fish: plugin now works on older versions.
- PowerShell: warn when PowerShell version is too old for `z -` and `z +`. - PowerShell: warn when PowerShell version is too old for `z -` and `z +`.
- PowerShell: support for PWD hooks on all versions. - PowerShell: support for PWD hooks on all versions.
@ -327,9 +231,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- `cd -` on Fish shells. - `cd -` on fish shells.
- `__zoxide_hook` no longer changes value of `$?` within `$PROMPT_COMMAND` on - `__zoxide_hook` no longer changes value of `$?` within `$PROMPT_COMMAND` on
Bash. bash.
### Removed ### Removed
@ -368,7 +272,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `$_ZO_EXCLUDE_DIRS` now supports globs. - `$_ZO_EXCLUDE_DIRS` now supports globs.
- `zoxide init` now defines `__zoxide_z*` functions that can be aliased as - `zoxide init` now defines `__zoxide_z*` functions that can be aliased as
needed. needed.
- Support for the [Xonsh](https://xon.sh/) shell. - Support for the [xonsh](https://xon.sh/) shell.
- `zoxide import` can now import from Autojump. - `zoxide import` can now import from Autojump.
### Changed ### Changed
@ -377,7 +281,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Clobber conflicting alias definitions in Bash/Fish/Zsh/POSIX shells. - Clobber conflicting alias definitions in bash/fish/zsh/POSIX shells.
### Removed ### Removed
@ -388,7 +292,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Bug in Fish init script. - Bug in Fish init script
## [0.4.2] - 2020-07-03 ## [0.4.2] - 2020-07-03
@ -413,7 +317,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Support for PowerShell. - Support for powershell.
### Removed ### Removed
@ -441,7 +345,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Fish no longer `cd`s to the user's home when no match is found. - fish no longer `cd`s to the user's home when no match is found.
## [0.3.1] - 2020-04-03 ## [0.3.1] - 2020-04-03
@ -481,7 +385,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Incorrect exit codes in `z` command on Fish. - Incorrect exit codes in `z` command on fish.
### Removed ### Removed
@ -494,7 +398,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `$_ZO_ECHO` to echo match before `cd`ing. - `$_ZO_ECHO` to echo match before `cd`ing.
- Minimal `ranger` plugin. - Minimal `ranger` plugin.
- PWD hook to only update the database when the current directory is changed. - PWD hook to only update the database when the current directory is changed.
- Support for Bash. - Support for bash.
- `migrate` subcommand to allow users to migrate from `z`. - `migrate` subcommand to allow users to migrate from `z`.
### Fixed ### Fixed
@ -508,11 +412,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `init` subcommand to remove dependency on shell plugin managers. - `init` subcommand to remove dependency on shell plugin managers.
- Support for `z -` command to go to previous directory. - Support for `z -` command to go to previous directory.
- `Cargo.lock` for more reproducible builds. - `Cargo.lock` for more reproducible builds.
- Support for the Fish shell. - Support for the fish shell.
### Fixed ### Fixed
- `_zoxide_precmd` overriding other precmd hooks on Zsh. - `_zoxide_precmd` overriding other precmd hooks on zsh.
## [0.1.1] - 2020-03-08 ## [0.1.1] - 2020-03-08
@ -534,15 +438,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- GitHub Actions pipeline to build and upload releases. - GitHub Actions pipeline to build and upload releases.
- Add support for Zsh. - Support for zsh.
[0.9.8]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.7...v0.9.8
[0.9.7]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.6...v0.9.7
[0.9.6]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.5...v0.9.6
[0.9.5]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.4...v0.9.5
[0.9.4]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.3...v0.9.4
[0.9.3]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.2...v0.9.3
[0.9.2]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.1...v0.9.2
[0.9.1]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.0...v0.9.1 [0.9.1]: https://github.com/ajeetdsouza/zoxide/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/ajeetdsouza/zoxide/compare/v0.8.3...v0.9.0 [0.9.0]: https://github.com/ajeetdsouza/zoxide/compare/v0.8.3...v0.9.0
[0.8.3]: https://github.com/ajeetdsouza/zoxide/compare/v0.8.2...v0.8.3 [0.8.3]: https://github.com/ajeetdsouza/zoxide/compare/v0.8.2...v0.8.3

809
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,56 +2,52 @@
authors = ["Ajeet D'Souza <98ajeet@gmail.com>"] authors = ["Ajeet D'Souza <98ajeet@gmail.com>"]
categories = ["command-line-utilities", "filesystem"] categories = ["command-line-utilities", "filesystem"]
description = "A smarter cd command for your terminal" description = "A smarter cd command for your terminal"
edition = "2024" edition = "2021"
homepage = "https://github.com/ajeetdsouza/zoxide" homepage = "https://github.com/ajeetdsouza/zoxide"
keywords = ["cli", "filesystem", "shell", "tool", "utility"] keywords = ["cli"]
license = "MIT" license = "MIT"
name = "zoxide" name = "zoxide"
readme = "README.md" readme = "README.md"
repository = "https://github.com/ajeetdsouza/zoxide" repository = "https://github.com/ajeetdsouza/zoxide"
rust-version = "1.85.0" rust-version = "1.65"
version = "0.9.8" version = "0.9.1"
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[dependencies] [dependencies]
anyhow = "1.0.32" anyhow = "1.0.32"
askama = { version = "0.14.0", default-features = false, features = [ askama = { version = "0.12.0", default-features = false }
"derive",
"std",
] }
bincode = "1.3.1" bincode = "1.3.1"
clap = { version = "4.3.0", features = ["derive"] } clap = { version = "4.0.0", features = ["derive"] }
color-print = "0.3.4" color-print = "0.3.4"
dirs = "6.0.0" dirs = "5.0.0"
dunce = "1.0.1" dunce = "1.0.1"
fastrand = "2.0.0" fastrand = "1.7.0"
glob = "0.3.0" glob = "0.3.0"
ouroboros = "0.18.3" ouroboros = "0.15.5"
serde = { version = "1.0.116", features = ["derive"] } serde = { version = "1.0.116", features = ["derive"] }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
nix = { version = "0.30.1", default-features = false, features = [ nix = { version = "0.26.1", default-features = false, features = [
"fs", "fs",
"user", "user",
] } ] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
which = "7.0.3" which = "4.2.5"
[build-dependencies] [build-dependencies]
clap = { version = "4.3.0", features = ["derive"] } clap = { version = "4.0.0", features = ["derive"] }
clap_complete = "4.5.50" clap_complete = "4.0.0"
clap_complete_fig = "4.5.2" clap_complete_fig = "4.0.0"
clap_complete_nushell = "4.5.5"
color-print = "0.3.4" color-print = "0.3.4"
[dev-dependencies] [dev-dependencies]
assert_cmd = "2.0.0" assert_cmd = "2.0.0"
rstest = { version = "0.26.0", default-features = false } rstest = { version = "0.17.0", default-features = false }
rstest_reuse = "0.7.0" rstest_reuse = "0.5.0"
tempfile = "3.15.0" tempfile = "3.1.0"
[features] [features]
default = [] default = []

187
README.md
View File

@ -9,20 +9,6 @@
<div align="center"> <div align="center">
<sup>Special thanks to:</sup>
<!-- markdownlint-disable-next-line MD013 -->
<div><a href="https://go.warp.dev/zoxide"><img alt="Sponsored by Warp" width="230" src="https://raw.githubusercontent.com/warpdotdev/brand-assets/refs/heads/main/Github/Sponsor/Warp-Github-LG-03.png" /></a></div>
<div><sup><b>Warp, built for coding with multiple AI agents.</b></sup></div>
<div><sup>Available for macOS, Linux, and Windows.</sup></div>
<div><sup>
Visit
<a href="https://go.warp.dev/zoxide"><u>warp.dev</u></a>
to learn more.
</sup></div>
<hr />
# zoxide # zoxide
[![crates.io][crates.io-badge]][crates.io] [![crates.io][crates.io-badge]][crates.io]
@ -73,45 +59,37 @@ zoxide can be installed in 4 easy steps:
please [open an issue][issues]. please [open an issue][issues].
<details> <details>
<summary>Linux / WSL</summary> <summary>Linux</summary>
> The recommended way to install zoxide is via the install script: > The recommended way to install zoxide is via the install script:
> >
> ```sh > ```sh
> curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh > curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
> ``` > ```
> >
> Or, you can use a package manager: > Or, you can use a package manager:
> >
> | Distribution | Repository | Instructions | > | Distribution | Repository | Instructions |
> | ------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------- | > | ------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- |
> | **_Any_** | **[crates.io]** | `cargo install zoxide --locked` | > | **_Any_** | **[crates.io]** | `cargo install zoxide --locked` |
> | _Any_ | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git` <br /> `asdf install zoxide latest` | > | _Any_ | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git` <br /> `asdf install zoxide latest` |
> | _Any_ | [conda-forge] | `conda install -c conda-forge zoxide` | > | _Any_ | [conda-forge] | `conda install -c conda-forge zoxide` |
> | _Any_ | [guix] | `guix install zoxide` | > | _Any_ | [Linuxbrew] | `brew install zoxide` |
> | _Any_ | [Linuxbrew] | `brew install zoxide` | > | Alpine Linux 3.13+ | [Alpine Linux Packages] | `apk add zoxide` |
> | _Any_ | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` | > | Arch Linux | [Arch Linux Community] | `pacman -S zoxide` |
> | AlmaLinux | | `dnf install zoxide` | > | CentOS 7+ | [Copr] | `dnf copr enable atim/zoxide` <br /> `dnf install zoxide` |
> | Alpine Linux 3.13+ | [Alpine Linux Packages] | `apk add zoxide` | > | Debian 11+[^1] | [Debian Packages] | `apt install zoxide` |
> | Arch Linux | [Arch Linux Extra] | `pacman -S zoxide` | > | Devuan 4.0+[^1] | [Devuan Packages] | `apt install zoxide` |
> | CentOS Stream | | `dnf install zoxide` | > | Fedora 32+ | [Fedora Packages] | `dnf install zoxide` |
> | ~Debian 11+~[^1] | ~[Debian Packages]~ | ~`apt install zoxide`~ | > | Gentoo | [GURU Overlay] | `eselect repository enable guru` <br /> `emerge --sync guru` <br /> `emerge app-shells/zoxide` |
> | Devuan 4.0+ | [Devuan Packages] | `apt install zoxide` | > | Manjaro | | `pacman -S zoxide` |
> | Exherbo Linux | [Exherbo packages] | `cave resolve -x repository/rust` <br /> `cave resolve -x zoxide` | > | NixOS 21.05+ | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
> | Fedora 32+ | [Fedora Packages] | `dnf install zoxide` | > | openSUSE Tumbleweed | [openSUSE Factory] | `zypper install zoxide` |
> | Gentoo | [Gentoo Packages] | `emerge app-shells/zoxide` | > | Parrot OS[^1] | | `apt install zoxide` |
> | Linux Mint | [apt.cli.rs] (unofficial) | [Setup the repository][apt.cli.rs-setup], then `apt install zoxide` | > | Raspbian 11+[^1] | [Raspbian Packages] | `apt install zoxide` |
> | Manjaro | | `pacman -S zoxide` | > | Slackware 15.0+ | [SlackBuilds] | [Instructions][slackbuilds-howto] |
> | openSUSE Tumbleweed | [openSUSE Factory] | `zypper install zoxide` | > | Ubuntu 21.04+[^1] | [Ubuntu Packages] | `apt install zoxide` |
> | ~Parrot OS~[^1] | | ~`apt install zoxide`~ | > | Void Linux | [Void Linux Packages] | `xbps-install -S zoxide` |
> | ~Raspbian 11+~[^1] | ~[Raspbian Packages]~ | ~`apt install zoxide`~ |
> | RHEL 8+ | | `dnf install zoxide` |
> | Rhino Linux | [Pacstall Packages] | `pacstall -I zoxide-deb` |
> | Rocky Linux | | `dnf install zoxide` |
> | Slackware 15.0+ | [SlackBuilds] | [Instructions][slackbuilds-howto] |
> | Solus | [Solus Packages] | `eopkg install zoxide` |
> | Ubuntu | [apt.cli.rs] (unofficial) | [Setup the repository][apt.cli.rs-setup], then `apt install zoxide` |
> | Void Linux | [Void Linux Packages] | `xbps-install -S zoxide` |
</details> </details>
@ -127,12 +105,11 @@ zoxide can be installed in 4 easy steps:
> | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git` <br /> `asdf install zoxide latest` | > | [asdf] | `asdf plugin add zoxide https://github.com/nyrst/asdf-zoxide.git` <br /> `asdf install zoxide latest` |
> | [conda-forge] | `conda install -c conda-forge zoxide` | > | [conda-forge] | `conda install -c conda-forge zoxide` |
> | [MacPorts] | `port install zoxide` | > | [MacPorts] | `port install zoxide` |
> | [nixpkgs] | `nix-env -iA nixpkgs.zoxide` |
> >
> Or, run this command in your terminal: > Or, run this command in your terminal:
> >
> ```sh > ```sh
> curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh > curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
> ``` > ```
</details> </details>
@ -140,13 +117,10 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Windows</summary> <summary>Windows</summary>
> zoxide works with PowerShell, as well as shells running in Cygwin, Git
> Bash, and MSYS2.
>
> The recommended way to install zoxide is via `winget`: > The recommended way to install zoxide is via `winget`:
> >
> ```sh > ```sh
> winget install ajeetdsouza.zoxide > winget install zoxide
> ``` > ```
> >
> Or, you can use an alternative package manager: > Or, you can use an alternative package manager:
@ -158,10 +132,10 @@ zoxide can be installed in 4 easy steps:
> | [conda-forge] | `conda install -c conda-forge zoxide` | > | [conda-forge] | `conda install -c conda-forge zoxide` |
> | [Scoop] | `scoop install zoxide` | > | [Scoop] | `scoop install zoxide` |
> >
> If you're using Cygwin, Git Bash, or MSYS2, you can also use the install script: > If you're using Cygwin, Git Bash, or MSYS2, use the install script instead:
> >
> ```sh > ```sh
> curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh > curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
> ``` > ```
</details> </details>
@ -177,12 +151,6 @@ zoxide can be installed in 4 easy steps:
> | DragonFly BSD | [DPorts] | `pkg install zoxide` | > | DragonFly BSD | [DPorts] | `pkg install zoxide` |
> | FreeBSD | [FreshPorts] | `pkg install zoxide` | > | FreeBSD | [FreshPorts] | `pkg install zoxide` |
> | NetBSD | [pkgsrc] | `pkgin install zoxide` | > | NetBSD | [pkgsrc] | `pkgin install zoxide` |
>
> Or, run this command in your terminal:
>
> ```sh
> curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
> ```
</details> </details>
@ -194,12 +162,6 @@ zoxide can be installed in 4 easy steps:
> | Repository | Instructions | > | Repository | Instructions |
> | ---------- | -------------------- | > | ---------- | -------------------- |
> | [Termux] | `pkg install zoxide` | > | [Termux] | `pkg install zoxide` |
>
> Or, run this command in your terminal:
>
> ```sh
> curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
> ```
</details> </details>
@ -210,7 +172,7 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Bash</summary> <summary>Bash</summary>
> Add this to the <ins>**end**</ins> of your config file (usually `~/.bashrc`): > Add this to your configuration (usually `~/.bashrc`):
> >
> ```sh > ```sh
> eval "$(zoxide init bash)" > eval "$(zoxide init bash)"
@ -221,7 +183,7 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Elvish</summary> <summary>Elvish</summary>
> Add this to the <ins>**end**</ins> of your config file (usually `~/.elvish/rc.elv`): > Add this to your configuration (usually `~/.elvish/rc.elv`):
> >
> ```sh > ```sh
> eval (zoxide init elvish | slurp) > eval (zoxide init elvish | slurp)
@ -235,10 +197,9 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Fish</summary> <summary>Fish</summary>
> Add this to the <ins>**end**</ins> of your config file (usually > Add this to your configuration (usually `~/.config/fish/config.fish`):
> `~/.config/fish/config.fish`):
> >
> ```sh > ```fish
> zoxide init fish | source > zoxide init fish | source
> ``` > ```
@ -247,14 +208,13 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Nushell</summary> <summary>Nushell</summary>
> Add this to the <ins>**end**</ins> of your env file (find it by running `$nu.env-path` > Add this to your env file (find it by running `$nu.env-path` in Nushell):
> in Nushell):
> >
> ```sh > ```sh
> zoxide init nushell | save -f ~/.zoxide.nu > zoxide init nushell | save -f ~/.zoxide.nu
> ``` > ```
> >
> Now, add this to the <ins>**end**</ins> of your config file (find it by running > Now, add this to the end of your config file (find it by running
> `$nu.config-path` in Nushell): > `$nu.config-path` in Nushell):
> >
> ```sh > ```sh
@ -262,15 +222,15 @@ zoxide can be installed in 4 easy steps:
> ``` > ```
> >
> **Note** > **Note**
> zoxide only supports Nushell v0.89.0+. > zoxide only supports Nushell v0.73.0 and above.
</details> </details>
<details> <details>
<summary>PowerShell</summary> <summary>PowerShell</summary>
> Add this to the <ins>**end**</ins> of your config file (find it by running > Add this to your configuration (find it by running `echo $profile` in
> `echo $profile` in PowerShell): > PowerShell):
> >
> ```powershell > ```powershell
> Invoke-Expression (& { (zoxide init powershell | Out-String) }) > Invoke-Expression (& { (zoxide init powershell | Out-String) })
@ -278,22 +238,10 @@ zoxide can be installed in 4 easy steps:
</details> </details>
<details>
<summary>Tcsh</summary>
> Add this to the <ins>**end**</ins> of your config file (usually `~/.tcshrc`):
>
> ```sh
> zoxide init tcsh > ~/.zoxide.tcsh
> source ~/.zoxide.tcsh
> ```
</details>
<details> <details>
<summary>Xonsh</summary> <summary>Xonsh</summary>
> Add this to the <ins>**end**</ins> of your config file (usually `~/.xonshrc`): > Add this to your configuration (usually `~/.xonshrc`):
> >
> ```python > ```python
> execx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide') > execx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide')
@ -304,7 +252,7 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Zsh</summary> <summary>Zsh</summary>
> Add this to the <ins>**end**</ins> of your config file (usually `~/.zshrc`): > Add this to your configuration (usually `~/.zshrc`):
> >
> ```sh > ```sh
> eval "$(zoxide init zsh)" > eval "$(zoxide init zsh)"
@ -319,7 +267,7 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Any POSIX shell</summary> <summary>Any POSIX shell</summary>
> Add this to the <ins>**end**</ins> of your config file: > Add this to your configuration:
> >
> ```sh > ```sh
> eval "$(zoxide init posix --hook prompt)" > eval "$(zoxide init posix --hook prompt)"
@ -333,7 +281,7 @@ zoxide can be installed in 4 easy steps:
interactive selection. It can be installed from [here][fzf-installation]. interactive selection. It can be installed from [here][fzf-installation].
> **Note** > **Note**
> The minimum supported fzf version is v0.51.0. > zoxide only supports fzf v0.33.0 and above.
4. **Import your data** <sup>(optional)</sup> 4. **Import your data** <sup>(optional)</sup>
@ -403,16 +351,14 @@ When calling `zoxide init`, the following flags are available:
- `--cmd` - `--cmd`
- Changes the prefix of the `z` and `zi` commands. - Changes the prefix of the `z` and `zi` commands.
- `--cmd j` would change the commands to (`j`, `ji`). - `--cmd j` would change the commands to (`j`, `ji`).
- `--cmd cd` would replace the `cd` command. - `--cmd cd` would replace the `cd` command (doesn't work on Nushell / POSIX shells).
- `--hook <HOOK>` - `--hook <HOOK>`
- Changes how often zoxide increments a directory's score: - Changes how often zoxide increments a directory's score:
| Hook | Description |
| Hook | Description | | -------- | --------------------------------- |
| --------------- | --------------------------------- | | `none` | Never |
| `none` | Never | | `prompt` | At every shell prompt |
| `prompt` | At every shell prompt | | `pwd` | Whenever the directory is changed |
| `pwd` (default) | Whenever the directory is changed |
- `--no-cmd` - `--no-cmd`
- Prevents zoxide from defining the `z` and `zi` commands. - Prevents zoxide from defining the `z` and `zi` commands.
- These functions will still be available in your shell as `__zoxide_z` and - These functions will still be available in your shell as `__zoxide_z` and
@ -426,13 +372,11 @@ Environment variables[^2] can be used for configuration. They must be set before
- `_ZO_DATA_DIR` - `_ZO_DATA_DIR`
- Specifies the directory in which the database is stored. - Specifies the directory in which the database is stored.
- The default value varies across OSes: - The default value varies across OSes:
| OS | Path | Example | | OS | Path | Example |
| ----------- | ---------------------------------------- | ------------------------------------------ | | ----------- | ---------------------------------------- | ------------------------------------------ |
| Linux / BSD | `$XDG_DATA_HOME` or `$HOME/.local/share` | `/home/alice/.local/share` | | Linux / BSD | `$XDG_DATA_HOME` or `$HOME/.local/share` | `/home/alice/.local/share` |
| macOS | `$HOME/Library/Application Support` | `/Users/Alice/Library/Application Support` | | macOS | `$HOME/Library/Application Support` | `/Users/Alice/Library/Application Support` |
| Windows | `%LOCALAPPDATA%` | `C:\Users\Alice\AppData\Local` | | Windows | `%LOCALAPPDATA%` | `C:\Users\Alice\AppData\Local` |
- `_ZO_ECHO` - `_ZO_ECHO`
- When set to 1, `z` will print the matched directory before navigating to - When set to 1, `z` will print the matched directory before navigating to
it. it.
@ -440,12 +384,10 @@ Environment variables[^2] can be used for configuration. They must be set before
- Excludes the specified directories from the database. - Excludes the specified directories from the database.
- This is provided as a list of [globs][glob], separated by OS-specific - This is provided as a list of [globs][glob], separated by OS-specific
characters: characters:
| OS | Separator | Example | | OS | Separator | Example |
| ------------------- | --------- | ----------------------- | | ------------------- | --------- | ----------------------- |
| Linux / macOS / BSD | `:` | `$HOME:$HOME/private/*` | | Linux / macOS / BSD | `:` | `$HOME:$HOME/private/*` |
| Windows | `;` | `$HOME;$HOME/private/*` | | Windows | `;` | `$HOME;$HOME/private/*` |
- By default, this is set to `"$HOME"`. - By default, this is set to `"$HOME"`.
- `_ZO_FZF_OPTS` - `_ZO_FZF_OPTS`
- Custom options to pass to [fzf] during interactive selection. See - Custom options to pass to [fzf] during interactive selection. See
@ -462,8 +404,6 @@ Environment variables[^2] can be used for configuration. They must be set before
| Application | Description | Plugin | | Application | Description | Plugin |
| --------------------- | -------------------------------------------- | -------------------------- | | --------------------- | -------------------------------------------- | -------------------------- |
| [aerc] | Email client | Natively supported |
| [alfred] | macOS launcher | [alfred-zoxide] |
| [clink] | Improved cmd.exe for Windows | [clink-zoxide] | | [clink] | Improved cmd.exe for Windows | [clink-zoxide] |
| [emacs] | Text editor | [zoxide.el] | | [emacs] | Text editor | [zoxide.el] |
| [felix] | File manager | Natively supported | | [felix] | File manager | Natively supported |
@ -471,37 +411,27 @@ Environment variables[^2] can be used for configuration. They must be set before
| [lf] | File manager | See the [wiki][lf-wiki] | | [lf] | File manager | See the [wiki][lf-wiki] |
| [nnn] | File manager | [nnn-autojump] | | [nnn] | File manager | [nnn-autojump] |
| [ranger] | File manager | [ranger-zoxide] | | [ranger] | File manager | [ranger-zoxide] |
| [raycast] | macOS launcher | [raycast-zoxide] |
| [rfm] | File manager | Natively supported |
| [sesh] | `tmux` session manager | Natively supported |
| [telescope.nvim] | Fuzzy finder for Neovim | [telescope-zoxide] | | [telescope.nvim] | Fuzzy finder for Neovim | [telescope-zoxide] |
| [t] | `tmux` session manager | Natively supported |
| [tmux-session-wizard] | `tmux` session manager | Natively supported | | [tmux-session-wizard] | `tmux` session manager | Natively supported |
| [tmux-sessionx] | `tmux` session manager | Natively supported |
| [vim] / [neovim] | Text editor | [zoxide.vim] | | [vim] / [neovim] | Text editor | [zoxide.vim] |
| [xplr] | File manager | [zoxide.xplr] | | [xplr] | File manager | [zoxide.xplr] |
| [xxh] | Transports shell configuration over SSH | [xxh-plugin-prerun-zoxide] | | [xxh] | Transports shell configuration over SSH | [xxh-plugin-prerun-zoxide] |
| [yazi] | File manager | Natively supported |
| [zabb] | Finds the shortest possible query for a path | Natively supported | | [zabb] | Finds the shortest possible query for a path | Natively supported |
| [zesh] | `zellij` session manager | Natively supported |
| [zsh-autocomplete] | Realtime completions for zsh | Natively supported | | [zsh-autocomplete] | Realtime completions for zsh | Natively supported |
[^1]: [^1]:
Debian and its derivatives update their packages very slowly. If you're Debian / Ubuntu derivatives update their packages very slowly. If you're
using one of these distributions, consider using the install script instead. using one of these distributions, consider using the install script instead.
[^2]: [^2]:
If you're not sure how to set an environment variable on your shell, check If you're not sure how to set an environment variable on your shell, check
out the [wiki][wiki-env]. out the [wiki][wiki-env].
[aerc]: https://github.com/rjarry/aerc
[alfred]: https://www.alfredapp.com/
[alfred-zoxide]: https://github.com/yihou/alfred-zoxide
[algorithm-aging]: https://github.com/ajeetdsouza/zoxide/wiki/Algorithm#aging [algorithm-aging]: https://github.com/ajeetdsouza/zoxide/wiki/Algorithm#aging
[algorithm-matching]: https://github.com/ajeetdsouza/zoxide/wiki/Algorithm#matching [algorithm-matching]: https://github.com/ajeetdsouza/zoxide/wiki/Algorithm#matching
[alpine linux packages]: https://pkgs.alpinelinux.org/packages?name=zoxide [alpine linux packages]: https://pkgs.alpinelinux.org/packages?name=zoxide
[apt.cli.rs]: https://apt.cli.rs/ [arch linux community]: https://archlinux.org/packages/community/x86_64/zoxide/
[apt.cli.rs-setup]: https://github.com/emmatyping/apt.cli.rs#how-to-add-the-repo
[arch linux extra]: https://archlinux.org/packages/extra/x86_64/zoxide/
[asdf]: https://github.com/asdf-vm/asdf [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-badge]: https://img.shields.io/badge/builtwith-nix-7d81f7?logo=nixos&logoColor=white&style=flat-square
[builtwithnix]: https://builtwithnix.org/ [builtwithnix]: https://builtwithnix.org/
@ -509,10 +439,10 @@ Environment variables[^2] can be used for configuration. They must be set before
[clink-zoxide]: https://github.com/shunsambongi/clink-zoxide [clink-zoxide]: https://github.com/shunsambongi/clink-zoxide
[clink]: https://github.com/mridgers/clink [clink]: https://github.com/mridgers/clink
[conda-forge]: https://anaconda.org/conda-forge/zoxide [conda-forge]: https://anaconda.org/conda-forge/zoxide
[copr]: https://copr.fedorainfracloud.org/coprs/atim/zoxide/
[crates.io-badge]: https://img.shields.io/crates/v/zoxide?logo=rust&logoColor=white&style=flat-square [crates.io-badge]: https://img.shields.io/crates/v/zoxide?logo=rust&logoColor=white&style=flat-square
[crates.io]: https://crates.io/crates/zoxide [crates.io]: https://crates.io/crates/zoxide
[debian packages]: https://packages.debian.org/stable/admin/zoxide [debian packages]: https://packages.debian.org/stable/admin/zoxide
[exherbo packages]: https://gitlab.exherbo.org/exherbo/rust/-/tree/master/packages/sys-apps/zoxide
[devuan packages]: https://pkginfo.devuan.org/cgi-bin/package-query.html?c=package&q=zoxide [devuan packages]: https://pkginfo.devuan.org/cgi-bin/package-query.html?c=package&q=zoxide
[downloads-badge]: https://img.shields.io/github/downloads/ajeetdsouza/zoxide/total?logo=github&logoColor=white&style=flat-square [downloads-badge]: https://img.shields.io/github/downloads/ajeetdsouza/zoxide/total?logo=github&logoColor=white&style=flat-square
[dports]: https://github.com/DragonFlyBSD/DPorts/tree/master/sysutils/zoxide [dports]: https://github.com/DragonFlyBSD/DPorts/tree/master/sysutils/zoxide
@ -523,9 +453,8 @@ Environment variables[^2] can be used for configuration. They must be set before
[fzf-installation]: https://github.com/junegunn/fzf#installation [fzf-installation]: https://github.com/junegunn/fzf#installation
[fzf-man]: https://manpages.ubuntu.com/manpages/en/man1/fzf.1.html [fzf-man]: https://manpages.ubuntu.com/manpages/en/man1/fzf.1.html
[fzf]: https://github.com/junegunn/fzf [fzf]: https://github.com/junegunn/fzf
[gentoo packages]: https://packages.gentoo.org/packages/app-shells/zoxide
[glob]: https://man7.org/linux/man-pages/man7/glob.7.html [glob]: https://man7.org/linux/man-pages/man7/glob.7.html
[guix]: https://packages.guix.gnu.org/packages/zoxide/ [guru overlay]: https://github.com/gentoo-mirror/guru
[homebrew]: https://formulae.brew.sh/formula/zoxide [homebrew]: https://formulae.brew.sh/formula/zoxide
[issues]: https://github.com/ajeetdsouza/zoxide/issues/new [issues]: https://github.com/ajeetdsouza/zoxide/issues/new
[joshuto]: https://github.com/kamiyaa/joshuto [joshuto]: https://github.com/kamiyaa/joshuto
@ -534,39 +463,31 @@ Environment variables[^2] can be used for configuration. They must be set before
[linuxbrew]: https://formulae.brew.sh/formula-linux/zoxide [linuxbrew]: https://formulae.brew.sh/formula-linux/zoxide
[macports]: https://ports.macports.org/port/zoxide/summary [macports]: https://ports.macports.org/port/zoxide/summary
[neovim]: https://github.com/neovim/neovim [neovim]: https://github.com/neovim/neovim
[nixpkgs]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/zo/zoxide/package.nix [nixpkgs]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/zoxide/default.nix
[nnn-autojump]: https://github.com/jarun/nnn/blob/master/plugins/autojump [nnn-autojump]: https://github.com/jarun/nnn/blob/master/plugins/autojump
[nnn]: https://github.com/jarun/nnn [nnn]: https://github.com/jarun/nnn
[opensuse factory]: https://build.opensuse.org/package/show/openSUSE:Factory/zoxide [opensuse factory]: https://build.opensuse.org/package/show/openSUSE:Factory/zoxide
[pacstall packages]: https://pacstall.dev/packages/zoxide-deb
[pkgsrc]: https://pkgsrc.se/sysutils/zoxide [pkgsrc]: https://pkgsrc.se/sysutils/zoxide
[ranger-zoxide]: https://github.com/jchook/ranger-zoxide [ranger-zoxide]: https://github.com/jchook/ranger-zoxide
[ranger]: https://github.com/ranger/ranger [ranger]: https://github.com/ranger/ranger
[raspbian packages]: https://archive.raspbian.org/raspbian/pool/main/r/rust-zoxide/ [raspbian packages]: https://archive.raspbian.org/raspbian/pool/main/r/rust-zoxide/
[raycast]: https://www.raycast.com/
[raycast-zoxide]: https://www.raycast.com/mrpunkin/raycast-zoxide
[releases]: https://github.com/ajeetdsouza/zoxide/releases [releases]: https://github.com/ajeetdsouza/zoxide/releases
[rfm]: https://github.com/dsxmachina/rfm
[scoop]: https://github.com/ScoopInstaller/Main/tree/master/bucket/zoxide.json [scoop]: https://github.com/ScoopInstaller/Main/tree/master/bucket/zoxide.json
[sesh]: https://github.com/joshmedeski/sesh
[slackbuilds]: https://slackbuilds.org/repository/15.0/system/zoxide/
[slackbuilds-howto]: https://slackbuilds.org/howto/ [slackbuilds-howto]: https://slackbuilds.org/howto/
[solus packages]: https://github.com/getsolus/packages/tree/main/packages/z/zoxide/ [t]: https://github.com/joshmedeski/t-smart-tmux-session-manager
[telescope-zoxide]: https://github.com/jvgrootveld/telescope-zoxide [telescope-zoxide]: https://github.com/jvgrootveld/telescope-zoxide
[telescope.nvim]: https://github.com/nvim-telescope/telescope.nvim [telescope.nvim]: https://github.com/nvim-telescope/telescope.nvim
[termux]: https://github.com/termux/termux-packages/tree/master/packages/zoxide [termux]: https://github.com/termux/termux-packages/tree/master/packages/zoxide
[tmux-session-wizard]: https://github.com/27medkamal/tmux-session-wizard [tmux-session-wizard]: https://github.com/27medkamal/tmux-session-wizard
[tmux-sessionx]: https://github.com/omerxx/tmux-sessionx
[tutorial]: contrib/tutorial.webp [tutorial]: contrib/tutorial.webp
[ubuntu packages]: https://packages.ubuntu.com/jammy/zoxide
[vim]: https://github.com/vim/vim [vim]: https://github.com/vim/vim
[void linux packages]: https://github.com/void-linux/void-packages/tree/master/srcpkgs/zoxide [void linux packages]: https://github.com/void-linux/void-packages/tree/master/srcpkgs/zoxide
[wiki-env]: https://github.com/ajeetdsouza/zoxide/wiki/HOWTO:-set-environment-variables "HOWTO: set environment variables" [wiki-env]: https://github.com/ajeetdsouza/zoxide/wiki/HOWTO:-set-environment-variables "HOWTO: set environment variables"
[xplr]: https://github.com/sayanarijit/xplr [xplr]: https://github.com/sayanarijit/xplr
[xxh-plugin-prerun-zoxide]: https://github.com/xxh/xxh-plugin-prerun-zoxide [xxh-plugin-prerun-zoxide]: https://github.com/xxh/xxh-plugin-prerun-zoxide
[xxh]: https://github.com/xxh/xxh [xxh]: https://github.com/xxh/xxh
[yazi]: https://github.com/sxyazi/yazi
[zabb]: https://github.com/Mellbourn/zabb [zabb]: https://github.com/Mellbourn/zabb
[zesh]: https://github.com/roberte777/zesh
[zoxide.el]: https://gitlab.com/Vonfry/zoxide.el [zoxide.el]: https://gitlab.com/Vonfry/zoxide.el
[zoxide.vim]: https://github.com/nanotee/zoxide.vim [zoxide.vim]: https://github.com/nanotee/zoxide.vim
[zoxide.xplr]: https://github.com/sayanarijit/zoxide.xplr [zoxide.xplr]: https://github.com/sayanarijit/zoxide.xplr

View File

@ -1,36 +1,56 @@
#[path = "src/cmd/cmd.rs"] use std::process::Command;
mod cmd;
use std::{env, io}; use std::{env, io};
use clap::CommandFactory as _; fn main() {
use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; let pkg_version = env!("CARGO_PKG_VERSION");
use clap_complete_fig::Fig; let version = match env::var_os("PROFILE") {
use clap_complete_nushell::Nushell; Some(profile) if profile == "release" => format!("v{pkg_version}"),
use cmd::Cmd; _ => git_version().unwrap_or_else(|| format!("v{pkg_version}-unknown")),
};
println!("cargo:rustc-env=ZOXIDE_VERSION={version}");
fn main() -> io::Result<()> { // Since we are generating completions in the package directory, we need to set
// Since we are generating completions in the package directory, we need to // this so that Cargo doesn't rebuild every time.
// set this so that Cargo doesn't rebuild every time.
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/"); println!("cargo:rerun-if-changed=src/");
println!("cargo:rerun-if-changed=templates/"); println!("cargo:rerun-if-changed=templates/");
println!("cargo:rerun-if-changed=tests/"); println!("cargo:rerun-if-changed=tests/");
generate_completions()
generate_completions().unwrap();
}
fn git_version() -> Option<String> {
let dir = env!("CARGO_MANIFEST_DIR");
let mut git = Command::new("git");
git.args(["-C", dir, "describe", "--tags", "--match=v*.*.*", "--always", "--broken"]);
let output = git.output().ok()?;
if !output.status.success() || output.stdout.is_empty() || !output.stderr.is_empty() {
return None;
}
String::from_utf8(output.stdout).ok()
} }
fn generate_completions() -> io::Result<()> { fn generate_completions() -> io::Result<()> {
const BIN_NAME: &str = env!("CARGO_PKG_NAME"); #[path = "src/cmd/cmd.rs"]
const OUT_DIR: &str = "contrib/completions"; mod cmd;
let cmd = &mut Cmd::command();
clap_complete::generate_to(Bash, cmd, BIN_NAME, OUT_DIR)?; use clap::CommandFactory;
clap_complete::generate_to(Elvish, cmd, BIN_NAME, OUT_DIR)?; use clap_complete::generate_to;
clap_complete::generate_to(Fig, cmd, BIN_NAME, OUT_DIR)?; use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh};
clap_complete::generate_to(Fish, cmd, BIN_NAME, OUT_DIR)?; use clap_complete_fig::Fig;
clap_complete::generate_to(Nushell, cmd, BIN_NAME, OUT_DIR)?; use cmd::Cmd;
clap_complete::generate_to(PowerShell, cmd, BIN_NAME, OUT_DIR)?;
clap_complete::generate_to(Zsh, cmd, BIN_NAME, OUT_DIR)?; let cmd = &mut Cmd::command();
let bin_name = env!("CARGO_PKG_NAME");
let out_dir = "contrib/completions";
generate_to(Bash, cmd, bin_name, out_dir)?;
generate_to(Elvish, cmd, bin_name, out_dir)?;
generate_to(Fig, cmd, bin_name, out_dir)?;
generate_to(Fish, cmd, bin_name, out_dir)?;
generate_to(PowerShell, cmd, bin_name, out_dir)?;
generate_to(Zsh, cmd, bin_name, out_dir)?;
Ok(()) Ok(())
} }

View File

@ -14,7 +14,7 @@ _zoxide() {
fi fi
local context curcontext="$curcontext" state line local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
@ -29,9 +29,7 @@ _zoxide() {
curcontext="${curcontext%:*:*}:zoxide-command-$line[1]:" curcontext="${curcontext%:*:*}:zoxide-command-$line[1]:"
case $line[1] in case $line[1] in
(add) (add)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-s+[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \
'--score=[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
@ -40,7 +38,7 @@ _arguments "${_arguments_options[@]}" : \
&& ret=0 && ret=0
;; ;;
(edit) (edit)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
@ -56,34 +54,34 @@ _arguments "${_arguments_options[@]}" : \
curcontext="${curcontext%:*:*}:zoxide-edit-command-$line[1]:" curcontext="${curcontext%:*:*}:zoxide-edit-command-$line[1]:"
case $line[1] in case $line[1] in
(decrement) (decrement)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
':path:_default' \ ':path:' \
&& ret=0 && ret=0
;; ;;
(delete) (delete)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
':path:_default' \ ':path:' \
&& ret=0 && ret=0
;; ;;
(increment) (increment)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
':path:_default' \ ':path:' \
&& ret=0 && ret=0
;; ;;
(reload) (reload)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
@ -95,7 +93,7 @@ _arguments "${_arguments_options[@]}" : \
esac esac
;; ;;
(import) (import)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'--from=[Application to import from]:FROM:(autojump z)' \ '--from=[Application to import from]:FROM:(autojump z)' \
'--merge[Merge into existing database]' \ '--merge[Merge into existing database]' \
'-h[Print help]' \ '-h[Print help]' \
@ -106,23 +104,21 @@ _arguments "${_arguments_options[@]}" : \
&& ret=0 && ret=0
;; ;;
(init) (init)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'--cmd=[Changes the prefix of the \`z\` and \`zi\` commands]:CMD:_default' \ '--cmd=[Changes the prefix of the \`z\` and \`zi\` commands]:CMD: ' \
'--hook=[Changes how often zoxide increments a directory'\''s score]:HOOK:(none prompt pwd)' \ '--hook=[Changes how often zoxide increments a directory'\''s score]:HOOK:(none prompt pwd)' \
'--no-cmd[Prevents zoxide from defining the \`z\` and \`zi\` commands]' \ '--no-cmd[Prevents zoxide from defining the \`z\` and \`zi\` commands]' \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
':shell:(bash elvish fish nushell posix powershell tcsh xonsh zsh)' \ ':shell:(bash elvish fish nushell posix powershell xonsh zsh)' \
&& ret=0 && ret=0
;; ;;
(query) (query)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'--exclude=[Exclude the current directory]:path:_files -/' \ '--exclude=[Exclude the current directory]:path:_files -/' \
'--base-dir=[Only search within this directory]:path:_files -/' \ '--all[Show deleted directories]' \
'-a[Show unavailable directories]' \
'--all[Show unavailable directories]' \
'(-l --list)-i[Use interactive selection]' \ '(-l --list)-i[Use interactive selection]' \
'(-l --list)--interactive[Use interactive selection]' \ '(-l --list)--interactive[Use interactive selection]' \
'(-i --interactive)-l[List all matching directories]' \ '(-i --interactive)-l[List all matching directories]' \
@ -133,11 +129,11 @@ _arguments "${_arguments_options[@]}" : \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
'*::keywords:_default' \ '*::keywords:' \
&& ret=0 && ret=0
;; ;;
(remove) (remove)
_arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" \
'-h[Print help]' \ '-h[Print help]' \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
@ -167,16 +163,6 @@ _zoxide__add_commands() {
local commands; commands=() local commands; commands=()
_describe -t commands 'zoxide add commands' commands "$@" _describe -t commands 'zoxide add commands' commands "$@"
} }
(( $+functions[_zoxide__edit_commands] )) ||
_zoxide__edit_commands() {
local commands; commands=(
'decrement:' \
'delete:' \
'increment:' \
'reload:' \
)
_describe -t commands 'zoxide edit commands' commands "$@"
}
(( $+functions[_zoxide__edit__decrement_commands] )) || (( $+functions[_zoxide__edit__decrement_commands] )) ||
_zoxide__edit__decrement_commands() { _zoxide__edit__decrement_commands() {
local commands; commands=() local commands; commands=()
@ -187,21 +173,26 @@ _zoxide__edit__delete_commands() {
local commands; commands=() local commands; commands=()
_describe -t commands 'zoxide edit delete commands' commands "$@" _describe -t commands 'zoxide edit delete commands' commands "$@"
} }
(( $+functions[_zoxide__edit__increment_commands] )) || (( $+functions[_zoxide__edit_commands] )) ||
_zoxide__edit__increment_commands() { _zoxide__edit_commands() {
local commands; commands=() local commands; commands=(
_describe -t commands 'zoxide edit increment commands' commands "$@" 'decrement:' \
} 'delete:' \
(( $+functions[_zoxide__edit__reload_commands] )) || 'increment:' \
_zoxide__edit__reload_commands() { 'reload:' \
local commands; commands=() )
_describe -t commands 'zoxide edit reload commands' commands "$@" _describe -t commands 'zoxide edit commands' commands "$@"
} }
(( $+functions[_zoxide__import_commands] )) || (( $+functions[_zoxide__import_commands] )) ||
_zoxide__import_commands() { _zoxide__import_commands() {
local commands; commands=() local commands; commands=()
_describe -t commands 'zoxide import commands' commands "$@" _describe -t commands 'zoxide import commands' commands "$@"
} }
(( $+functions[_zoxide__edit__increment_commands] )) ||
_zoxide__edit__increment_commands() {
local commands; commands=()
_describe -t commands 'zoxide edit increment commands' commands "$@"
}
(( $+functions[_zoxide__init_commands] )) || (( $+functions[_zoxide__init_commands] )) ||
_zoxide__init_commands() { _zoxide__init_commands() {
local commands; commands=() local commands; commands=()
@ -212,6 +203,11 @@ _zoxide__query_commands() {
local commands; commands=() local commands; commands=()
_describe -t commands 'zoxide query commands' commands "$@" _describe -t commands 'zoxide query commands' commands "$@"
} }
(( $+functions[_zoxide__edit__reload_commands] )) ||
_zoxide__edit__reload_commands() {
local commands; commands=()
_describe -t commands 'zoxide edit reload commands' commands "$@"
}
(( $+functions[_zoxide__remove_commands] )) || (( $+functions[_zoxide__remove_commands] )) ||
_zoxide__remove_commands() { _zoxide__remove_commands() {
local commands; commands=() local commands; commands=()

View File

@ -21,10 +21,10 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
$completions = @(switch ($command) { $completions = @(switch ($command) {
'zoxide' { 'zoxide' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Add a new directory or increment its rank') [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Add a new directory or increment its rank')
[CompletionResult]::new('edit', 'edit', [CompletionResultType]::ParameterValue, 'Edit the database') [CompletionResult]::new('edit', 'edit', [CompletionResultType]::ParameterValue, 'Edit the database')
[CompletionResult]::new('import', 'import', [CompletionResultType]::ParameterValue, 'Import entries from another application') [CompletionResult]::new('import', 'import', [CompletionResultType]::ParameterValue, 'Import entries from another application')
@ -34,19 +34,17 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
break break
} }
'zoxide;add' { 'zoxide;add' {
[CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--score', '--score', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;edit' { 'zoxide;edit' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('decrement', 'decrement', [CompletionResultType]::ParameterValue, 'decrement') [CompletionResult]::new('decrement', 'decrement', [CompletionResultType]::ParameterValue, 'decrement')
[CompletionResult]::new('delete', 'delete', [CompletionResultType]::ParameterValue, 'delete') [CompletionResult]::new('delete', 'delete', [CompletionResultType]::ParameterValue, 'delete')
[CompletionResult]::new('increment', 'increment', [CompletionResultType]::ParameterValue, 'increment') [CompletionResult]::new('increment', 'increment', [CompletionResultType]::ParameterValue, 'increment')
@ -54,74 +52,72 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
break break
} }
'zoxide;edit;decrement' { 'zoxide;edit;decrement' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;edit;delete' { 'zoxide;edit;delete' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;edit;increment' { 'zoxide;edit;increment' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;edit;reload' { 'zoxide;edit;reload' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;import' { 'zoxide;import' {
[CompletionResult]::new('--from', '--from', [CompletionResultType]::ParameterName, 'Application to import from') [CompletionResult]::new('--from', 'from', [CompletionResultType]::ParameterName, 'Application to import from')
[CompletionResult]::new('--merge', '--merge', [CompletionResultType]::ParameterName, 'Merge into existing database') [CompletionResult]::new('--merge', 'merge', [CompletionResultType]::ParameterName, 'Merge into existing database')
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;init' { 'zoxide;init' {
[CompletionResult]::new('--cmd', '--cmd', [CompletionResultType]::ParameterName, 'Changes the prefix of the `z` and `zi` commands') [CompletionResult]::new('--cmd', 'cmd', [CompletionResultType]::ParameterName, 'Changes the prefix of the `z` and `zi` commands')
[CompletionResult]::new('--hook', '--hook', [CompletionResultType]::ParameterName, 'Changes how often zoxide increments a directory''s score') [CompletionResult]::new('--hook', 'hook', [CompletionResultType]::ParameterName, 'Changes how often zoxide increments a directory''s score')
[CompletionResult]::new('--no-cmd', '--no-cmd', [CompletionResultType]::ParameterName, 'Prevents zoxide from defining the `z` and `zi` commands') [CompletionResult]::new('--no-cmd', 'no-cmd', [CompletionResultType]::ParameterName, 'Prevents zoxide from defining the `z` and `zi` commands')
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;query' { 'zoxide;query' {
[CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Exclude the current directory') [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'Exclude the current directory')
[CompletionResult]::new('--base-dir', '--base-dir', [CompletionResultType]::ParameterName, 'Only search within this directory') [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Show deleted directories')
[CompletionResult]::new('-a', '-a', [CompletionResultType]::ParameterName, 'Show unavailable directories') [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Use interactive selection')
[CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'Show unavailable directories') [CompletionResult]::new('--interactive', 'interactive', [CompletionResultType]::ParameterName, 'Use interactive selection')
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'Use interactive selection') [CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'List all matching directories')
[CompletionResult]::new('--interactive', '--interactive', [CompletionResultType]::ParameterName, 'Use interactive selection') [CompletionResult]::new('--list', 'list', [CompletionResultType]::ParameterName, 'List all matching directories')
[CompletionResult]::new('-l', '-l', [CompletionResultType]::ParameterName, 'List all matching directories') [CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Print score with results')
[CompletionResult]::new('--list', '--list', [CompletionResultType]::ParameterName, 'List all matching directories') [CompletionResult]::new('--score', 'score', [CompletionResultType]::ParameterName, 'Print score with results')
[CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'Print score with results') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--score', '--score', [CompletionResultType]::ParameterName, 'Print score with results') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
'zoxide;remove' { 'zoxide;remove' {
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break break
} }
}) })

View File

@ -1,16 +1,12 @@
_zoxide() { _zoxide() {
local i cur prev opts cmd local i cur prev opts cmd
COMPREPLY=() COMPREPLY=()
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then cur="${COMP_WORDS[COMP_CWORD]}"
cur="$2" prev="${COMP_WORDS[COMP_CWORD-1]}"
else
cur="${COMP_WORDS[COMP_CWORD]}"
fi
prev="$3"
cmd="" cmd=""
opts="" opts=""
for i in "${COMP_WORDS[@]:0:COMP_CWORD}" for i in ${COMP_WORDS[@]}
do do
case "${cmd},${i}" in case "${cmd},${i}" in
",$1") ",$1")
@ -67,20 +63,12 @@ _zoxide() {
return 0 return 0
;; ;;
zoxide__add) zoxide__add)
opts="-s -h -V --score --help --version <PATHS>..." opts="-h -V --help --version <PATHS>..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0
fi fi
case "${prev}" in case "${prev}" in
--score)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-s)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*) *)
COMPREPLY=() COMPREPLY=()
;; ;;
@ -177,7 +165,7 @@ _zoxide() {
return 0 return 0
;; ;;
zoxide__init) zoxide__init)
opts="-h -V --no-cmd --cmd --hook --help --version bash elvish fish nushell posix powershell tcsh xonsh zsh" opts="-h -V --no-cmd --cmd --hook --help --version bash elvish fish nushell posix powershell xonsh zsh"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0
@ -199,24 +187,14 @@ _zoxide() {
return 0 return 0
;; ;;
zoxide__query) zoxide__query)
opts="-a -i -l -s -h -V --all --interactive --list --score --exclude --base-dir --help --version [KEYWORDS]..." opts="-i -l -s -h -V --all --interactive --list --score --exclude --help --version [KEYWORDS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0
fi fi
case "${prev}" in case "${prev}" in
--exclude) --exclude)
COMPREPLY=() COMPREPLY=($(compgen -f "${cur}"))
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
compopt -o plusdirs
fi
return 0
;;
--base-dir)
COMPREPLY=()
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
compopt -o plusdirs
fi
return 0 return 0
;; ;;
*) *)
@ -243,8 +221,4 @@ _zoxide() {
esac esac
} }
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then complete -F _zoxide -o bashdefault -o default zoxide
complete -F _zoxide -o nosort -o bashdefault -o default zoxide
else
complete -F _zoxide -o bashdefault -o default zoxide
fi

View File

@ -30,8 +30,6 @@ set edit:completion:arg-completer[zoxide] = {|@words|
cand remove 'Remove a directory from the database' cand remove 'Remove a directory from the database'
} }
&'zoxide;add'= { &'zoxide;add'= {
cand -s 'The rank to increment the entry if it exists or initialize it with if it doesn''t'
cand --score 'The rank to increment the entry if it exists or initialize it with if it doesn''t'
cand -h 'Print help' cand -h 'Print help'
cand --help 'Print help' cand --help 'Print help'
cand -V 'Print version' cand -V 'Print version'
@ -90,9 +88,7 @@ set edit:completion:arg-completer[zoxide] = {|@words|
} }
&'zoxide;query'= { &'zoxide;query'= {
cand --exclude 'Exclude the current directory' cand --exclude 'Exclude the current directory'
cand --base-dir 'Only search within this directory' cand --all 'Show deleted directories'
cand -a 'Show unavailable directories'
cand --all 'Show unavailable directories'
cand -i 'Use interactive selection' cand -i 'Use interactive selection'
cand --interactive 'Use interactive selection' cand --interactive 'Use interactive selection'
cand -l 'List all matching directories' cand -l 'List all matching directories'

View File

@ -1,73 +1,42 @@
# Print an optspec for argparse to handle cmd's options that are independent of any subcommand. complete -c zoxide -n "__fish_use_subcommand" -s h -l help -d 'Print help'
function __fish_zoxide_global_optspecs complete -c zoxide -n "__fish_use_subcommand" -s V -l version -d 'Print version'
string join \n h/help V/version complete -c zoxide -n "__fish_use_subcommand" -f -a "add" -d 'Add a new directory or increment its rank'
end complete -c zoxide -n "__fish_use_subcommand" -f -a "edit" -d 'Edit the database'
complete -c zoxide -n "__fish_use_subcommand" -f -a "import" -d 'Import entries from another application'
function __fish_zoxide_needs_command complete -c zoxide -n "__fish_use_subcommand" -f -a "init" -d 'Generate shell configuration'
# Figure out if the current invocation already has a command. complete -c zoxide -n "__fish_use_subcommand" -f -a "query" -d 'Search for a directory in the database'
set -l cmd (commandline -opc) complete -c zoxide -n "__fish_use_subcommand" -f -a "remove" -d 'Remove a directory from the database'
set -e cmd[1] complete -c zoxide -n "__fish_seen_subcommand_from add" -s h -l help -d 'Print help'
argparse -s (__fish_zoxide_global_optspecs) -- $cmd 2>/dev/null complete -c zoxide -n "__fish_seen_subcommand_from add" -s V -l version -d 'Print version'
or return complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -s h -l help -d 'Print help'
if set -q argv[1] complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -s V -l version -d 'Print version'
# Also print the command, so this can be used to figure out what it is. complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "decrement"
echo $argv[1] complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "delete"
return 1 complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "increment"
end complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "reload"
return 0 complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from decrement" -s h -l help -d 'Print help'
end complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from decrement" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from delete" -s h -l help -d 'Print help'
function __fish_zoxide_using_subcommand complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from delete" -s V -l version -d 'Print version'
set -l cmd (__fish_zoxide_needs_command) complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s h -l help -d 'Print help'
test -z "$cmd" complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s V -l version -d 'Print version'
and return 1 complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s h -l help -d 'Print help'
contains -- $cmd[1] $argv complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s V -l version -d 'Print version'
end complete -c zoxide -n "__fish_seen_subcommand_from import" -l from -d 'Application to import from' -r -f -a "{autojump ,z }"
complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database'
complete -c zoxide -n "__fish_zoxide_needs_command" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_needs_command" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_seen_subcommand_from import" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "add" -d 'Add a new directory or increment its rank' complete -c zoxide -n "__fish_seen_subcommand_from init" -l cmd -d 'Changes the prefix of the `z` and `zi` commands' -r
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "edit" -d 'Edit the database' complete -c zoxide -n "__fish_seen_subcommand_from init" -l hook -d 'Changes how often zoxide increments a directory\'s score' -r -f -a "{none ,prompt ,pwd }"
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "import" -d 'Import entries from another application' complete -c zoxide -n "__fish_seen_subcommand_from init" -l no-cmd -d 'Prevents zoxide from defining the `z` and `zi` commands'
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "init" -d 'Generate shell configuration' complete -c zoxide -n "__fish_seen_subcommand_from init" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "query" -d 'Search for a directory in the database' complete -c zoxide -n "__fish_seen_subcommand_from init" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "remove" -d 'Remove a directory from the database' complete -c zoxide -n "__fish_seen_subcommand_from query" -l exclude -d 'Exclude the current directory' -r -f -a "(__fish_complete_directories)"
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s s -l score -d 'The rank to increment the entry if it exists or initialize it with if it doesn\'t' -r complete -c zoxide -n "__fish_seen_subcommand_from query" -l all -d 'Show deleted directories'
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_seen_subcommand_from query" -s i -l interactive -d 'Use interactive selection'
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_seen_subcommand_from query" -s l -l list -d 'List all matching directories'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_seen_subcommand_from query" -s s -l score -d 'Print score with results'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_seen_subcommand_from query" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -f -a "decrement" complete -c zoxide -n "__fish_seen_subcommand_from query" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -f -a "delete" complete -c zoxide -n "__fish_seen_subcommand_from remove" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -f -a "increment" complete -c zoxide -n "__fish_seen_subcommand_from remove" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -f -a "reload"
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from decrement" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from decrement" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from delete" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from delete" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and __fish_seen_subcommand_from increment" -s h -l help -d 'Print help'
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 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''
pwd\t''"
complete -c zoxide -n "__fish_zoxide_using_subcommand init" -l no-cmd -d 'Prevents zoxide from defining the `z` and `zi` commands'
complete -c zoxide -n "__fish_zoxide_using_subcommand init" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand init" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -l exclude -d 'Exclude the current directory' -r -f -a "(__fish_complete_directories)"
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -l base-dir -d 'Only search within this directory' -r -f -a "(__fish_complete_directories)"
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s a -l all -d 'Show unavailable directories'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s i -l interactive -d 'Use interactive selection'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s l -l list -d 'List all matching directories'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s s -l score -d 'Print score with results'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s V -l version -d 'Print version'
complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s V -l version -d 'Print version'

View File

@ -1,99 +0,0 @@
module completions {
# A smarter cd command for your terminal
export extern zoxide [
--help(-h) # Print help
--version(-V) # Print version
]
# 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
]
# Edit the database
export extern "zoxide edit" [
--help(-h) # Print help
--version(-V) # Print version
]
export extern "zoxide edit decrement" [
path: string
--help(-h) # Print help
--version(-V) # Print version
]
export extern "zoxide edit delete" [
path: string
--help(-h) # Print help
--version(-V) # Print version
]
export extern "zoxide edit increment" [
path: string
--help(-h) # Print help
--version(-V) # Print version
]
export extern "zoxide edit reload" [
--help(-h) # Print help
--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
]
def "nu-complete zoxide init shell" [] {
[ "bash" "elvish" "fish" "nushell" "posix" "powershell" "tcsh" "xonsh" "zsh" ]
}
def "nu-complete zoxide init hook" [] {
[ "none" "prompt" "pwd" ]
}
# 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
]
# 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
--score(-s) # Print score with results
--exclude: path # Exclude the current directory
--base-dir: path # Only search within this directory
--help(-h) # Print help
--version(-V) # Print version
]
# Remove a directory from the database
export extern "zoxide remove" [
...paths: path
--help(-h) # Print help
--version(-V) # Print version
]
}
export use completions *

View File

@ -6,15 +6,6 @@ const completion: Fig.Spec = {
name: "add", name: "add",
description: "Add a new directory or increment its rank", description: "Add a new directory or increment its rank",
options: [ options: [
{
name: ["-s", "--score"],
description: "The rank to increment the entry if it exists or initialize it with if it doesn't",
isRepeatable: true,
args: {
name: "score",
isOptional: true,
},
},
{ {
name: ["-h", "--help"], name: ["-h", "--help"],
description: "Print help", description: "Print help",
@ -194,7 +185,6 @@ const completion: Fig.Spec = {
"nushell", "nushell",
"posix", "posix",
"powershell", "powershell",
"tcsh",
"xonsh", "xonsh",
"zsh", "zsh",
], ],
@ -215,18 +205,8 @@ const completion: Fig.Spec = {
}, },
}, },
{ {
name: "--base-dir", name: "--all",
description: "Only search within this directory", description: "Show deleted directories",
isRepeatable: true,
args: {
name: "base_dir",
isOptional: true,
template: "folders",
},
},
{
name: ["-a", "--all"],
description: "Show unavailable directories",
}, },
{ {
name: ["-i", "--interactive"], name: ["-i", "--interactive"],

View File

@ -1,6 +1,5 @@
#!/bin/sh #!/bin/sh
# shellcheck shell=dash # shellcheck shell=dash
# shellcheck disable=SC3043 # Assume `local` extension
# The official zoxide installer. # The official zoxide installer.
# #
@ -8,35 +7,29 @@
# extension. Note: Most shells limit `local` to 1 var per line, contra bash. # extension. Note: Most shells limit `local` to 1 var per line, contra bash.
main() { main() {
# The version of ksh93 that ships with many illumos systems does not support the "local"
# extension. Print a message rather than fail in subtle ways later on:
if [ "${KSH_VERSION-}" = 'Version JM 93t+ 2010-03-05' ]; then if [ "${KSH_VERSION-}" = 'Version JM 93t+ 2010-03-05' ]; then
# The version of ksh93 that ships with many illumos systems does not
# support the "local" extension. Print a message rather than fail in
# subtle ways later on:
err 'the installer does not work with this ksh93 version; please try bash' err 'the installer does not work with this ksh93 version; please try bash'
fi fi
set -u set -u
parse_args "$@" # Detect and print host target triple.
ensure get_architecture
local _arch local _arch="${RETVAL}"
_arch="${ARCH:-$(ensure get_architecture)}"
assert_nz "${_arch}" "arch" assert_nz "${_arch}" "arch"
echo "Detected architecture: ${_arch}" echo "Detected architecture: ${_arch}"
local _bin_name
case "${_arch}" in
*windows*) _bin_name="zoxide.exe" ;;
*) _bin_name="zoxide" ;;
esac
# Create and enter a temporary directory. # Create and enter a temporary directory.
local _tmp_dir local _tmp_dir
_tmp_dir="$(mktemp -d)" || err "mktemp: could not create temporary directory" _tmp_dir="$(mktemp -d)" || err "mktemp: could not create temporary directory"
cd "${_tmp_dir}" || err "cd: failed to enter directory: ${_tmp_dir}" cd "${_tmp_dir}" || err "cd: failed to enter directory: ${_tmp_dir}"
# Download and extract zoxide. # Download and extract zoxide.
local _package ensure download_zoxide "${_arch}"
_package="$(ensure download_zoxide "${_arch}")" local _package="${RETVAL}"
assert_nz "${_package}" "package" assert_nz "${_package}" "package"
echo "Downloaded package: ${_package}" echo "Downloaded package: ${_package}"
case "${_package}" in case "${_package}" in
@ -54,77 +47,31 @@ main() {
esac esac
# Install binary. # Install binary.
ensure try_sudo mkdir -p -- "${BIN_DIR}" local _bin_dir="${HOME}/.local/bin"
ensure try_sudo cp -- "${_bin_name}" "${BIN_DIR}/${_bin_name}" local _bin_name
ensure try_sudo chmod +x "${BIN_DIR}/${_bin_name}" case "${_arch}" in
echo "Installed zoxide to ${BIN_DIR}" *windows*) _bin_name="zoxide.exe" ;;
*) _bin_name="zoxide" ;;
esac
ensure mkdir -p "${_bin_dir}"
ensure cp "${_bin_name}" "${_bin_dir}"
ensure chmod +x "${_bin_dir}/${_bin_name}"
echo "Installed zoxide to ${_bin_dir}"
# Install manpages. # Install manpages.
ensure try_sudo mkdir -p -- "${MAN_DIR}/man1" local _man_dir="${HOME}/.local/share/man"
ensure try_sudo cp -- "man/man1/"* "${MAN_DIR}/man1/" ensure mkdir -p "${_man_dir}/man1"
echo "Installed manpages to ${MAN_DIR}" ensure cp "man/man1/"* "${_man_dir}/man1/"
echo "Installed manpages to ${_man_dir}"
# Print success message and check $PATH. # Print success message and check $PATH.
echo "" echo ""
echo "zoxide is installed!" echo "zoxide is installed!"
if ! echo ":${PATH}:" | grep -Fq ":${BIN_DIR}:"; then if ! echo ":${PATH}:" | grep -Fq ":${_bin_dir}:"; then
echo "Note: ${BIN_DIR} is not on your \$PATH. zoxide will not work unless it is added to \$PATH." echo "NOTE: ${_bin_dir} is not on your \$PATH. zoxide will not work unless it is added to \$PATH."
fi fi
} }
# Parse the arguments passed and set variables accordingly.
parse_args() {
BIN_DIR_DEFAULT="${HOME}/.local/bin"
MAN_DIR_DEFAULT="${HOME}/.local/share/man"
SUDO_DEFAULT="sudo"
BIN_DIR="${BIN_DIR_DEFAULT}"
MAN_DIR="${MAN_DIR_DEFAULT}"
SUDO="${SUDO_DEFAULT}"
while [ "$#" -gt 0 ]; do
case "$1" in
--arch) ARCH="$2" && shift 2 ;;
--arch=*) ARCH="${1#*=}" && shift 1 ;;
--bin-dir) BIN_DIR="$2" && shift 2 ;;
--bin-dir=*) BIN_DIR="${1#*=}" && shift 1 ;;
--man-dir) MAN_DIR="$2" && shift 2 ;;
--man-dir=*) MAN_DIR="${1#*=}" && shift 1 ;;
--sudo) SUDO="$2" && shift 2 ;;
--sudo=*) SUDO="${1#*=}" && shift 1 ;;
-h | --help) usage && exit 0 ;;
*) err "Unknown option: $1" ;;
esac
done
}
usage() {
# heredocs are not defined in POSIX.
local _text_heading _text_reset
_text_heading="$(tput bold || true 2>/dev/null)$(tput smul || true 2>/dev/null)"
_text_reset="$(tput sgr0 || true 2>/dev/null)"
local _arch
_arch="$(get_architecture || true)"
echo "\
${_text_heading}zoxide installer${_text_reset}
Ajeet D'Souza <98ajeet@gmail.com>
https://github.com/ajeetdsouza/zoxide
Fetches and installs zoxide. If zoxide is already installed, it will be updated to the latest version.
${_text_heading}Usage:${_text_reset}
install.sh [OPTIONS]
${_text_heading}Options:${_text_reset}
--arch Override the architecture identified by the installer [current: ${_arch}]
--bin-dir Override the installation directory [default: ${BIN_DIR_DEFAULT}]
--man-dir Override the manpage installation directory [default: ${MAN_DIR_DEFAULT}]
--sudo Override the command used to elevate to root privileges [default: ${SUDO_DEFAULT}]
-h, --help Print help"
}
download_zoxide() { download_zoxide() {
local _arch="$1" local _arch="$1"
@ -150,7 +97,7 @@ download_zoxide() {
err "you have exceeded GitHub's API rate limit. Please try again later, or use a different installation method: https://github.com/ajeetdsouza/zoxide/#installation" err "you have exceeded GitHub's API rate limit. Please try again later, or use a different installation method: https://github.com/ajeetdsouza/zoxide/#installation"
local _package_url local _package_url
_package_url="$(echo "${_releases}" | grep "browser_download_url" | cut -d '"' -f 4 | grep -- "${_arch}")" || _package_url="$(echo "${_releases}" | grep "browser_download_url" | cut -d '"' -f 4 | grep "${_arch}")" ||
err "zoxide has not yet been packaged for your architecture (${_arch}), please file an issue: https://github.com/ajeetdsouza/zoxide/issues" err "zoxide has not yet been packaged for your architecture (${_arch}), please file an issue: https://github.com/ajeetdsouza/zoxide/issues"
local _ext local _ext
@ -167,30 +114,7 @@ download_zoxide() {
*) err "unsupported downloader: ${_dld}" ;; *) err "unsupported downloader: ${_dld}" ;;
esac esac
echo "${_package}" RETVAL="${_package}"
}
try_sudo() {
if "$@" >/dev/null 2>&1; then
return 0
fi
need_sudo
"${SUDO}" "$@"
}
need_sudo() {
if ! check_cmd "${SUDO}"; then
err "\
could not find the command \`${SUDO}\` needed to get permissions for install.
If you are on Windows, please run your shell as an administrator, then rerun this script.
Otherwise, please run this script as root, or install \`sudo\`."
fi
if ! "${SUDO}" -v; then
err "sudo permissions not granted, aborting installation"
fi
} }
# The below functions have been extracted with minor modifications from the # The below functions have been extracted with minor modifications from the
@ -335,7 +259,8 @@ get_architecture() {
x86_64) x86_64)
# 32-bit executable for amd64 = x32 # 32-bit executable for amd64 = x32
if is_host_amd64_elf; then { if is_host_amd64_elf; then {
err "x32 userland is unsupported" echo "x32 userland is unsupported" 1>&2
exit 1
}; else }; else
_cputype=i686 _cputype=i686
fi fi
@ -372,7 +297,7 @@ get_architecture() {
fi fi
_arch="${_cputype}-${_ostype}" _arch="${_cputype}-${_ostype}"
echo "${_arch}" RETVAL="${_arch}"
} }
get_bitness() { get_bitness() {
@ -395,9 +320,9 @@ get_bitness() {
} }
get_endianness() { get_endianness() {
local cputype="$1" local cputype=$1
local suffix_eb="$2" local suffix_eb=$2
local suffix_el="$3" local suffix_el=$3
# detect endianness without od/hexdump, like get_bitness() does. # detect endianness without od/hexdump, like get_bitness() does.
need_cmd head need_cmd head
@ -440,7 +365,7 @@ need_cmd() {
} }
check_cmd() { check_cmd() {
command -v -- "$1" >/dev/null 2>&1 command -v "$1" >/dev/null 2>&1
} }
# Run a command that should never fail. If the command fails execution # Run a command that should never fail. If the command fails execution

View File

@ -21,7 +21,7 @@ lint:
nix-shell --cores 0 --pure --run 'mandoc -man -Wall -Tlint -- man/man1/*.1' nix-shell --cores 0 --pure --run 'mandoc -man -Wall -Tlint -- man/man1/*.1'
nix-shell --cores 0 --pure --run 'markdownlint *.md' nix-shell --cores 0 --pure --run 'markdownlint *.md'
nix-shell --cores 0 --pure --run 'nixfmt --check -- *.nix' nix-shell --cores 0 --pure --run 'nixfmt --check -- *.nix'
nix-shell --cores 0 --pure --run 'shellcheck --enable all *.sh' # nix-shell --cores 0 --pure --run 'shellcheck --enable all *.sh'
nix-shell --cores 0 --pure --run 'shfmt --diff --indent=4 --language-dialect=posix --simplify *.sh' nix-shell --cores 0 --pure --run 'shfmt --diff --indent=4 --language-dialect=posix --simplify *.sh'
nix-shell --cores 0 --pure --run 'yamlfmt -lint -- .github/workflows/*.yml' nix-shell --cores 0 --pure --run 'yamlfmt -lint -- .github/workflows/*.yml'

View File

@ -7,14 +7,14 @@
To initialize zoxide on your shell: To initialize zoxide on your shell:
.TP .TP
.B bash .B bash
Add this to the \fBend\fR of your config file (usually \fB~/.bashrc\fR): Add this to your configuration (usually \fB~/.bashrc\fR):
.sp .sp
.nf .nf
\fBeval "$(zoxide init bash)"\fR \fBeval "$(zoxide init bash)"\fR
.fi .fi
.TP .TP
.B elvish .B elvish
Add this to the \fBend\fR of your config file (usually \fB~/.elvish/rc.elv\fR): Add this to your configuration (usually \fB~/.elvish/rc.elv\fR):
.sp .sp
.nf .nf
\fBeval $(zoxide init elvish | slurp)\fR \fBeval $(zoxide init elvish | slurp)\fR
@ -23,55 +23,45 @@ Add this to the \fBend\fR of your config file (usually \fB~/.elvish/rc.elv\fR):
Note: zoxide only supports elvish v0.18.0 and above. Note: zoxide only supports elvish v0.18.0 and above.
.TP .TP
.B fish .B fish
Add this to the \fBend\fR of your config file (usually Add this to your configuration (usually \fB~/.config/fish/config.fish\fR):
\fB~/.config/fish/config.fish\fR):
.sp .sp
.nf .nf
\fBzoxide init fish | source\fR \fBzoxide init fish | source\fR
.fi .fi
.TP .TP
.B nushell .B nushell
Add this to the \fBend\fR of your env file (find it by running Add this to your env file (find it by running \fB$nu.env-path\fR in Nushell):
\fB$nu.env-path\fR in Nushell):
.sp .sp
.nf .nf
\fBzoxide init nushell | save -f ~/.zoxide.nu\fR \fBzoxide init nushell | save -f ~/.zoxide.nu\fR
.fi .fi
.sp .sp
Now, add this to the \fBend\fR of your config file (find it by running Now, add this to the end of your config file (find it by running
\fB$nu.config-path\fR in Nushell): \fB$nu.config-path\fR in Nushell):
.sp .sp
.nf .nf
\fBsource ~/.zoxide.nu\fR \fBsource ~/.zoxide.nu\fR
.fi .fi
.sp .sp
Note: zoxide only supports Nushell v0.89.0+. Note: zoxide only supports Nushell v0.73.0 and above.
.TP .TP
.B powershell .B powershell
Add this to the \fBend\fR of your config file (find it by running \fBecho Add this to your configuration (find it by running \fBecho $profile\fR in
$profile\fR in PowerShell): PowerShell):
.sp .sp
.nf .nf
\fBInvoke-Expression (& { (zoxide init powershell | Out-String) })\fR \fBInvoke-Expression (& { (zoxide init powershell | Out-String) })\fR
.fi .fi
.TP .TP
.B tcsh
Add this to the \fBend\fR of your config file (usually \fB~/.tcshrc\fR):
.sp
.nf
\fBzoxide init tcsh > ~/.zoxide.tcsh\fR
\fBsource ~/.zoxide.tcsh\fR
.fi
.TP
.B xonsh .B xonsh
Add this to the \fBend\fR of your config file (usually \fB~/.xonshrc\fR): Add this to your configuration (usually \fB~/.xonshrc\fR):
.sp .sp
.nf .nf
\fBexecx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide')\fR \fBexecx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide')\fR
.fi .fi
.TP .TP
.B zsh .B zsh
Add this to the \fBend\fR of your config file (usually \fB~/.zshrc\fR): Add this to your configuration (usually \fB~/.zshrc\fR):
.sp .sp
.nf .nf
\fBeval "$(zoxide init zsh)"\fR \fBeval "$(zoxide init zsh)"\fR
@ -79,7 +69,7 @@ Add this to the \fBend\fR of your config file (usually \fB~/.zshrc\fR):
.TP .TP
.B any POSIX shell .B any POSIX shell
.sp .sp
Add this to the \fBend\fR of your config file: Add this to your configuration:
.sp .sp
.nf .nf
\fBeval "$(zoxide init posix --hook prompt)"\fR \fBeval "$(zoxide init posix --hook prompt)"\fR

View File

@ -5,4 +5,4 @@ use_field_init_shorthand = true
use_small_heuristics = "Max" use_small_heuristics = "Max"
use_try_shorthand = true use_try_shorthand = true
wrap_comments = true wrap_comments = true
style_edition = "2024" version = "Two"

View File

@ -1,10 +1,10 @@
let let
pkgs = import (builtins.fetchTarball pkgs = import (builtins.fetchTarball
"https://github.com/NixOS/nixpkgs/archive/ec9ef366451af88284d7dfd18ee017b7e86a0710.tar.gz") { "https://github.com/NixOS/nixpkgs/archive/22a6958f46fd8e14830d02856ff63b1d0e5cc3e4.tar.gz") {
overlays = [ rust ]; overlays = [ rust ];
}; };
rust = import (builtins.fetchTarball rust = import (builtins.fetchTarball
"https://github.com/oxalica/rust-overlay/archive/026e8fedefd6b167d92ed04b195c658d95ffc7a5.tar.gz"); "https://github.com/oxalica/rust-overlay/archive/a61fcd9910229d097ffef92b5a2440065e3b64d5.tar.gz");
rust-nightly = rust-nightly =
pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal); pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal);
@ -24,10 +24,8 @@ in pkgs.mkShell {
pkgs.dash pkgs.dash
pkgs.elvish pkgs.elvish
pkgs.fish pkgs.fish
pkgs.ksh
pkgs.nushell pkgs.nushell
pkgs.powershell pkgs.powershell
pkgs.tcsh
pkgs.xonsh pkgs.xonsh
pkgs.zsh pkgs.zsh

View File

@ -1,6 +1,6 @@
use std::path::Path; use std::path::Path;
use anyhow::{Result, bail}; use anyhow::{bail, Result};
use crate::cmd::{Add, Run}; use crate::cmd::{Add, Run};
use crate::db::Database; use crate::db::Database;
@ -33,9 +33,7 @@ impl Run for Add {
if !Path::new(path).is_dir() { if !Path::new(path).is_dir() {
bail!("not a directory: {path}"); bail!("not a directory: {path}");
} }
db.add_update(path, 1.0, now);
let by = self.score.unwrap_or(1.0);
db.add_update(path, by, now);
} }
if db.dirty() { if db.dirty() {

View File

@ -2,43 +2,33 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::builder::{IntoResettable, Resettable, StyledStr};
use clap::{Parser, Subcommand, ValueEnum, ValueHint}; use clap::{Parser, Subcommand, ValueEnum, ValueHint};
struct HelpTemplate; const HELP_TEMPLATE: &str = color_print::cstr!(
"\
impl IntoResettable<StyledStr> for HelpTemplate { <bold><underline>{before-help}{name} {version}</underline></bold>
fn into_resettable(self) -> Resettable<StyledStr> { {author-with-newline}{about-with-newline}
color_print::cstr!("\ {usage-heading} {usage}
{before-help}<bold><underline>{name} {version}</underline></bold>
{author}
https://github.com/ajeetdsouza/zoxide
{about}
{usage-heading}
{tab}{usage}
{all-args}{after-help} {all-args}{after-help}
<bold><underline>Environment variables:</underline></bold> <bold><underline>Environment variables:</underline></bold>
{tab}<bold>_ZO_DATA_DIR</bold> {tab}Path for zoxide data files <bold>_ZO_DATA_DIR</bold> Path for zoxide data files
{tab}<bold>_ZO_ECHO</bold> {tab}Print the matched directory before navigating to it when set to 1 <bold>_ZO_ECHO</bold> Print the matched directory before navigating to it when set to 1
{tab}<bold>_ZO_EXCLUDE_DIRS</bold> {tab}List of directory globs to be excluded <bold>_ZO_EXCLUDE_DIRS</bold> List of directory globs to be excluded
{tab}<bold>_ZO_FZF_OPTS</bold> {tab}Custom flags to pass to fzf <bold>_ZO_FZF_OPTS</bold> Custom flags to pass to fzf
{tab}<bold>_ZO_MAXAGE</bold> {tab}Maximum total age after which entries start getting deleted <bold>_ZO_MAXAGE</bold> Maximum total age after which entries start getting deleted
{tab}<bold>_ZO_RESOLVE_SYMLINKS</bold>{tab}Resolve symlinks when storing paths").into_resettable() <bold>_ZO_RESOLVE_SYMLINKS</bold> Resolve symlinks when storing paths"
} );
}
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
about, about,
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
disable_help_subcommand = true, disable_help_subcommand = true,
propagate_version = true, propagate_version = true,
version, version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
)] )]
pub enum Cmd { pub enum Cmd {
Add(Add), Add(Add),
@ -53,23 +43,18 @@ pub enum Cmd {
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Add { pub struct Add {
#[clap(num_args = 1.., required = true, value_hint = ValueHint::DirPath)] #[clap(num_args = 1.., required = true, value_hint = ValueHint::DirPath)]
pub paths: Vec<PathBuf>, pub paths: Vec<PathBuf>,
/// The rank to increment the entry if it exists or initialize it with if it
/// doesn't
#[clap(short, long)]
pub score: Option<f64>,
} }
/// Edit the database /// Edit the database
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Edit { pub struct Edit {
#[clap(subcommand)] #[clap(subcommand)]
@ -92,7 +77,7 @@ pub enum EditCommand {
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Import { pub struct Import {
#[clap(value_hint = ValueHint::FilePath)] #[clap(value_hint = ValueHint::FilePath)]
@ -118,7 +103,7 @@ pub enum ImportFrom {
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Init { pub struct Init {
#[clap(value_enum)] #[clap(value_enum)]
@ -150,10 +135,8 @@ pub enum InitShell {
Elvish, Elvish,
Fish, Fish,
Nushell, Nushell,
#[clap(alias = "ksh")]
Posix, Posix,
Powershell, Powershell,
Tcsh,
Xonsh, Xonsh,
Zsh, Zsh,
} }
@ -162,13 +145,13 @@ pub enum InitShell {
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Query { pub struct Query {
pub keywords: Vec<String>, pub keywords: Vec<String>,
/// Show unavailable directories /// Show deleted directories
#[clap(long, short)] #[clap(long)]
pub all: bool, pub all: bool,
/// Use interactive selection /// Use interactive selection
@ -186,17 +169,13 @@ pub struct Query {
/// Exclude the current directory /// Exclude the current directory
#[clap(long, value_hint = ValueHint::DirPath, value_name = "path")] #[clap(long, value_hint = ValueHint::DirPath, value_name = "path")]
pub exclude: Option<String>, pub exclude: Option<String>,
/// Only search within this directory
#[clap(long, value_hint = ValueHint::DirPath, value_name = "path")]
pub base_dir: Option<String>,
} }
/// Remove a directory from the database /// Remove a directory from the database
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap( #[clap(
author, author,
help_template = HelpTemplate, help_template = HELP_TEMPLATE,
)] )]
pub struct Remove { pub struct Remove {
#[clap(value_hint = ValueHint::DirPath)] #[clap(value_hint = ValueHint::DirPath)]

View File

@ -1,6 +1,6 @@
use std::fs; use std::fs;
use anyhow::{Context, Result, bail}; use anyhow::{bail, Context, Result};
use crate::cmd::{Import, ImportFrom, Run}; use crate::cmd::{Import, ImportFrom, Run};
use crate::db::Database; use crate::db::Database;

View File

@ -6,7 +6,7 @@ use askama::Template;
use crate::cmd::{Init, InitShell, Run}; use crate::cmd::{Init, InitShell, Run};
use crate::config; use crate::config;
use crate::error::BrokenPipeHandler; use crate::error::BrokenPipeHandler;
use crate::shell::{Bash, Elvish, Fish, Nushell, Opts, Posix, Powershell, Tcsh, Xonsh, Zsh}; use crate::shell::{Bash, Elvish, Fish, Nushell, Opts, Posix, Powershell, Xonsh, Zsh};
impl Run for Init { impl Run for Init {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {
@ -22,7 +22,6 @@ impl Run for Init {
InitShell::Nushell => Nushell(opts).render(), InitShell::Nushell => Nushell(opts).render(),
InitShell::Posix => Posix(opts).render(), InitShell::Posix => Posix(opts).render(),
InitShell::Powershell => Powershell(opts).render(), InitShell::Powershell => Powershell(opts).render(),
InitShell::Tcsh => Tcsh(opts).render(),
InitShell::Xonsh => Xonsh(opts).render(), InitShell::Xonsh => Xonsh(opts).render(),
InitShell::Zsh => Zsh(opts).render(), InitShell::Zsh => Zsh(opts).render(),
} }

View File

@ -1,10 +1,10 @@
use std::io::{self, Write}; use std::io::{self, Write};
use anyhow::{Context, Result}; use anyhow::{bail, Context, Result};
use crate::cmd::{Query, Run}; use crate::cmd::{Query, Run};
use crate::config; use crate::config;
use crate::db::{Database, Epoch, Stream, StreamOptions}; use crate::db::{Database, Epoch, Stream};
use crate::error::BrokenPipeHandler; use crate::error::BrokenPipeHandler;
use crate::util::{self, Fzf, FzfChild}; use crate::util::{self, Fzf, FzfChild};
@ -18,76 +18,59 @@ impl Run for Query {
impl Query { impl Query {
fn query(&self, db: &mut Database) -> Result<()> { fn query(&self, db: &mut Database) -> Result<()> {
let now = util::current_time()?; let now = util::current_time()?;
let mut stream = self.get_stream(db, now)?; let mut stream = self.get_stream(db, now);
if self.interactive { if self.interactive {
self.query_interactive(&mut stream, now) let mut fzf = Self::get_fzf()?;
} else if self.list { let selection = loop {
self.query_list(&mut stream, now) match stream.next() {
} else { Some(dir) => {
self.query_first(&mut stream, now) if let Some(selection) = fzf.write(dir, now)? {
} break selection;
} }
fn query_interactive(&self, stream: &mut Stream, now: Epoch) -> Result<()> {
let mut fzf = Self::get_fzf()?;
let selection = loop {
match stream.next() {
Some(dir) if Some(dir.path.as_ref()) == self.exclude.as_deref() => continue,
Some(dir) => {
if let Some(selection) = fzf.write(dir, now)? {
break selection;
} }
None => break fzf.wait()?,
} }
None => break fzf.wait()?, };
}
};
if self.score { if self.score {
print!("{selection}"); print!("{selection}");
} else {
let path = selection.get(7..).context("could not read selection from fzf")?;
print!("{path}");
}
} else if self.list {
let handle = &mut io::stdout().lock();
while let Some(dir) = stream.next() {
let dir = if self.score { dir.display().with_score(now) } else { dir.display() };
writeln!(handle, "{dir}").pipe_exit("stdout")?;
}
} else { } else {
let path = selection.get(7..).context("could not read selection from fzf")?; let handle = &mut io::stdout();
print!("{path}"); let Some(dir) = stream.next() else {
} bail!(if stream.did_exclude() {
Ok(()) "you are already in the only match"
} } else {
"no match found"
fn query_list(&self, stream: &mut Stream, now: Epoch) -> Result<()> { });
let handle = &mut io::stdout().lock(); };
while let Some(dir) = stream.next() {
if Some(dir.path.as_ref()) == self.exclude.as_deref() {
continue;
}
let dir = if self.score { dir.display().with_score(now) } else { dir.display() }; let dir = if self.score { dir.display().with_score(now) } else { dir.display() };
writeln!(handle, "{dir}").pipe_exit("stdout")?; writeln!(handle, "{dir}").pipe_exit("stdout")?;
} }
Ok(()) Ok(())
} }
fn query_first(&self, stream: &mut Stream, now: Epoch) -> Result<()> { fn get_stream<'a>(&self, db: &'a mut Database, now: Epoch) -> Stream<'a> {
let handle = &mut io::stdout(); let mut stream = db.stream(now).with_keywords(&self.keywords);
let mut dir = stream.next().context("no match found")?;
while Some(dir.path.as_ref()) == self.exclude.as_deref() {
dir = stream.next().context("you are already in the only match")?;
}
let dir = if self.score { dir.display().with_score(now) } else { dir.display() };
writeln!(handle, "{dir}").pipe_exit("stdout")
}
fn get_stream<'a>(&self, db: &'a mut Database, now: Epoch) -> Result<Stream<'a>> {
let mut options = StreamOptions::new(now)
.with_keywords(self.keywords.iter().map(|s| s.as_str()))
.with_exclude(config::exclude_dirs()?)
.with_base_dir(self.base_dir.clone());
if !self.all { if !self.all {
let resolve_symlinks = config::resolve_symlinks(); let resolve_symlinks = config::resolve_symlinks();
options = options.with_exists(true).with_resolve_symlinks(resolve_symlinks); stream = stream.with_exists(resolve_symlinks);
} }
if let Some(path) = &self.exclude {
let stream = Stream::new(db, options); stream = stream.with_exclude(path);
Ok(stream) }
stream
} }
fn get_fzf() -> Result<FzfChild> { fn get_fzf() -> Result<FzfChild> {
@ -113,6 +96,7 @@ impl Query {
"--tabstop=1", "--tabstop=1",
// Scripting // Scripting
"--exit-0", "--exit-0",
"--select-1",
]) ])
.enable_preview() .enable_preview()
} }

View File

@ -1,4 +1,4 @@
use anyhow::{Result, bail}; use anyhow::{bail, Result};
use crate::cmd::{Remove, Run}; use crate::cmd::{Remove, Run};
use crate::db::Database; use crate::db::Database;

View File

@ -2,25 +2,23 @@ use std::env;
use std::ffi::OsString; use std::ffi::OsString;
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::{Context, Result, ensure}; use anyhow::{Context, Result};
use glob::Pattern; use glob::Pattern;
use crate::db::Rank; use crate::db::Rank;
pub fn data_dir() -> Result<PathBuf> { pub fn data_dir() -> Result<PathBuf> {
let dir = match env::var_os("_ZO_DATA_DIR") { let path = match env::var_os("_ZO_DATA_DIR") {
Some(path) => PathBuf::from(path), Some(path) => PathBuf::from(path),
None => dirs::data_local_dir() None => dirs::data_local_dir()
.context("could not find data directory, please set _ZO_DATA_DIR manually")? .context("could not find data directory, please set _ZO_DATA_DIR manually")?
.join("zoxide"), .join("zoxide"),
}; };
Ok(path)
ensure!(dir.is_absolute(), "_ZO_DATA_DIR must be an absolute path");
Ok(dir)
} }
pub fn echo() -> bool { pub fn echo() -> bool {
env::var_os("_ZO_ECHO").is_some_and(|var| var == "1") env::var_os("_ZO_ECHO").map_or(false, |var| var == "1")
} }
pub fn exclude_dirs() -> Result<Vec<Pattern>> { pub fn exclude_dirs() -> Result<Vec<Pattern>> {
@ -58,5 +56,5 @@ pub fn maxage() -> Result<Rank> {
} }
pub fn resolve_symlinks() -> bool { pub fn resolve_symlinks() -> bool {
env::var_os("_ZO_RESOLVE_SYMLINKS").is_some_and(|var| var == "1") env::var_os("_ZO_RESOLVE_SYMLINKS").map_or(false, |var| var == "1")
} }

View File

@ -4,12 +4,12 @@ mod stream;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::{fs, io}; use std::{fs, io};
use anyhow::{Context, Result, bail}; use anyhow::{bail, Context, Result};
use bincode::Options; use bincode::Options;
use ouroboros::self_referencing; use ouroboros::self_referencing;
pub use crate::db::dir::{Dir, Epoch, Rank}; pub use crate::db::dir::{Dir, Epoch, Rank};
pub use crate::db::stream::{Stream, StreamOptions}; pub use crate::db::stream::Stream;
use crate::{config, util}; use crate::{config, util};
#[self_referencing] #[self_referencing]
@ -33,7 +33,6 @@ impl Database {
pub fn open_dir(data_dir: impl AsRef<Path>) -> Result<Self> { pub fn open_dir(data_dir: impl AsRef<Path>) -> Result<Self> {
let data_dir = data_dir.as_ref(); let data_dir = data_dir.as_ref();
let path = data_dir.join("db.zo"); let path = data_dir.join("db.zo");
let path = fs::canonicalize(&path).unwrap_or(path);
match fs::read(&path) { match fs::read(&path) {
Ok(bytes) => Self::try_new(path, bytes, |bytes| Self::deserialize(bytes), false), Ok(bytes) => Self::try_new(path, bytes, |bytes| Self::deserialize(bytes), false),
@ -136,6 +135,10 @@ impl Database {
self.with_dirty_mut(|dirty_prev| *dirty_prev |= dirty); self.with_dirty_mut(|dirty_prev| *dirty_prev |= dirty);
} }
pub fn stream(&mut self, now: Epoch) -> Stream {
Stream::new(self, now)
}
pub fn dedup(&mut self) { pub fn dedup(&mut self) {
// Sort by path, so that equal paths are next to each other. // Sort by path, so that equal paths are next to each other.
self.sort_by_path(); self.sort_by_path();
@ -183,7 +186,7 @@ impl Database {
*self.borrow_dirty() *self.borrow_dirty()
} }
pub fn dirs(&self) -> &[Dir<'_>] { pub fn dirs(&self) -> &[Dir] {
self.borrow_dirs() self.borrow_dirs()
} }
@ -203,7 +206,7 @@ impl Database {
.context("could not serialize database") .context("could not serialize database")
} }
fn deserialize(bytes: &[u8]) -> Result<Vec<Dir<'_>>> { fn deserialize(bytes: &[u8]) -> Result<Vec<Dir>> {
// Assume a maximum size for the database. This prevents bincode from throwing // Assume a maximum size for the database. This prevents bincode from throwing
// strange errors when it encounters invalid data. // strange errors when it encounters invalid data.
const MAX_SIZE: u64 = 32 << 20; // 32 MiB const MAX_SIZE: u64 = 32 << 20; // 32 MiB

View File

@ -1,51 +1,81 @@
use std::iter::Rev; use std::iter::Rev;
use std::ops::Range; use std::ops::Range;
use std::path::Path;
use std::{fs, path}; use std::{fs, path};
use glob::Pattern;
use crate::db::{Database, Dir, Epoch}; use crate::db::{Database, Dir, Epoch};
use crate::util::{self, MONTH}; use crate::util::{self, MONTH};
pub struct Stream<'a> { pub struct Stream<'a> {
// State
db: &'a mut Database, db: &'a mut Database,
idxs: Rev<Range<usize>>, idxs: Rev<Range<usize>>,
options: StreamOptions, did_exclude: bool,
// Configuration
keywords: Vec<String>,
check_exists: bool,
expire_below: Epoch,
resolve_symlinks: bool,
exclude_path: Option<String>,
} }
impl<'a> Stream<'a> { impl<'a> Stream<'a> {
pub fn new(db: &'a mut Database, options: StreamOptions) -> Self { pub fn new(db: &'a mut Database, now: Epoch) -> Self {
db.sort_by_score(options.now); db.sort_by_score(now);
let idxs = (0..db.dirs().len()).rev(); let idxs = (0..db.dirs().len()).rev();
Stream { db, idxs, options }
// If a directory is deleted and hasn't been used for 3 months, delete
// it from the database.
let expire_below = now.saturating_sub(3 * MONTH);
Stream {
db,
idxs,
did_exclude: false,
keywords: Vec::new(),
check_exists: false,
expire_below,
resolve_symlinks: false,
exclude_path: None,
}
} }
pub fn next(&mut self) -> Option<&Dir<'_>> { pub fn with_exclude(mut self, path: impl Into<String>) -> Self {
self.exclude_path = Some(path.into());
self
}
pub fn with_exists(mut self, resolve_symlinks: bool) -> Self {
self.check_exists = true;
self.resolve_symlinks = resolve_symlinks;
self
}
pub fn with_keywords(mut self, keywords: &[impl AsRef<str>]) -> Self {
self.keywords = keywords.iter().map(util::to_lowercase).collect();
self
}
pub fn next(&mut self) -> Option<&Dir> {
while let Some(idx) = self.idxs.next() { while let Some(idx) = self.idxs.next() {
let dir = &self.db.dirs()[idx]; let dir = &self.db.dirs()[idx];
if !self.filter_by_keywords(&dir.path) { if !self.matches_keywords(&dir.path) {
continue; continue;
} }
if !self.filter_by_base_dir(&dir.path) { if !self.matches_exists(&dir.path) {
continue; if dir.last_accessed < self.expire_below {
}
if !self.filter_by_exclude(&dir.path) {
self.db.swap_remove(idx);
continue;
}
// Exists queries are slow, this should always be checked last.
if !self.filter_by_exists(&dir.path) {
if dir.last_accessed < self.options.ttl {
self.db.swap_remove(idx); self.db.swap_remove(idx);
} }
continue; continue;
} }
if Some(dir.path.as_ref()) == self.exclude_path.as_deref() {
self.did_exclude = true;
continue;
}
let dir = &self.db.dirs()[idx]; let dir = &self.db.dirs()[idx];
return Some(dir); return Some(dir);
} }
@ -53,32 +83,20 @@ impl<'a> Stream<'a> {
None None
} }
fn filter_by_base_dir(&self, path: &str) -> bool { pub fn did_exclude(&self) -> bool {
match &self.options.base_dir { self.did_exclude
Some(base_dir) => Path::new(path).starts_with(base_dir),
None => true,
}
} }
fn filter_by_exclude(&self, path: &str) -> bool { fn matches_exists(&self, path: &str) -> bool {
!self.options.exclude.iter().any(|pattern| pattern.matches(path)) if !self.check_exists {
}
fn filter_by_exists(&self, path: &str) -> bool {
if !self.options.exists {
return true; return true;
} }
let resolver = if self.resolve_symlinks { fs::symlink_metadata } else { fs::metadata };
// The logic here is reversed - if we resolve symlinks when adding entries to resolver(path).map(|m| m.is_dir()).unwrap_or_default()
// the database, we should not return symlinks when querying back from
// the database.
let resolver =
if self.options.resolve_symlinks { fs::symlink_metadata } else { fs::metadata };
resolver(path).map(|metadata| metadata.is_dir()).unwrap_or_default()
} }
fn filter_by_keywords(&self, path: &str) -> bool { fn matches_keywords(&self, path: &str) -> bool {
let (keywords_last, keywords) = match self.options.keywords.split_last() { let (keywords_last, keywords) = match self.keywords.split_last() {
Some(split) => split, Some(split) => split,
None => return true, None => return true,
}; };
@ -106,74 +124,6 @@ impl<'a> Stream<'a> {
} }
} }
pub struct StreamOptions {
/// The current time.
now: Epoch,
/// Only directories matching these keywords will be returned.
keywords: Vec<String>,
/// Directories that match any of these globs will be lazily removed.
exclude: Vec<Pattern>,
/// Directories will only be returned if they exist on the filesystem.
exists: bool,
/// Whether to resolve symlinks when checking if a directory exists.
resolve_symlinks: bool,
/// Directories that do not exist and haven't been accessed since TTL will
/// be lazily removed.
ttl: Epoch,
/// Only return directories within this parent directory
/// Does not check if the path exists
base_dir: Option<String>,
}
impl StreamOptions {
pub fn new(now: Epoch) -> Self {
StreamOptions {
now,
keywords: Vec::new(),
exclude: Vec::new(),
exists: false,
resolve_symlinks: false,
ttl: now.saturating_sub(3 * MONTH),
base_dir: None,
}
}
pub fn with_keywords<I>(mut self, keywords: I) -> Self
where
I: IntoIterator,
I::Item: AsRef<str>,
{
self.keywords = keywords.into_iter().map(util::to_lowercase).collect();
self
}
pub fn with_exclude(mut self, exclude: Vec<Pattern>) -> Self {
self.exclude = exclude;
self
}
pub fn with_exists(mut self, exists: bool) -> Self {
self.exists = exists;
self
}
pub fn with_resolve_symlinks(mut self, resolve_symlinks: bool) -> Self {
self.resolve_symlinks = resolve_symlinks;
self
}
pub fn with_base_dir(mut self, base_dir: Option<String>) -> Self {
self.base_dir = base_dir;
self
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::path::PathBuf; use std::path::PathBuf;
@ -204,8 +154,7 @@ mod tests {
#[case(&["/foo/", "/bar"], "/foo/baz/bar", true)] #[case(&["/foo/", "/bar"], "/foo/baz/bar", true)]
fn query(#[case] keywords: &[&str], #[case] path: &str, #[case] is_match: bool) { fn query(#[case] keywords: &[&str], #[case] path: &str, #[case] is_match: bool) {
let db = &mut Database::new(PathBuf::new(), Vec::new(), |_| Vec::new(), false); let db = &mut Database::new(PathBuf::new(), Vec::new(), |_| Vec::new(), false);
let options = StreamOptions::new(0).with_keywords(keywords.iter()); let stream = Stream::new(db, 0).with_keywords(keywords);
let stream = Stream::new(db, options); assert_eq!(is_match, stream.matches_keywords(path));
assert_eq!(is_match, stream.filter_by_keywords(path));
} }
} }

View File

@ -1,7 +1,7 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::io; use std::io;
use anyhow::{Context, Result, bail}; use anyhow::{bail, Context, Result};
/// Custom error type for early exit. /// Custom error type for early exit.
#[derive(Debug)] #[derive(Debug)]

View File

@ -1,5 +1,9 @@
#![allow(clippy::single_component_path_imports)] #![allow(clippy::single_component_path_imports)]
// rstest_reuse must be imported at the top of the crate.
#[cfg(all(test, feature = "nix-dev"))]
use rstest_reuse;
mod cmd; mod cmd;
mod config; mod config;
mod db; mod db;
@ -18,8 +22,8 @@ use crate::error::SilentExit;
pub fn main() -> ExitCode { pub fn main() -> ExitCode {
// Forcibly disable backtraces. // Forcibly disable backtraces.
unsafe { env::remove_var("RUST_LIB_BACKTRACE") }; env::remove_var("RUST_LIB_BACKTRACE");
unsafe { env::remove_var("RUST_BACKTRACE") }; env::remove_var("RUST_BACKTRACE");
match Cmd::parse().run() { match Cmd::parse().run() {
Ok(()) => ExitCode::SUCCESS, Ok(()) => ExitCode::SUCCESS,

View File

@ -29,7 +29,6 @@ make_template!(Fish, "fish.txt");
make_template!(Nushell, "nushell.txt"); make_template!(Nushell, "nushell.txt");
make_template!(Posix, "posix.txt"); make_template!(Posix, "posix.txt");
make_template!(Powershell, "powershell.txt"); make_template!(Powershell, "powershell.txt");
make_template!(Tcsh, "tcsh.txt");
make_template!(Xonsh, "xonsh.txt"); make_template!(Xonsh, "xonsh.txt");
make_template!(Zsh, "zsh.txt"); make_template!(Zsh, "zsh.txt");
@ -71,7 +70,7 @@ mod tests {
let source = Bash(&opts).render().unwrap(); let source = Bash(&opts).render().unwrap();
Command::new("shellcheck") Command::new("shellcheck")
.args(["--enable=all", "-"]) .args(["--enable", "all", "--shell", "bash", "-"])
.write_stdin(source) .write_stdin(source)
.assert() .assert()
.success() .success()
@ -97,7 +96,7 @@ mod tests {
#[apply(opts)] #[apply(opts)]
fn elvish_elvish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn elvish_elvish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = String::new(); let mut source = String::default();
// Filter out lines using edit:*, since those functions are only available in // Filter out lines using edit:*, since those functions are only available in
// the interactive editor. // the interactive editor.
@ -114,16 +113,6 @@ mod tests {
.stderr(""); .stderr("");
} }
#[apply(opts)]
fn fish_no_builtin_abbr(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Fish(&opts).render().unwrap();
assert!(
!source.contains("builtin abbr"),
"`builtin abbr` does not work on older versions of Fish"
);
}
#[apply(opts)] #[apply(opts)]
fn fish_fish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn fish_fish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
@ -207,12 +196,12 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
fn posix_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn posix_shellcheck_(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Posix(&opts).render().unwrap(); let source = Posix(&opts).render().unwrap();
Command::new("shellcheck") Command::new("shellcheck")
.args(["--enable=all", "-"]) .args(["--enable", "all", "--shell", "sh", "-"])
.write_stdin(source) .write_stdin(source)
.assert() .assert()
.success() .success()
@ -249,20 +238,6 @@ mod tests {
.stderr(""); .stderr("");
} }
#[apply(opts)]
fn tcsh_tcsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Tcsh(&opts).render().unwrap();
Command::new("tcsh")
.args(["-e", "-f", "-s"])
.write_stdin(source)
.assert()
.success()
.stdout("")
.stderr("");
}
#[apply(opts)] #[apply(opts)]
fn xonsh_black(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn xonsh_black(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
@ -323,7 +298,7 @@ mod tests {
// ShellCheck doesn't support zsh yet: https://github.com/koalaman/shellcheck/issues/809 // ShellCheck doesn't support zsh yet: https://github.com/koalaman/shellcheck/issues/809
Command::new("shellcheck") Command::new("shellcheck")
.args(["--enable=all", "-"]) .args(["--enable", "all", "--shell", "bash", "-"])
.write_stdin(source) .write_stdin(source)
.assert() .assert()
.success() .success()

View File

@ -8,7 +8,7 @@ use std::{env, mem};
#[cfg(windows)] #[cfg(windows)]
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::{Context, Result, bail}; use anyhow::{bail, Context, Result};
use crate::db::{Dir, Epoch}; use crate::db::{Dir, Epoch};
use crate::error::SilentExit; use crate::error::SilentExit;
@ -23,7 +23,7 @@ pub const MONTH: Epoch = 30 * DAY;
pub struct Fzf(Command); pub struct Fzf(Command);
impl Fzf { impl Fzf {
const ERR_FZF_NOT_FOUND: &'static str = "could not find fzf, is it installed?"; const ERR_FZF_NOT_FOUND: &str = "could not find fzf, is it installed?";
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
// On Windows, CreateProcess implicitly searches the current working // On Windows, CreateProcess implicitly searches the current working
@ -135,7 +135,7 @@ impl FzfChild {
mem::drop(self.0.stdin.take()); mem::drop(self.0.stdin.take());
let mut stdout = self.0.stdout.take().unwrap(); let mut stdout = self.0.stdout.take().unwrap();
let mut output = String::new(); let mut output = String::default();
stdout.read_to_string(&mut output).context("failed to read from fzf")?; stdout.read_to_string(&mut output).context("failed to read from fzf")?;
let status = self.0.wait().context("wait failed on fzf")?; let status = self.0.wait().context("wait failed on fzf")?;
@ -169,21 +169,16 @@ pub fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {
#[cfg(unix)] #[cfg(unix)]
if let Ok(metadata) = path.metadata() { if let Ok(metadata) = path.metadata() {
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::os::unix::io::AsRawFd;
use nix::unistd::{self, Gid, Uid}; use nix::unistd::{self, Gid, Uid};
let uid = Uid::from_raw(metadata.uid()); let uid = Uid::from_raw(metadata.uid());
let gid = Gid::from_raw(metadata.gid()); let gid = Gid::from_raw(metadata.gid());
_ = unistd::fchown(&tmp_file, Some(uid), Some(gid)); _ = unistd::fchown(tmp_file.as_raw_fd(), Some(uid), Some(gid));
} }
// Close and rename the tmpfile. // Close and rename the tmpfile.
// In some cases, errors from the last write() are reported only on close().
// Rust ignores errors from close(), since it occurs inside `Drop`. To
// catch these errors, we manually call `File::sync_all()` first.
tmp_file
.sync_all()
.with_context(|| format!("could not sync writes to file: {}", tmp_path.display()))?;
mem::drop(tmp_file); mem::drop(tmp_file);
rename(&tmp_path, path) rename(&tmp_path, path)
})(); })();

View File

@ -1,8 +1,6 @@
{%- let section = "# =============================================================================\n#" -%} {%- let section = "# =============================================================================\n#" -%}
{%- let not_configured = "# -- not configured --" -%} {%- let not_configured = "# -- not configured --" -%}
# shellcheck shell=bash
{{ section }} {{ section }}
# Utility functions for zoxide. # Utility functions for zoxide.
# #
@ -27,8 +25,11 @@ function __zoxide_cd() {
{{ section }} {{ section }}
# Hook configuration for zoxide. # Hook configuration for zoxide.
# #
{%- if hook != InitHook::None %}
{% if hook == InitHook::None -%}
{{ not_configured }}
{%- else -%}
# Hook to add new entries to the database. # Hook to add new entries to the database.
{%- if hook == InitHook::Prompt %} {%- if hook == InitHook::Prompt %}
function __zoxide_hook() { function __zoxide_hook() {
@ -37,7 +38,6 @@ function __zoxide_hook() {
\command zoxide add -- "$(__zoxide_pwd)" \command zoxide add -- "$(__zoxide_pwd)"
return "${retval}" return "${retval}"
} }
{%- else if hook == InitHook::Pwd %} {%- else if hook == InitHook::Pwd %}
__zoxide_oldpwd="$(__zoxide_pwd)" __zoxide_oldpwd="$(__zoxide_pwd)"
@ -58,32 +58,7 @@ if [[ ${PROMPT_COMMAND:=} != *'__zoxide_hook'* ]]; then
PROMPT_COMMAND="__zoxide_hook;${PROMPT_COMMAND#;}" PROMPT_COMMAND="__zoxide_hook;${PROMPT_COMMAND#;}"
fi fi
{%- endif %} {% endif -%}
# Report common issues.
function __zoxide_doctor() {
{%- if hook == InitHook::None %}
return 0
{%- else %}
[[ ${_ZO_DOCTOR:-1} -eq 0 ]] && return 0
# shellcheck disable=SC2199
[[ ${PROMPT_COMMAND[@]:-} == *'__zoxide_hook'* ]] && return 0
# shellcheck disable=SC2199
[[ ${__vsc_original_prompt_command[@]:-} == *'__zoxide_hook'* ]] && return 0
_ZO_DOCTOR=0
\builtin printf '%s\n' \
'zoxide: detected a possible configuration issue.' \
'Please ensure that zoxide is initialized right at the end of your shell configuration file (usually ~/.bashrc).' \
'' \
'If the issue persists, consider filing an issue at:' \
'https://github.com/ajeetdsouza/zoxide/issues' \
'' \
'Disable this message by setting _ZO_DOCTOR=0.' \
'' >&2
{%- endif %}
}
{{ section }} {{ section }}
# When using zoxide with --no-cmd, alias these internal functions as desired. # When using zoxide with --no-cmd, alias these internal functions as desired.
@ -93,8 +68,6 @@ __zoxide_z_prefix='z#'
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
function __zoxide_z() { function __zoxide_z() {
__zoxide_doctor
# shellcheck disable=SC2199 # shellcheck disable=SC2199
if [[ $# -eq 0 ]]; then if [[ $# -eq 0 ]]; then
__zoxide_cd ~ __zoxide_cd ~
@ -102,8 +75,6 @@ function __zoxide_z() {
__zoxide_cd "${OLDPWD}" __zoxide_cd "${OLDPWD}"
elif [[ $# -eq 1 && -d $1 ]]; then elif [[ $# -eq 1 && -d $1 ]]; then
__zoxide_cd "$1" __zoxide_cd "$1"
elif [[ $# -eq 2 && $1 == '--' ]]; then
__zoxide_cd "$2"
elif [[ ${@: -1} == "${__zoxide_z_prefix}"?* ]]; then elif [[ ${@: -1} == "${__zoxide_z_prefix}"?* ]]; then
# shellcheck disable=SC2124 # shellcheck disable=SC2124
\builtin local result="${@: -1}" \builtin local result="${@: -1}"
@ -118,7 +89,6 @@ function __zoxide_z() {
# Jump to a directory using interactive search. # Jump to a directory using interactive search.
function __zoxide_zi() { function __zoxide_zi() {
__zoxide_doctor
\builtin local result \builtin local result
result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${result}" result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${result}"
} }
@ -147,13 +117,8 @@ function {{cmd}}i() {
# - Completions don't work on `dumb` terminals. # - Completions don't work on `dumb` terminals.
if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VERSINFO[0]:-0} -ge 5 ]] && if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VERSINFO[0]:-0} -ge 5 ]] &&
[[ :"${SHELLOPTS}": =~ :(vi|emacs): && ${TERM} != 'dumb' ]]; then [[ :"${SHELLOPTS}": =~ :(vi|emacs): && ${TERM} != 'dumb' ]]; then
# Use `printf '\e[5n'` to redraw line after fzf closes.
function __zoxide_z_complete_helper() { \builtin bind '"\e[0n": redraw-current-line' &>/dev/null
READLINE_LINE="{{ cmd }} ${__zoxide_result@Q}"
READLINE_POINT={{ "${#READLINE_LINE}" }}
bind '"\e[0n": accept-line'
\builtin printf '\e[5n' >/dev/tty
}
function __zoxide_z_complete() { function __zoxide_z_complete() {
# Only show completions when the cursor is at the end of the line. # Only show completions when the cursor is at the end of the line.
@ -165,20 +130,12 @@ if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VER
\builtin compgen -A directory -- "${COMP_WORDS[-1]}" || \builtin true \builtin compgen -A directory -- "${COMP_WORDS[-1]}" || \builtin true
) )
# If there is a space after the last word, use interactive selection. # If there is a space after the last word, use interactive selection.
elif [[ -z ${COMP_WORDS[-1]} ]]; then elif [[ -z ${COMP_WORDS[-1]} ]] && [[ ${COMP_WORDS[-2]} != "${__zoxide_z_prefix}"?* ]]; then
\builtin local result
# shellcheck disable=SC2312 # shellcheck disable=SC2312
__zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" && { result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" &&
# In case the terminal does not respond to \e[5n or another COMPREPLY=("${__zoxide_z_prefix}${result}/")
# mechanism steals the response, it is still worth completing \builtin printf '\e[5n'
# the directory in the command line.
COMPREPLY=("${__zoxide_z_prefix}${__zoxide_result}/")
# Note: We here call "bind" without prefixing "\builtin" to be
# compatible with frameworks like ble.sh, which emulates Bash's
# builtin "bind".
bind -x '"\e[0n": __zoxide_z_complete_helper'
\builtin printf '\e[5n' >/dev/tty
}
fi fi
} }
@ -193,6 +150,6 @@ fi
{%- endmatch %} {%- endmatch %}
{{ section }} {{ section }}
# To initialize zoxide, add this to your shell configuration file (usually ~/.bashrc): # To initialize zoxide, add this to your configuration (usually ~/.bashrc):
# #
# eval "$(zoxide init bash)" # eval "$(zoxide init bash)"

View File

@ -22,7 +22,7 @@ fn __zoxide_cd {|path|
# Initialize hook to track previous directory. # Initialize hook to track previous directory.
var oldpwd = $builtin:pwd var oldpwd = $builtin:pwd
set builtin:before-chdir = [$@builtin:before-chdir {|_| set oldpwd = $builtin:pwd }] set builtin:before-chdir = [$@builtin:before-chdir {|_| edit:add-var oldpwd $builtin:pwd }]
# Initialize hook to add directories to zoxide. # Initialize hook to add directories to zoxide.
{%- if hook == InitHook::None %} {%- if hook == InitHook::None %}

View File

@ -19,21 +19,19 @@ end
# A copy of fish's internal cd function. This makes it possible to use # A copy of fish's internal cd function. This makes it possible to use
# `alias cd=z` without causing an infinite loop. # `alias cd=z` without causing an infinite loop.
if ! builtin functions --query __zoxide_cd_internal if ! builtin functions --query __zoxide_cd_internal
string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' <$__fish_data_dir/functions/cd.fish | source if builtin functions --query cd
builtin functions --copy cd __zoxide_cd_internal
else
alias __zoxide_cd_internal='builtin cd'
end
end end
# cd + custom logic based on the value of _ZO_ECHO. # cd + custom logic based on the value of _ZO_ECHO.
function __zoxide_cd function __zoxide_cd
if set -q __zoxide_loop
builtin echo "zoxide: infinite loop detected"
builtin echo "Avoid aliasing `cd` to `z` directly, use `zoxide init --cmd=cd fish` instead"
return 1
end
{%- if cfg!(windows) %} {%- if cfg!(windows) %}
__zoxide_loop=1 __zoxide_cd_internal (cygpath -u $argv) __zoxide_cd_internal (cygpath -u $argv)
{%- else %} {%- else %}
__zoxide_loop=1 __zoxide_cd_internal $argv __zoxide_cd_internal $argv
{%- endif %} {%- endif %}
{%- if echo %} {%- if echo %}
and __zoxide_pwd and __zoxide_pwd
@ -64,17 +62,22 @@ end
# When using zoxide with --no-cmd, alias these internal functions as desired. # When using zoxide with --no-cmd, alias these internal functions as desired.
# #
if test -z $__zoxide_z_prefix
set __zoxide_z_prefix 'z!'
end
set __zoxide_z_prefix_regex ^(string escape --style=regex $__zoxide_z_prefix)
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
function __zoxide_z function __zoxide_z
set -l argc (builtin count $argv) set -l argc (count $argv)
if test $argc -eq 0 if test $argc -eq 0
__zoxide_cd $HOME __zoxide_cd $HOME
else if test "$argv" = - else if test "$argv" = -
__zoxide_cd - __zoxide_cd -
else if test $argc -eq 1 -a -d $argv[1] else if test $argc -eq 1 -a -d $argv[1]
__zoxide_cd $argv[1] __zoxide_cd $argv[1]
else if test $argc -eq 2 -a $argv[1] = -- else if set -l result (string replace --regex $__zoxide_z_prefix_regex '' $argv[-1]); and test -n $result
__zoxide_cd -- $argv[2] __zoxide_cd $result
else else
set -l result (command zoxide query --exclude (__zoxide_pwd) -- $argv) set -l result (command zoxide query --exclude (__zoxide_pwd) -- $argv)
and __zoxide_cd $result and __zoxide_cd $result
@ -83,18 +86,19 @@ end
# Completions. # Completions.
function __zoxide_z_complete function __zoxide_z_complete
set -l tokens (builtin commandline --current-process --tokenize) set -l tokens (commandline --current-process --tokenize)
set -l curr_tokens (builtin commandline --cut-at-cursor --current-process --tokenize) set -l curr_tokens (commandline --cut-at-cursor --current-process --tokenize)
if test (builtin count $tokens) -le 2 -a (builtin count $curr_tokens) -eq 1 if test (count $tokens) -le 2 -a (count $curr_tokens) -eq 1
# If there are < 2 arguments, use `cd` completions. # If there are < 2 arguments, use `cd` completions.
complete --do-complete "'' "(builtin commandline --cut-at-cursor --current-token) | string match --regex -- '.*/$' complete --do-complete "'' "(commandline --cut-at-cursor --current-token) | string match --regex '.*/$'
else if test (builtin count $tokens) -eq (builtin count $curr_tokens) else if test (count $tokens) -eq (count $curr_tokens); and ! string match --quiet --regex $__zoxide_z_prefix_regex. $tokens[-1]
# If the last argument is empty, use interactive selection. # If the last argument is empty and the one before doesn't start with
# $__zoxide_z_prefix, use interactive selection.
set -l query $tokens[2..-1] set -l query $tokens[2..-1]
set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query) set -l result (zoxide query --exclude (__zoxide_pwd) --interactive -- $query)
and __zoxide_cd $result and echo $__zoxide_z_prefix$result
and builtin commandline --function cancel-commandline repaint commandline --function repaint
end end
end end
complete --command __zoxide_z --no-files --arguments '(__zoxide_z_complete)' complete --command __zoxide_z --no-files --arguments '(__zoxide_z_complete)'

View File

@ -12,40 +12,23 @@
{%- else -%} {%- else -%}
# Initialize hook to add new entries to the database. # Initialize hook to add new entries to the database.
export-env { if (not ($env | default false __zoxide_hooked | get __zoxide_hooked)) {
let-env __zoxide_hooked = true
{%- if hook == InitHook::Prompt %} {%- if hook == InitHook::Prompt %}
$env.config = ( let-env config = ($env | default {} config).config
$env.config? let-env config = ($env.config | default {} hooks)
| default {} let-env config = ($env.config | update hooks ($env.config.hooks | default [] pre_prompt))
| upsert hooks { default {} } let-env config = ($env.config | update hooks.pre_prompt ($env.config.hooks.pre_prompt | append { ||
| upsert hooks.pre_prompt { default [] } zoxide add -- $env.PWD
) }))
let __zoxide_hooked = (
$env.config.hooks.pre_prompt | any { try { get __zoxide_hook } catch { false } }
)
if not $__zoxide_hooked {
$env.config.hooks.pre_prompt = ($env.config.hooks.pre_prompt | append {
__zoxide_hook: true,
code: {|| ^zoxide add -- $env.PWD}
})
}
{%- else if hook == InitHook::Pwd %} {%- else if hook == InitHook::Pwd %}
$env.config = ( let-env config = ($env | default {} config).config
$env.config? let-env config = ($env.config | default {} hooks)
| default {} let-env config = ($env.config | update hooks ($env.config.hooks | default {} env_change))
| upsert hooks { default {} } let-env config = ($env.config | update hooks.env_change ($env.config.hooks.env_change | default [] PWD))
| upsert hooks.env_change { default {} } let-env config = ($env.config | update hooks.env_change.PWD ($env.config.hooks.env_change.PWD | append {|_, dir|
| upsert hooks.env_change.PWD { default [] } zoxide add -- $dir
) }))
let __zoxide_hooked = (
$env.config.hooks.env_change.PWD | any { try { get __zoxide_hook } catch { false } }
)
if not $__zoxide_hooked {
$env.config.hooks.env_change.PWD = ($env.config.hooks.env_change.PWD | append {
__zoxide_hook: true,
code: {|_, dir| ^zoxide add -- $dir}
})
}
{%- endif %} {%- endif %}
} }
@ -56,14 +39,12 @@ export-env {
# #
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
def --env --wrapped __zoxide_z [...rest: string] { def-env __zoxide_z [...rest:string] {
let path = match $rest { let arg0 = ($rest | append '~').0
[] => {'~'}, let path = if (($rest | length) <= 1) and ($arg0 == '-' or ($arg0 | path expand | path type) == dir) {
[ '-' ] => {'-'}, $arg0
[ $arg ] if ($arg | path expand | path type) == 'dir' => {$arg} } else {
_ => { (zoxide query --exclude $env.PWD -- $rest | str trim -r -c "\n")
^zoxide query --exclude $env.PWD -- ...$rest | str trim -r -c "\n"
}
} }
cd $path cd $path
{%- if echo %} {%- if echo %}
@ -72,8 +53,8 @@ def --env --wrapped __zoxide_z [...rest: string] {
} }
# Jump to a directory using interactive search. # Jump to a directory using interactive search.
def --env --wrapped __zoxide_zi [...rest:string] { def-env __zoxide_zi [...rest:string] {
cd $'(^zoxide query --interactive -- ...$rest | str trim -r -c "\n")' cd $'(zoxide query --interactive -- $rest | str trim -r -c "\n")'
{%- if echo %} {%- if echo %}
echo $env.PWD echo $env.PWD
{%- endif %} {%- endif %}
@ -105,4 +86,4 @@ alias {{cmd}}i = __zoxide_zi
# #
# source ~/.zoxide.nu # source ~/.zoxide.nu
# #
# Note: zoxide only supports Nushell v0.89.0+. # Note: zoxide only supports Nushell v0.73.0 and above.

View File

@ -1,8 +1,6 @@
{%- let section = "# =============================================================================\n#" -%} {%- let section = "# =============================================================================\n#" -%}
{%- let not_configured = "# -- not configured --" -%} {%- let not_configured = "# -- not configured --" -%}
# shellcheck shell=sh
{{ section }} {{ section }}
# Utility functions for zoxide. # Utility functions for zoxide.
# #
@ -43,30 +41,6 @@ if [ "${PS1:=}" = "${PS1#*\$(__zoxide_hook)}" ]; then
PS1="${PS1}\$(__zoxide_hook)" PS1="${PS1}\$(__zoxide_hook)"
fi fi
# Report common issues.
__zoxide_doctor() {
{%- if hook != InitHook::Prompt %}
return 0
{%- else %}
[ "${_ZO_DOCTOR:-1}" -eq 0 ] && return 0
case "${PS1:-}" in
*__zoxide_hook*) return 0 ;;
*) ;;
esac
_ZO_DOCTOR=0
\command printf '%s\n' \
'zoxide: detected a possible configuration issue.' \
'Please ensure that zoxide is initialized right at the end of your shell configuration file.' \
'' \
'If the issue persists, consider filing an issue at:' \
'https://github.com/ajeetdsouza/zoxide/issues' \
'' \
'Disable this message by setting _ZO_DOCTOR=0.' \
'' >&2
{%- endif %}
}
{%- when InitHook::Pwd -%} {%- when InitHook::Pwd -%}
\command printf "%s\n%s\n" \ \command printf "%s\n%s\n" \
"zoxide: PWD hooks are not supported on POSIX shells." \ "zoxide: PWD hooks are not supported on POSIX shells." \
@ -80,8 +54,6 @@ __zoxide_doctor() {
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
__zoxide_z() { __zoxide_z() {
__zoxide_doctor
if [ "$#" -eq 0 ]; then if [ "$#" -eq 0 ]; then
__zoxide_cd ~ __zoxide_cd ~
elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then
@ -102,7 +74,6 @@ __zoxide_z() {
# Jump to a directory using interactive search. # Jump to a directory using interactive search.
__zoxide_zi() { __zoxide_zi() {
__zoxide_doctor
__zoxide_result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${__zoxide_result}" __zoxide_result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${__zoxide_result}"
} }

View File

@ -6,7 +6,7 @@
# #
# Call zoxide binary, returning the output as UTF-8. # Call zoxide binary, returning the output as UTF-8.
function global:__zoxide_bin { function __zoxide_bin {
$encoding = [Console]::OutputEncoding $encoding = [Console]::OutputEncoding
try { try {
[Console]::OutputEncoding = [System.Text.Utf8Encoding]::new() [Console]::OutputEncoding = [System.Text.Utf8Encoding]::new()
@ -18,7 +18,7 @@ function global:__zoxide_bin {
} }
# pwd based on zoxide's format. # pwd based on zoxide's format.
function global:__zoxide_pwd { function __zoxide_pwd {
$cwd = Get-Location $cwd = Get-Location
if ($cwd.Provider.Name -eq "FileSystem") { if ($cwd.Provider.Name -eq "FileSystem") {
$cwd.ProviderPath $cwd.ProviderPath
@ -26,7 +26,7 @@ function global:__zoxide_pwd {
} }
# cd + custom logic based on the value of _ZO_ECHO. # cd + custom logic based on the value of _ZO_ECHO.
function global:__zoxide_cd($dir, $literal) { function __zoxide_cd($dir, $literal) {
$dir = if ($literal) { $dir = if ($literal) {
Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop Set-Location -LiteralPath $dir -Passthru -ErrorAction Stop
} else { } else {
@ -59,20 +59,20 @@ function global:__zoxide_cd($dir, $literal) {
-#} -#}
{%- if hook == InitHook::Prompt -%} {%- if hook == InitHook::Prompt -%}
# Hook to add new entries to the database. # Hook to add new entries to the database.
function global:__zoxide_hook { function __zoxide_hook {
$result = __zoxide_pwd $result = __zoxide_pwd
if ($null -ne $result) { if ($null -ne $result) {
zoxide add "--" $result zoxide add -- $result
} }
} }
{%- else if hook == InitHook::Pwd -%} {%- else if hook == InitHook::Pwd -%}
# Hook to add new entries to the database. # Hook to add new entries to the database.
$global:__zoxide_oldpwd = __zoxide_pwd $global:__zoxide_oldpwd = __zoxide_pwd
function global:__zoxide_hook { function __zoxide_hook {
$result = __zoxide_pwd $result = __zoxide_pwd
if ($result -ne $global:__zoxide_oldpwd) { if ($result -ne $global:__zoxide_oldpwd) {
if ($null -ne $result) { if ($null -ne $result) {
zoxide add "--" $result zoxide add -- $result
} }
$global:__zoxide_oldpwd = $result $global:__zoxide_oldpwd = $result
} }
@ -80,12 +80,12 @@ function global:__zoxide_hook {
{%- endif %} {%- endif %}
# Initialize hook. # Initialize hook.
$global:__zoxide_hooked = (Get-Variable __zoxide_hooked -ErrorAction Ignore -ValueOnly) $__zoxide_hooked = (Get-Variable __zoxide_hooked -ErrorAction SilentlyContinue -ValueOnly)
if ($global:__zoxide_hooked -ne 1) { if ($__zoxide_hooked -ne 1) {
$global:__zoxide_hooked = 1 $__zoxide_hooked = 1
$global:__zoxide_prompt_old = $function:prompt $__zoxide_prompt_old = $function:prompt
function global:prompt { function prompt {
if ($null -ne $__zoxide_prompt_old) { if ($null -ne $__zoxide_prompt_old) {
& $__zoxide_prompt_old & $__zoxide_prompt_old
} }
@ -99,26 +99,23 @@ if ($global:__zoxide_hooked -ne 1) {
# #
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
function global:__zoxide_z { function __zoxide_z {
if ($args.Length -eq 0) { if ($args.Length -eq 0) {
__zoxide_cd ~ $true __zoxide_cd ~ $true
} }
elseif ($args.Length -eq 1 -and ($args[0] -eq '-' -or $args[0] -eq '+')) { elseif ($args.Length -eq 1 -and ($args[0] -eq '-' -or $args[0] -eq '+')) {
__zoxide_cd $args[0] $false __zoxide_cd $args[0] $false
} }
elseif ($args.Length -eq 1 -and (Test-Path -PathType Container -LiteralPath $args[0])) { elseif ($args.Length -eq 1 -and (Test-Path $args[0] -PathType Container)) {
__zoxide_cd $args[0] $true __zoxide_cd $args[0] $true
} }
elseif ($args.Length -eq 1 -and (Test-Path -PathType Container -Path $args[0] )) {
__zoxide_cd $args[0] $false
}
else { else {
$result = __zoxide_pwd $result = __zoxide_pwd
if ($null -ne $result) { if ($null -ne $result) {
$result = __zoxide_bin query --exclude $result "--" @args $result = __zoxide_bin query --exclude $result -- @args
} }
else { else {
$result = __zoxide_bin query "--" @args $result = __zoxide_bin query -- @args
} }
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
__zoxide_cd $result $true __zoxide_cd $result $true
@ -127,8 +124,8 @@ function global:__zoxide_z {
} }
# Jump to a directory using interactive search. # Jump to a directory using interactive search.
function global:__zoxide_zi { function __zoxide_zi {
$result = __zoxide_bin query -i "--" @args $result = __zoxide_bin query -i -- @args
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
__zoxide_cd $result $true __zoxide_cd $result $true
} }

View File

@ -1,74 +0,0 @@
{%- let section = "# =============================================================================\n#" -%}
{%- let not_configured = "# -- not configured --" -%}
{%- let pwd_cmd -%}
{%- if resolve_symlinks -%}
{%- let pwd_cmd = "pwd -P" -%}
{%- else -%}
{%- let pwd_cmd = "pwd -L" -%}
{%- endif -%}
{{ section }}
# Hook configuration for zoxide.
#
{%- if hook != InitHook::None %}
# Hook to add new entries to the database.
{%- if hook == InitHook::Prompt %}
alias __zoxide_hook 'zoxide add -- "`{{ pwd_cmd }}`"'
{%- else if hook == InitHook::Pwd %}
set __zoxide_pwd_old = `{{ pwd_cmd }}`
alias __zoxide_hook 'set __zoxide_pwd_tmp = "`{{ pwd_cmd }}`"; test "$__zoxide_pwd_tmp" != "$__zoxide_pwd_old" && zoxide add -- "$__zoxide_pwd_tmp"; set __zoxide_pwd_old = "$__zoxide_pwd_tmp"'
{%- endif %}
# Initialize hook.
alias precmd ';__zoxide_hook'
{%- endif %}
{{ section }}
# When using zoxide with --no-cmd, alias these internal functions as desired.
#
# Jump to a directory using only keywords.
alias __zoxide_z 'set __zoxide_args = (\!*)\
if ("$#__zoxide_args" == 0) then\
cd ~\
else\
if ("$#__zoxide_args" == 1 && "$__zoxide_args[1]" == "-") then\
cd -\
else if ("$#__zoxide_args" == 1 && -d "$__zoxide_args[1]") then\
cd "$__zoxide_args[1]"\
else\
set __zoxide_pwd = `{{ pwd_cmd }}`\
set __zoxide_result = "`zoxide query --exclude '"'"'$__zoxide_pwd'"'"' -- $__zoxide_args`" && cd "$__zoxide_result"\
endif\
endif'
# Jump to a directory using interactive search.
alias __zoxide_zi 'set __zoxide_args = (\!*)\
set __zoxide_pwd = `{{ pwd_cmd }}`\
set __zoxide_result = "`zoxide query --exclude '"'"'$__zoxide_pwd'"'"' --interactive -- $__zoxide_args`" && cd "$__zoxide_result"'
{{ section }}
# Commands for zoxide. Disable these using --no-cmd.
#
{%- match cmd %}
{%- when Some with (cmd) %}
alias {{cmd}} __zoxide_z
alias {{cmd}}i __zoxide_zi
{%- when None %}
{{ not_configured }}
{%- endmatch %}
{{ section }}
# To initialize zoxide, add this to your shell configuration file (usually ~/.tcshrc):
#
# zoxide init tcsh > ~/.zoxide.tcsh
# source ~/.zoxide.tcsh

View File

@ -26,7 +26,7 @@ def __zoxide_bin() -> str:
return zoxide return zoxide
def __zoxide_env() -> dict[str, str]: def __zoxide_env() -> typing.Dict[str, str]:
"""Returns the current environment.""" """Returns the current environment."""
return builtins.__xonsh__.env.detype() # type: ignore # pylint:disable=no-member return builtins.__xonsh__.env.detype() # type: ignore # pylint:disable=no-member
@ -38,22 +38,22 @@ def __zoxide_pwd() -> str:
{%- else %} {%- else %}
pwd = __zoxide_env().get("PWD") pwd = __zoxide_env().get("PWD")
if pwd is None: if pwd is None:
raise RuntimeError("$PWD not found") raise Exception("$PWD not found")
{%- endif %} {%- endif %}
return pwd return pwd
def __zoxide_cd(path: str | bytes | None = None) -> None: def __zoxide_cd(path: typing.Optional[typing.AnyStr] = None) -> None:
"""cd + custom logic based on the value of _ZO_ECHO.""" """cd + custom logic based on the value of _ZO_ECHO."""
if path is None: if path is None:
args = [] args = []
elif isinstance(path, bytes): elif isinstance(path, bytes):
args = [path.decode("utf-8")] args = [path.decode("utf-8")]
else: elif isinstance(path, str):
args = [path] args = [path]
_, exc, _ = xonsh.dirstack.cd(args) _, exc, _ = xonsh.dirstack.cd(args)
if exc is not None: if exc is not None:
raise RuntimeError(exc) raise Exception(exc)
{%- if echo %} {%- if echo %}
print(__zoxide_pwd()) print(__zoxide_pwd())
{%- endif %} {%- endif %}
@ -64,11 +64,11 @@ class ZoxideSilentException(Exception):
def __zoxide_errhandler( def __zoxide_errhandler(
func: typing.Callable[[list[str]], None], func: typing.Callable[[typing.List[str]], None]
) -> typing.Callable[[list[str]], int]: ) -> typing.Callable[[typing.List[str]], int]:
"""Print exception and exit with error code 1.""" """Print exception and exit with error code 1."""
def wrapper(args: list[str]) -> int: def wrapper(args: typing.List[str]) -> int:
try: try:
func(args) func(args)
return 0 return 0
@ -113,7 +113,7 @@ if "__zoxide_hook" not in globals():
@__zoxide_errhandler @__zoxide_errhandler
def __zoxide_z(args: list[str]) -> None: def __zoxide_z(args: typing.List[str]) -> None:
"""Jump to a directory using only keywords.""" """Jump to a directory using only keywords."""
if args == []: if args == []:
__zoxide_cd() __zoxide_cd()
@ -138,7 +138,7 @@ def __zoxide_z(args: list[str]) -> None:
@__zoxide_errhandler @__zoxide_errhandler
def __zoxide_zi(args: list[str]) -> None: def __zoxide_zi(args: typing.List[str]) -> None:
"""Jump to a directory using interactive search.""" """Jump to a directory using interactive search."""
try: try:
zoxide = __zoxide_bin() zoxide = __zoxide_bin()

View File

@ -1,8 +1,6 @@
{%- let section = "# =============================================================================\n#" -%} {%- let section = "# =============================================================================\n#" -%}
{%- let not_configured = "# -- not configured --" -%} {%- let not_configured = "# -- not configured --" -%}
# shellcheck shell=bash
{{ section }} {{ section }}
# Utility functions for zoxide. # Utility functions for zoxide.
# #
@ -28,6 +26,10 @@ function __zoxide_cd() {
# Hook configuration for zoxide. # Hook configuration for zoxide.
# #
{% if hook == InitHook::None -%}
{{ not_configured -}}
{% else -%}
# Hook to add new entries to the database. # Hook to add new entries to the database.
function __zoxide_hook() { function __zoxide_hook() {
# shellcheck disable=SC2312 # shellcheck disable=SC2312
@ -35,73 +37,74 @@ function __zoxide_hook() {
} }
# Initialize hook. # Initialize hook.
\builtin typeset -ga precmd_functions # shellcheck disable=SC2154
\builtin typeset -ga chpwd_functions if [[ ${precmd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]] && [[ ${chpwd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]]; then
# shellcheck disable=SC2034,SC2296
precmd_functions=("${(@)precmd_functions:#__zoxide_hook}")
# shellcheck disable=SC2034,SC2296
chpwd_functions=("${(@)chpwd_functions:#__zoxide_hook}")
{%- if hook == InitHook::Prompt %} {%- if hook == InitHook::Prompt %}
precmd_functions+=(__zoxide_hook) precmd_functions+=(__zoxide_hook)
{%- else if hook == InitHook::Pwd %} {%- else if hook == InitHook::Pwd %}
chpwd_functions+=(__zoxide_hook) chpwd_functions+=(__zoxide_hook)
{%- endif %} {%- endif %}
fi
# Report common issues.
function __zoxide_doctor() {
{%- if hook == InitHook::None %}
return 0
{%- else %}
[[ ${_ZO_DOCTOR:-1} -ne 0 ]] || return 0
{%- if hook == InitHook::Prompt %}
[[ ${precmd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]] || return 0
{%- else if hook == InitHook::Pwd %}
[[ ${chpwd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]] || return 0
{%- endif %} {%- endif %}
_ZO_DOCTOR=0
\builtin printf '%s\n' \
'zoxide: detected a possible configuration issue.' \
'Please ensure that zoxide is initialized right at the end of your shell configuration file (usually ~/.zshrc).' \
'' \
'If the issue persists, consider filing an issue at:' \
'https://github.com/ajeetdsouza/zoxide/issues' \
'' \
'Disable this message by setting _ZO_DOCTOR=0.' \
'' >&2
{%- endif %}
}
{{ section }} {{ section }}
# When using zoxide with --no-cmd, alias these internal functions as desired. # When using zoxide with --no-cmd, alias these internal functions as desired.
# #
__zoxide_z_prefix='z#'
# Jump to a directory using only keywords. # Jump to a directory using only keywords.
function __zoxide_z() { function __zoxide_z() {
__zoxide_doctor # shellcheck disable=SC2199
if [[ "$#" -eq 0 ]]; then if [[ "$#" -eq 0 ]]; then
__zoxide_cd ~ __zoxide_cd ~
elif [[ "$#" -eq 1 ]] && { [[ -d "$1" ]] || [[ "$1" = '-' ]] || [[ "$1" =~ ^[-+][0-9]+$ ]]; }; then elif [[ "$#" -eq 1 ]] && { [[ -d "$1" ]] || [[ "$1" = '-' ]] || [[ "$1" =~ ^[-+][0-9]$ ]]; }; then
__zoxide_cd "$1" __zoxide_cd "$1"
elif [[ "$#" -eq 2 ]] && [[ "$1" = "--" ]]; then elif [[ "$@[-1]" == "${__zoxide_z_prefix}"?* ]]; then
__zoxide_cd "$2" # shellcheck disable=SC2124
\builtin local result="${@[-1]}"
__zoxide_cd "{{ "${result:${#__zoxide_z_prefix}}" }}"
else else
\builtin local result \builtin local result
# shellcheck disable=SC2312 # shellcheck disable=SC2312
result="$(\command zoxide query --exclude "$(__zoxide_pwd)" -- "$@")" && __zoxide_cd "${result}" result="$(\command zoxide query --exclude "$(__zoxide_pwd)" -- "$@")" &&
__zoxide_cd "${result}"
fi fi
} }
# Jump to a directory using interactive search. # Jump to a directory using interactive search.
function __zoxide_zi() { function __zoxide_zi() {
__zoxide_doctor
\builtin local result \builtin local result
result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${result}" result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${result}"
} }
# Completions.
if [[ -o zle ]]; then
function __zoxide_z_complete() {
# Only show completions when the cursor is at the end of the line.
# shellcheck disable=SC2154
[[ "{{ "${#words[@]}" }}" -eq "${CURRENT}" ]] || return 0
if [[ "{{ "${#words[@]}" }}" -eq 2 ]]; then
_files -/
elif [[ "${words[-1]}" == '' ]] && [[ "${words[-2]}" != "${__zoxide_z_prefix}"?* ]]; then
\builtin local result
# shellcheck disable=SC2086,SC2312
if result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- ${words[2,-1]})"; then
result="${__zoxide_z_prefix}${result}"
# shellcheck disable=SC2296
compadd -Q "${(q-)result}"
fi
\builtin printf '\e[5n'
fi
return 0
}
\builtin bindkey '\e[0n' 'reset-prompt'
[[ "${+functions[compdef]}" -ne 0 ]] && \compdef __zoxide_z_complete __zoxide_z
fi
{{ section }} {{ section }}
# Commands for zoxide. Disable these using --no-cmd. # Commands for zoxide. Disable these using --no-cmd.
# #
@ -109,13 +112,8 @@ function __zoxide_zi() {
{%- match cmd %} {%- match cmd %}
{%- when Some with (cmd) %} {%- when Some with (cmd) %}
function {{ cmd }}() { \builtin alias {{cmd}}=__zoxide_z
__zoxide_z "$@" \builtin alias {{cmd}}i=__zoxide_zi
}
function {{ cmd }}i() {
__zoxide_zi "$@"
}
{%- when None %} {%- when None %}
@ -123,57 +121,7 @@ function {{ cmd }}i() {
{%- endmatch %} {%- endmatch %}
# Completions.
if [[ -o zle ]]; then
__zoxide_result=''
function __zoxide_z_complete() {
# Only show completions when the cursor is at the end of the line.
# shellcheck disable=SC2154
[[ "{{ "${#words[@]}" }}" -eq "${CURRENT}" ]] || return 0
if [[ "{{ "${#words[@]}" }}" -eq 2 ]]; then
# Show completions for local directories.
_cd -/
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=''
# Set a result to ensure completion doesn't re-run
compadd -Q ""
# Bind '\e[0n' to helper function.
\builtin bindkey '\e[0n' '__zoxide_z_complete_helper'
# Sends query device status code, which results in a '\e[0n' being sent to console input.
\builtin printf '\e[5n'
# Report that the completion was successful, so that we don't fall back
# to another completion function.
return 0
fi
}
function __zoxide_z_complete_helper() {
if [[ -n "${__zoxide_result}" ]]; then
# shellcheck disable=SC2034,SC2296
BUFFER="{{ cmd.unwrap_or("cd") }} ${(q-)__zoxide_result}"
__zoxide_result=''
\builtin zle reset-prompt
\builtin zle accept-line
else
\builtin zle reset-prompt
fi
}
\builtin zle -N __zoxide_z_complete_helper
{%- if let Some(cmd) = cmd %}
[[ "${+functions[compdef]}" -ne 0 ]] && \compdef __zoxide_z_complete {{ cmd }}
{%- endif %}
fi
{{ section }} {{ section }}
# To initialize zoxide, add this to your shell configuration file (usually ~/.zshrc): # To initialize zoxide, add this to your configuration (usually ~/.zshrc):
# #
# eval "$(zoxide init zsh)" # eval "$(zoxide init zsh)"