Merge branch 'main' into query-i-s
This commit is contained in:
commit
086867f335
|
|
@ -10,9 +10,12 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
# FIXME: Enable macos-latest when this is merged: https://nixpk.gs/pr-tracker.html?pr=163924
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
if: ${{ matrix.os == 'windows-latest' }}
|
if: ${{ matrix.os == 'windows-latest' }}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
# Compiled files and executables
|
# Compiled files and executables
|
||||||
debug/
|
debug/
|
||||||
target/
|
target/
|
||||||
|
target_nix/
|
||||||
|
|
||||||
# Backup files generated by rustfmt
|
# Backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
|
||||||
25
CHANGELOG.md
25
CHANGELOG.md
|
|
@ -11,12 +11,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- manpages: moved to `man/man1/*.1`.
|
- Manpages: moved to `man/man1/*.1`.
|
||||||
|
- Replace `--no-aliases` with `--no-cmd`.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Rename `_z` completion function to avoid conflicts with other shell plugins.
|
- Bash/Zsh: rename `_z` completion function to avoid conflicts with other shell
|
||||||
|
plugins.
|
||||||
- Elvish: upgrade to new lambda syntax.
|
- Elvish: upgrade to new lambda syntax.
|
||||||
|
- Fzf: added `--keep-right` option by default, upgrade minimum supported version
|
||||||
|
to v0.21.0.
|
||||||
|
- Bash: only enable completions on 4.4+.
|
||||||
|
- Fzf: bypass `ls` alias in preview window.
|
||||||
|
- Retain ownership of database file.
|
||||||
|
- Elvish: upgrade to new try-catch syntax, upgrade minimum supported version to
|
||||||
|
v0.18.0.
|
||||||
|
|
||||||
## [0.8.0] - 2021-12-25
|
## [0.8.0] - 2021-12-25
|
||||||
|
|
||||||
|
|
@ -27,7 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Fzf: better default options.
|
- Fzf: better default options.
|
||||||
- Fish: interactive completions are only triggered when the last argument is empty.
|
- Fish: interactive completions are only triggered when the last argument is
|
||||||
|
empty.
|
||||||
- PowerShell: installation instructions.
|
- PowerShell: installation instructions.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
@ -128,7 +138,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- Auto-generated shell completions.
|
- Auto-generated shell completions.
|
||||||
- `zoxide query --all` for listing deleted directories.
|
- `zoxide query --all` for listing deleted directories.
|
||||||
- Lazy deletion for removed directories that have not been accessed in > 90 days.
|
- Lazy deletion for removed directories that have not been accessed in > 90
|
||||||
|
days.
|
||||||
- Nushell: support for 0.32.0+.
|
- Nushell: support for 0.32.0+.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
@ -155,7 +166,8 @@ 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 bash.
|
- `__zoxide_hook` no longer changes value of `$?` within `$PROMPT_COMMAND` on
|
||||||
|
bash.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
@ -192,7 +204,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `$_ZO_EXCLUDE_DIRS` now supports globs.
|
- `$_ZO_EXCLUDE_DIRS` now supports globs.
|
||||||
- `zoxide init` now defines `__zoxide_z*` functions that can be aliased as needed.
|
- `zoxide init` now defines `__zoxide_z*` functions that can be aliased as
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.52"
|
version = "1.0.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
|
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama"
|
name = "askama"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d8f355701c672c2ba3d718acbd213f740beea577cc4eae66accdffe15be1882"
|
checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_derive",
|
"askama_derive",
|
||||||
"askama_escape",
|
"askama_escape",
|
||||||
|
|
@ -30,9 +30,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama_derive"
|
name = "askama_derive"
|
||||||
version = "0.11.0"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84704cab5b7ae0fd3a9f78ee5eb7b27f3749df445f04623db6633459ae283267"
|
checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_shared",
|
"askama_shared",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -41,17 +41,19 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama_escape"
|
name = "askama_escape"
|
||||||
version = "0.10.2"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a1bb320f97e6edf9f756bf015900038e43c7700e059688e5724a928c8f3b8d5"
|
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama_shared"
|
name = "askama_shared"
|
||||||
version = "0.12.0"
|
version = "0.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dae03eebba55a2697a376e58b573a29fe36893157173ac8df312ad85f3c0e012"
|
checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_escape",
|
"askama_escape",
|
||||||
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
"nom",
|
"nom",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -85,9 +87,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
|
|
@ -115,6 +117,12 @@ dependencies = [
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
@ -123,9 +131,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.0.10"
|
version = "3.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375"
|
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|
@ -140,18 +148,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_complete"
|
name = "clap_complete"
|
||||||
version = "3.0.4"
|
version = "3.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d044e9db8cd0f68191becdeb5246b7462e4cf0c069b19ae00d1bf3fa9889498d"
|
checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_complete_fig"
|
name = "clap_complete_fig"
|
||||||
version = "3.0.2"
|
version = "3.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29cc003d824770d10072f4aa4a958e66d33d74a9cb7339595ac2a445d80d50a0"
|
checksum = "690eb5abb7a98df1a64a3028beaf95af7e0ceb13da3186e6d0a86161af76309e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
|
|
@ -159,9 +167,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "3.0.6"
|
version = "3.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153"
|
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
|
|
@ -172,9 +180,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.6"
|
version = "0.8.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
|
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
@ -197,9 +205,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.3.6"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
|
|
@ -226,9 +234,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2"
|
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
@ -241,9 +249,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.4"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -310,9 +318,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
|
@ -344,15 +352,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.113"
|
version = "0.2.122"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9"
|
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
@ -363,6 +371,31 @@ version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|
@ -370,14 +403,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nix"
|
||||||
version = "7.1.0"
|
version = "0.23.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
|
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"memoffset",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
"version_check",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -391,9 +436,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.9.0"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
|
|
@ -466,64 +511,47 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.36"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.14"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.8.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.6.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.10"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.0"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.5.4"
|
version = "1.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -564,6 +592,17 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstest_reuse"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b29d3117bce27ea307d1fb7ce12c64ba11b3fd04311a42d32bc5f0072e6e3d4d"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -584,24 +623,24 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.4"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.133"
|
version = "1.0.136"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.133"
|
version = "1.0.136"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -610,9 +649,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shell-words"
|
name = "shell-words"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
|
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
|
|
@ -622,9 +661,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.86"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -647,9 +686,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.2"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
@ -662,9 +701,9 @@ checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.14.2"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
|
|
@ -688,13 +727,22 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
@ -787,11 +835,12 @@ dependencies = [
|
||||||
"clap_complete_fig",
|
"clap_complete_fig",
|
||||||
"dirs",
|
"dirs",
|
||||||
"dunce",
|
"dunce",
|
||||||
|
"fastrand",
|
||||||
"glob",
|
"glob",
|
||||||
|
"nix",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
"rand",
|
|
||||||
"rstest",
|
"rstest",
|
||||||
|
"rstest_reuse",
|
||||||
"serde",
|
"serde",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
26
Cargo.toml
26
Cargo.toml
|
|
@ -7,7 +7,7 @@ keywords = ["cli"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "zoxide"
|
name = "zoxide"
|
||||||
repository = "https://github.com/ajeetdsouza/zoxide"
|
repository = "https://github.com/ajeetdsouza/zoxide"
|
||||||
rust-version = "1.56"
|
rust-version = "1.59"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|
@ -20,35 +20,33 @@ members = ["xtask/"]
|
||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
askama = { version = "0.11.0", default-features = false }
|
askama = { version = "0.11.0", default-features = false }
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
clap = { version = "3.0.0", features = ["derive"] }
|
clap = { version = "3.1.0", features = ["derive"] }
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
dunce = "1.0.1"
|
dunce = "1.0.1"
|
||||||
|
fastrand = "1.7.0"
|
||||||
glob = "0.3.0"
|
glob = "0.3.0"
|
||||||
ordered-float = "2.0.0"
|
ordered-float = "2.0.0"
|
||||||
serde = { version = "1.0.116", features = ["derive"] }
|
serde = { version = "1.0.116", features = ["derive"] }
|
||||||
tempfile = "3.1.0"
|
|
||||||
thiserror = "1.0.30"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
rand = { version = "0.8.4", features = [
|
nix = "0.23.1"
|
||||||
"getrandom",
|
|
||||||
"small_rng",
|
|
||||||
], default-features = false }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "3.0.0", features = ["derive"] }
|
clap = { version = "3.1.0", features = ["derive"] }
|
||||||
clap_complete = "3.0.0"
|
clap_complete = "3.1.0"
|
||||||
clap_complete_fig = "3.0.0"
|
clap_complete_fig = "3.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "2.0.0"
|
assert_cmd = "2.0.0"
|
||||||
rstest = "0.12.0"
|
rstest = "0.12.0"
|
||||||
|
rstest_reuse = "0.3.0"
|
||||||
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
nix = []
|
nix-dev = []
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
lto = true
|
lto = true
|
||||||
# strip = true
|
strip = true
|
||||||
|
|
|
||||||
49
README.md
49
README.md
|
|
@ -44,7 +44,7 @@ z - # cd into previous directory
|
||||||
|
|
||||||
zi foo # cd with interactive selection (using fzf)
|
zi foo # cd with interactive selection (using fzf)
|
||||||
|
|
||||||
z foo<SPACE><TAB> # show interactive completions (zoxide v0.8.0+, bash/fish/zsh only)
|
z foo<SPACE><TAB> # show interactive completions (zoxide v0.8.0+, bash 4.4+/fish/zsh only)
|
||||||
```
|
```
|
||||||
|
|
||||||
Read more about the matching algorithm [here][algorithm-matching].
|
Read more about the matching algorithm [here][algorithm-matching].
|
||||||
|
|
@ -171,7 +171,7 @@ Add this to your configuration (usually `~/.elvish/rc.elv`):
|
||||||
eval (zoxide init elvish | slurp)
|
eval (zoxide init elvish | slurp)
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: zoxide only supports elvish v0.16.0 and above.
|
Note: zoxide only supports elvish v0.18.0 and above.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -241,8 +241,9 @@ Add this to your configuration (usually `~/.zshrc`):
|
||||||
eval "$(zoxide init zsh)"
|
eval "$(zoxide init zsh)"
|
||||||
```
|
```
|
||||||
|
|
||||||
For completions to work, the above line must be added _after_ `compinit` is
|
For completions to work, the above line must be added *after* `compinit` is
|
||||||
called. You may have to rebuild your cache by running `rm ~/.zcompdump*; compinit`.
|
called. You may have to rebuild your cache by running
|
||||||
|
`rm ~/.zcompdump*; compinit`.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -260,7 +261,8 @@ eval "$(zoxide init posix --hook prompt)"
|
||||||
### *Step 3: Install fzf (optional)*
|
### *Step 3: Install fzf (optional)*
|
||||||
|
|
||||||
[fzf] is a command-line fuzzy finder, used by zoxide for interactive
|
[fzf] is a command-line fuzzy finder, used by zoxide for interactive
|
||||||
selection. It can be installed from [here][fzf-installation].
|
selection. It can be installed from [here][fzf-installation]. zoxide supports
|
||||||
|
fzf v0.21.0+.
|
||||||
|
|
||||||
### *Step 4: Import your data (optional)*
|
### *Step 4: Import your data (optional)*
|
||||||
|
|
||||||
|
|
@ -292,8 +294,8 @@ zoxide import --from z path/to/db
|
||||||
When calling `zoxide init`, the following flags are available:
|
When calling `zoxide init`, the following flags are available:
|
||||||
|
|
||||||
- `--cmd`
|
- `--cmd`
|
||||||
- Changes the prefix of predefined aliases (`z`, `zi`).
|
- Changes the prefix of the `z` and `zi` commands.
|
||||||
- `--cmd j` would change the aliases to (`j`, `ji`).
|
- `--cmd j` would change the commands to (`j`, `ji`).
|
||||||
- `--cmd cd` would replace the `cd` command (doesn't work on Nushell / POSIX shells).
|
- `--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:
|
||||||
|
|
@ -302,8 +304,8 @@ When calling `zoxide init`, the following flags are available:
|
||||||
| `none` | Never |
|
| `none` | Never |
|
||||||
| `prompt` | At every shell prompt |
|
| `prompt` | At every shell prompt |
|
||||||
| `pwd` | Whenever the directory is changed |
|
| `pwd` | Whenever the directory is changed |
|
||||||
- `--no-aliases`
|
- `--no-cmd`
|
||||||
- Don't define aliases (`z`, `zi`).
|
- 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
|
||||||
`__zoxide_zi`, should you choose to redefine them.
|
`__zoxide_zi`, should you choose to redefine them.
|
||||||
|
|
||||||
|
|
@ -319,7 +321,7 @@ They must be set before `zoxide init` is called.
|
||||||
| ----------- | ---------------------------------------- | ------------------------------------------ |
|
| ----------- | ---------------------------------------- | ------------------------------------------ |
|
||||||
| 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 | `{FOLDERID_RoamingAppData}` | `C:\Users\Alice\AppData\Roaming` |
|
| 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.
|
||||||
|
|
@ -345,16 +347,19 @@ They must be set before `zoxide init` is called.
|
||||||
|
|
||||||
## Third-party integrations
|
## Third-party integrations
|
||||||
|
|
||||||
| Application | Description | Plugin |
|
| Application | Description | Plugin |
|
||||||
| ------------------ | --------------------------------------- | -------------------------- |
|
| ------------------ | -------------------------------------------- | -------------------------- |
|
||||||
| [emacs] | Text editor | [zoxide.el] |
|
| [clink] | Improved cmd.exe for Windows | [clink-zoxide] |
|
||||||
| [nnn] | File manager | [nnn-autojump] |
|
| [emacs] | Text editor | [zoxide.el] |
|
||||||
| [ranger] | File manager | [ranger-zoxide] |
|
| [felix] | File manager | Natively supported |
|
||||||
| [telescope.nvim] | Fuzzy finder for Neovim | [telescope-zoxide] |
|
| [nnn] | File manager | [nnn-autojump] |
|
||||||
| [vim] | Text editor | [zoxide.vim] |
|
| [ranger] | File manager | [ranger-zoxide] |
|
||||||
| [xplr] | File manager | [zoxide.xplr] |
|
| [telescope.nvim] | Fuzzy finder for Neovim | [telescope-zoxide] |
|
||||||
| [xxh] | Transports shell configuration over SSH | [xxh-plugin-prerun-zoxide] |
|
| [vim] | Text editor | [zoxide.vim] |
|
||||||
| [zsh-autocomplete] | Realtime completions for zsh | Supported by default |
|
| [xplr] | File manager | [zoxide.xplr] |
|
||||||
|
| [xxh] | Transports shell configuration over SSH | [xxh-plugin-prerun-zoxide] |
|
||||||
|
| [zabb] | Finds the shortest possible query for a path | Natively supported |
|
||||||
|
| [zsh-autocomplete] | Realtime completions for zsh | Natively supported |
|
||||||
|
|
||||||
[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
|
||||||
|
|
@ -363,6 +368,8 @@ They must be set before `zoxide init` is called.
|
||||||
[builtwithnix-badge]: https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square
|
[builtwithnix-badge]: https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square
|
||||||
[builtwithnix]: https://builtwithnix.org/
|
[builtwithnix]: https://builtwithnix.org/
|
||||||
[chocolatey]: https://community.chocolatey.org/packages/zoxide
|
[chocolatey]: https://community.chocolatey.org/packages/zoxide
|
||||||
|
[clink-zoxide]: https://github.com/shunsambongi/clink-zoxide
|
||||||
|
[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/
|
[copr]: https://copr.fedorainfracloud.org/coprs/atim/zoxide/
|
||||||
[crates.io-badge]: https://img.shields.io/crates/v/zoxide?style=flat-square
|
[crates.io-badge]: https://img.shields.io/crates/v/zoxide?style=flat-square
|
||||||
|
|
@ -373,6 +380,7 @@ They must be set before `zoxide init` is called.
|
||||||
[dports]: https://github.com/DragonFlyBSD/DPorts/tree/master/sysutils/zoxide
|
[dports]: https://github.com/DragonFlyBSD/DPorts/tree/master/sysutils/zoxide
|
||||||
[emacs]: https://www.gnu.org/software/emacs/
|
[emacs]: https://www.gnu.org/software/emacs/
|
||||||
[fedora packages]: https://src.fedoraproject.org/rpms/rust-zoxide
|
[fedora packages]: https://src.fedoraproject.org/rpms/rust-zoxide
|
||||||
|
[felix]: https://github.com/kyoheiu/felix
|
||||||
[freshports]: https://www.freshports.org/sysutils/zoxide/
|
[freshports]: https://www.freshports.org/sysutils/zoxide/
|
||||||
[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
|
||||||
|
|
@ -404,6 +412,7 @@ They must be set before `zoxide init` is called.
|
||||||
[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
|
||||||
|
[zabb]: https://github.com/Mellbourn/zabb
|
||||||
[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
|
||||||
|
|
|
||||||
24
build.rs
24
build.rs
|
|
@ -32,25 +32,25 @@ fn git_version() -> Option<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_completions() -> io::Result<()> {
|
fn generate_completions() -> io::Result<()> {
|
||||||
#[path = "src/app/_app.rs"]
|
#[path = "src/cmd/_cmd.rs"]
|
||||||
mod app;
|
mod cmd;
|
||||||
|
|
||||||
use app::App;
|
use clap::CommandFactory;
|
||||||
use clap::IntoApp;
|
|
||||||
use clap_complete::generate_to;
|
use clap_complete::generate_to;
|
||||||
use clap_complete::Shell::{Bash, Elvish, Fish, PowerShell, Zsh};
|
use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh};
|
||||||
use clap_complete_fig::Fig;
|
use clap_complete_fig::Fig;
|
||||||
|
use cmd::Cmd;
|
||||||
|
|
||||||
let app = &mut App::into_app();
|
let cmd = &mut Cmd::command();
|
||||||
let bin_name = env!("CARGO_PKG_NAME");
|
let bin_name = env!("CARGO_PKG_NAME");
|
||||||
let out_dir = "contrib/completions";
|
let out_dir = "contrib/completions";
|
||||||
|
|
||||||
generate_to(Bash, app, bin_name, out_dir)?;
|
generate_to(Bash, cmd, bin_name, out_dir)?;
|
||||||
generate_to(Elvish, app, bin_name, out_dir)?;
|
generate_to(Elvish, cmd, bin_name, out_dir)?;
|
||||||
generate_to(Fig, app, bin_name, out_dir)?;
|
generate_to(Fig, cmd, bin_name, out_dir)?;
|
||||||
generate_to(Fish, app, bin_name, out_dir)?;
|
generate_to(Fish, cmd, bin_name, out_dir)?;
|
||||||
generate_to(PowerShell, app, bin_name, out_dir)?;
|
generate_to(PowerShell, cmd, bin_name, out_dir)?;
|
||||||
generate_to(Zsh, app, bin_name, out_dir)?;
|
generate_to(Zsh, cmd, bin_name, out_dir)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,9 @@ _arguments "${_arguments_options[@]}" \
|
||||||
;;
|
;;
|
||||||
(init)
|
(init)
|
||||||
_arguments "${_arguments_options[@]}" \
|
_arguments "${_arguments_options[@]}" \
|
||||||
'--cmd=[Renames the '\''z'\'' command and corresponding aliases]:CMD: ' \
|
'--cmd=[Changes the prefix of the `z` and `zi` commands]:CMD: ' \
|
||||||
'--hook=[Chooses event upon which an entry is added to the database]:HOOK:(none prompt pwd)' \
|
'--hook=[Changes how often zoxide increments a directory'\''s score]:HOOK:(none prompt pwd)' \
|
||||||
'--no-aliases[Prevents zoxide from defining any commands]' \
|
'--no-cmd[Prevents zoxide from defining the `z` and `zi` commands]' \
|
||||||
'-h[Print help information]' \
|
'-h[Print help information]' \
|
||||||
'--help[Print help information]' \
|
'--help[Print help information]' \
|
||||||
'-V[Print version information]' \
|
'-V[Print version information]' \
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
|
||||||
$element = $commandElements[$i]
|
$element = $commandElements[$i]
|
||||||
if ($element -isnot [StringConstantExpressionAst] -or
|
if ($element -isnot [StringConstantExpressionAst] -or
|
||||||
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
||||||
$element.Value.StartsWith('-')) {
|
$element.Value.StartsWith('-') -or
|
||||||
|
$element.Value -eq $wordToComplete) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
$element.Value
|
$element.Value
|
||||||
|
|
@ -48,9 +49,9 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
'zoxide;init' {
|
'zoxide;init' {
|
||||||
[CompletionResult]::new('--cmd', 'cmd', [CompletionResultType]::ParameterName, 'Renames the ''z'' command and corresponding aliases')
|
[CompletionResult]::new('--cmd', 'cmd', [CompletionResultType]::ParameterName, 'Changes the prefix of the `z` and `zi` commands')
|
||||||
[CompletionResult]::new('--hook', 'hook', [CompletionResultType]::ParameterName, 'Chooses event upon which an entry is added to the database')
|
[CompletionResult]::new('--hook', 'hook', [CompletionResultType]::ParameterName, 'Changes how often zoxide increments a directory''s score')
|
||||||
[CompletionResult]::new('--no-aliases', 'no-aliases', [CompletionResultType]::ParameterName, 'Prevents zoxide from defining any 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 information')
|
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information')
|
||||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
|
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
|
||||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information')
|
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information')
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ _zoxide() {
|
||||||
fi
|
fi
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--from)
|
--from)
|
||||||
COMPREPLY=($(compgen -W "autojump z" -- "${cur}"))
|
COMPREPLY=($(compgen -W "" -- "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
@ -80,7 +80,7 @@ _zoxide() {
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
zoxide__init)
|
zoxide__init)
|
||||||
opts="-h -V --no-aliases --cmd --hook --help --version bash elvish fish nushell posix powershell 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
|
||||||
|
|
@ -91,7 +91,7 @@ _zoxide() {
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
--hook)
|
--hook)
|
||||||
COMPREPLY=($(compgen -W "none prompt pwd" -- "${cur}"))
|
COMPREPLY=($(compgen -W "" -- "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ set edit:completion:arg-completer[zoxide] = {|@words|
|
||||||
cand --version 'Print version information'
|
cand --version 'Print version information'
|
||||||
}
|
}
|
||||||
&'zoxide;init'= {
|
&'zoxide;init'= {
|
||||||
cand --cmd 'Renames the ''z'' command and corresponding aliases'
|
cand --cmd 'Changes the prefix of the `z` and `zi` commands'
|
||||||
cand --hook 'Chooses event upon which an entry is added to the database'
|
cand --hook 'Changes how often zoxide increments a directory''s score'
|
||||||
cand --no-aliases 'Prevents zoxide from defining any commands'
|
cand --no-cmd 'Prevents zoxide from defining the `z` and `zi` commands'
|
||||||
cand -h 'Print help information'
|
cand -h 'Print help information'
|
||||||
cand --help 'Print help information'
|
cand --help 'Print help information'
|
||||||
cand -V 'Print version information'
|
cand -V 'Print version information'
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ complete -c zoxide -n "__fish_seen_subcommand_from import" -l from -d 'Applicati
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help information'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help information'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -s V -l version -d 'Print version information'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -s V -l version -d 'Print version information'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from init" -l cmd -d 'Renames the \'z\' command and corresponding aliases' -r
|
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_seen_subcommand_from init" -l hook -d 'Chooses event upon which an entry is added to the database' -r -f -a "{none ,prompt ,pwd }"
|
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_seen_subcommand_from init" -l no-aliases -d 'Prevents zoxide from defining any commands'
|
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_seen_subcommand_from init" -s h -l help -d 'Print help information'
|
complete -c zoxide -n "__fish_seen_subcommand_from init" -s h -l help -d 'Print help information'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from init" -s V -l version -d 'Print version information'
|
complete -c zoxide -n "__fish_seen_subcommand_from init" -s V -l version -d 'Print version information'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from query" -l exclude -d 'Exclude a path from results' -r -f -a "(__fish_complete_directories)"
|
complete -c zoxide -n "__fish_seen_subcommand_from query" -l exclude -d 'Exclude a path from results' -r -f -a "(__fish_complete_directories)"
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,9 @@ const completion: Fig.Spec = {
|
||||||
args: {
|
args: {
|
||||||
name: "from",
|
name: "from",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
{
|
"autojump",
|
||||||
name: "autojump",
|
"z",
|
||||||
},
|
],
|
||||||
{
|
|
||||||
name: "z",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +60,7 @@ const completion: Fig.Spec = {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: "--cmd",
|
name: "--cmd",
|
||||||
description: "Renames the 'z' command and corresponding aliases",
|
description: "Changes the prefix of the `z` and `zi` commands",
|
||||||
args: {
|
args: {
|
||||||
name: "cmd",
|
name: "cmd",
|
||||||
isOptional: true,
|
isOptional: true,
|
||||||
|
|
@ -72,26 +68,20 @@ const completion: Fig.Spec = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "--hook",
|
name: "--hook",
|
||||||
description: "Chooses event upon which an entry is added to the database",
|
description: "Changes how often zoxide increments a directory's score",
|
||||||
args: {
|
args: {
|
||||||
name: "hook",
|
name: "hook",
|
||||||
isOptional: true,
|
isOptional: true,
|
||||||
suggestions: [
|
suggestions: [
|
||||||
{
|
"none",
|
||||||
name: "none",
|
"prompt",
|
||||||
},
|
"pwd",
|
||||||
{
|
],
|
||||||
name: "prompt",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "pwd",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "--no-aliases",
|
name: "--no-cmd",
|
||||||
description: "Prevents zoxide from defining any commands",
|
description: "Prevents zoxide from defining the `z` and `zi` commands",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ["-h", "--help"],
|
name: ["-h", "--help"],
|
||||||
|
|
@ -105,31 +95,15 @@ const completion: Fig.Spec = {
|
||||||
args: {
|
args: {
|
||||||
name: "shell",
|
name: "shell",
|
||||||
suggestions: [
|
suggestions: [
|
||||||
{
|
"bash",
|
||||||
name: "bash",
|
"elvish",
|
||||||
},
|
"fish",
|
||||||
{
|
"nushell",
|
||||||
name: "elvish",
|
"posix",
|
||||||
},
|
"powershell",
|
||||||
{
|
"xonsh",
|
||||||
name: "fish",
|
"zsh",
|
||||||
},
|
],
|
||||||
{
|
|
||||||
name: "nushell",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "posix",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "powershell",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "xonsh",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "zsh",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -152,14 +126,26 @@ const completion: Fig.Spec = {
|
||||||
{
|
{
|
||||||
name: ["-i", "--interactive"],
|
name: ["-i", "--interactive"],
|
||||||
description: "Use interactive selection",
|
description: "Use interactive selection",
|
||||||
|
exclusiveOn: [
|
||||||
|
"-l",
|
||||||
|
"--list",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ["-l", "--list"],
|
name: ["-l", "--list"],
|
||||||
description: "List all matching directories",
|
description: "List all matching directories",
|
||||||
|
exclusiveOn: [
|
||||||
|
"-i",
|
||||||
|
"--interactive",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ["-s", "--score"],
|
name: ["-s", "--score"],
|
||||||
description: "Print score with results",
|
description: "Print score with results",
|
||||||
|
exclusiveOn: [
|
||||||
|
"-i",
|
||||||
|
"--interactive",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ["-h", "--help"],
|
name: ["-h", "--help"],
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Add this to your configuration (usually \fB~/.elvish/rc.elv\fR):
|
||||||
\fBeval $(zoxide init elvish | slurp)\fR
|
\fBeval $(zoxide init elvish | slurp)\fR
|
||||||
.fi
|
.fi
|
||||||
.sp
|
.sp
|
||||||
Note: zoxide only supports elvish v0.16.0 and above.
|
Note: zoxide only supports elvish v0.18.0 and above.
|
||||||
.TP
|
.TP
|
||||||
.B fish
|
.B fish
|
||||||
Add this to your configuration (usually \fB~/.config/fish/config.fish\fR):
|
Add this to your configuration (usually \fB~/.config/fish/config.fish\fR):
|
||||||
|
|
@ -74,9 +74,9 @@ Add this to your configuration:
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B --cmd
|
.B --cmd
|
||||||
Changes the prefix of predefined aliases (\fBz\fR, \fBzi\fR).
|
Changes the prefix of the \fBz\fR and \fBzi\fR commands.
|
||||||
.br
|
.br
|
||||||
\fB--cmd j\fR would change the aliases to (\fBj\fR, \fBji\fR).
|
\fB--cmd j\fR would change the commands to (\fBj\fR, \fBji\fR).
|
||||||
.br
|
.br
|
||||||
\fB--cmd cd\fR would replace the \fBcd\fR command (doesn't work on Nushell /
|
\fB--cmd cd\fR would replace the \fBcd\fR command (doesn't work on Nushell /
|
||||||
POSIX shells).
|
POSIX shells).
|
||||||
|
|
@ -94,10 +94,10 @@ l l.
|
||||||
\fBpwd\fR|Whenever the directory is changed
|
\fBpwd\fR|Whenever the directory is changed
|
||||||
.TE
|
.TE
|
||||||
.TP
|
.TP
|
||||||
.B --no-aliases
|
.B --no-cmd
|
||||||
Don't define extra aliases (\fBz\fR, \fBzi\fR). These functions will still be
|
Prevents zoxide from defining the \fBz\fR and \fBzi\fR commands. These functions
|
||||||
available in your shell as \fB__zoxide_z\fR and \fB__zoxide_zi\fR, should you
|
will still be available in your shell as \fB__zoxide_z\fR and \fB__zoxide_zi\fR,
|
||||||
choose to redefine them.
|
should you choose to redefine them.
|
||||||
.SH REPORTING BUGS
|
.SH REPORTING BUGS
|
||||||
For any issues, feature requests, or questions, please visit:
|
For any issues, feature requests, or questions, please visit:
|
||||||
.sp
|
.sp
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,18 @@ directories you use most frequently, and uses a ranking algorithm to navigate
|
||||||
to the best match.
|
to the best match.
|
||||||
.SH USAGE
|
.SH USAGE
|
||||||
.nf
|
.nf
|
||||||
$ z foo # cd into highest ranked directory matching foo
|
z foo # cd into highest ranked directory matching foo
|
||||||
$ z foo bar # cd into highest ranked directory matching foo and bar
|
z foo bar # cd into highest ranked directory matching foo and bar
|
||||||
$ z foo / # cd into a subdirectory starting with foo
|
z foo / # cd into a subdirectory starting with foo
|
||||||
.sp
|
.sp
|
||||||
$ z ~/foo # z also works like a regular cd command
|
z ~/foo # z also works like a regular cd command
|
||||||
$ z foo/ # cd into relative path
|
z foo/ # cd into relative path
|
||||||
$ z .. # cd one level up
|
z .. # cd one level up
|
||||||
$ z - # cd into previous directory
|
z - # cd into previous directory
|
||||||
.sp
|
.sp
|
||||||
$ zi foo # cd with interactive selection (using fzf)
|
zi foo # cd with interactive selection (using fzf)
|
||||||
|
.sp
|
||||||
|
z foo<SPACE><TAB> # show interactive completions (bash 4.4+/fish/zsh only)
|
||||||
.fi
|
.fi
|
||||||
.SH SUBCOMMANDS
|
.SH SUBCOMMANDS
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -63,7 +65,7 @@ T}
|
||||||
\fB/Users/Alice/Library/Application Support\fR
|
\fB/Users/Alice/Library/Application Support\fR
|
||||||
T}
|
T}
|
||||||
\fBWindows\fR|T{
|
\fBWindows\fR|T{
|
||||||
\fB{FOLDERID_RoamingAppData}\fR, eg. \fBC:\\Users\\Alice\\AppData\\Roaming\fR
|
\fB%LOCALAPPDATA%\fR, eg. \fBC:\\Users\\Alice\\AppData\\Local\fR
|
||||||
T}
|
T}
|
||||||
.TE
|
.TE
|
||||||
.TP
|
.TP
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
let
|
let
|
||||||
rust = import (builtins.fetchTarball
|
rust = import (builtins.fetchTarball
|
||||||
"https://github.com/oxalica/rust-overlay/archive/203dc4fc3fe2a5df1aa481a3fc8a1bb27074d677.tar.gz");
|
"https://github.com/oxalica/rust-overlay/archive/46d8d20fce510c6a25fa66f36e31f207f6ea49e4.tar.gz");
|
||||||
pkgs = import (builtins.fetchTarball
|
pkgs = import (builtins.fetchTarball
|
||||||
"https://github.com/NixOS/nixpkgs/archive/fae46e66a5df220327b45e0d7c27c6961cf922ce.tar.gz") {
|
"https://github.com/NixOS/nixpkgs/archive/d19a9162c848517cfc9437f10945b736d718b948.tar.gz") {
|
||||||
overlays = [ rust ];
|
overlays = [ rust ];
|
||||||
};
|
};
|
||||||
in pkgs.mkShell {
|
in pkgs.mkShell {
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
mod _app;
|
|
||||||
mod add;
|
|
||||||
mod import;
|
|
||||||
mod init;
|
|
||||||
mod query;
|
|
||||||
mod remove;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
pub use crate::app::_app::*;
|
|
||||||
|
|
||||||
pub trait Run {
|
|
||||||
fn run(&self) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Run for App {
|
|
||||||
fn run(&self) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
App::Add(cmd) => cmd.run(),
|
|
||||||
App::Import(cmd) => cmd.run(),
|
|
||||||
App::Init(cmd) => cmd.run(),
|
|
||||||
App::Query(cmd) => cmd.run(),
|
|
||||||
App::Remove(cmd) => cmd.run(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{AppSettings, ArgEnum, Parser, ValueHint};
|
use clap::{ArgEnum, Parser, ValueHint};
|
||||||
|
|
||||||
const ENV_HELP: &str = "ENVIRONMENT VARIABLES:
|
const ENV_HELP: &str = "ENVIRONMENT VARIABLES:
|
||||||
_ZO_DATA_DIR Path for zoxide data files
|
_ZO_DATA_DIR Path for zoxide data files
|
||||||
|
|
@ -16,11 +16,11 @@ const ENV_HELP: &str = "ENVIRONMENT VARIABLES:
|
||||||
about,
|
about,
|
||||||
author,
|
author,
|
||||||
after_help = ENV_HELP,
|
after_help = ENV_HELP,
|
||||||
global_setting(AppSettings::DisableHelpSubcommand),
|
disable_help_subcommand = true,
|
||||||
global_setting(AppSettings::PropagateVersion),
|
propagate_version = true,
|
||||||
version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
|
version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
|
||||||
)]
|
)]
|
||||||
pub enum App {
|
pub enum Cmd {
|
||||||
Add(Add),
|
Add(Add),
|
||||||
Import(Import),
|
Import(Import),
|
||||||
Init(Init),
|
Init(Init),
|
||||||
|
|
@ -62,15 +62,15 @@ pub struct Init {
|
||||||
#[clap(arg_enum)]
|
#[clap(arg_enum)]
|
||||||
pub shell: InitShell,
|
pub shell: InitShell,
|
||||||
|
|
||||||
/// Prevents zoxide from defining any commands
|
/// Prevents zoxide from defining the `z` and `zi` commands
|
||||||
#[clap(long)]
|
#[clap(long, alias = "no-aliases")]
|
||||||
pub no_aliases: bool,
|
pub no_cmd: bool,
|
||||||
|
|
||||||
/// Renames the 'z' command and corresponding aliases
|
/// Changes the prefix of the `z` and `zi` commands
|
||||||
#[clap(long, default_value = "z")]
|
#[clap(long, default_value = "z")]
|
||||||
pub cmd: String,
|
pub cmd: String,
|
||||||
|
|
||||||
/// Chooses event upon which an entry is added to the database
|
/// Changes how often zoxide increments a directory's score
|
||||||
#[clap(arg_enum, long, default_value = "pwd")]
|
#[clap(arg_enum, long, default_value = "pwd")]
|
||||||
pub hook: InitHook,
|
pub hook: InitHook,
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
use crate::app::{Add, Run};
|
use crate::cmd::{Add, Run};
|
||||||
use crate::db::DatabaseFile;
|
use crate::db::DatabaseFile;
|
||||||
use crate::{config, util};
|
use crate::{config, util};
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::fs;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
|
||||||
use crate::app::{Import, ImportFrom, Run};
|
use crate::cmd::{Import, ImportFrom, Run};
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::db::{Database, DatabaseFile, Dir};
|
use crate::db::{Database, DatabaseFile, Dir};
|
||||||
|
|
||||||
|
|
@ -3,14 +3,14 @@ use std::io::{self, Write};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
use crate::app::{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::{self, Opts};
|
use crate::shell::{self, Opts};
|
||||||
|
|
||||||
impl Run for Init {
|
impl Run for Init {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
let cmd = if self.no_aliases { None } else { Some(self.cmd.as_str()) };
|
let cmd = if self.no_cmd { None } else { Some(self.cmd.as_str()) };
|
||||||
|
|
||||||
let echo = config::echo();
|
let echo = config::echo();
|
||||||
let resolve_symlinks = config::resolve_symlinks();
|
let resolve_symlinks = config::resolve_symlinks();
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
mod _cmd;
|
||||||
|
mod add;
|
||||||
|
mod import;
|
||||||
|
mod init;
|
||||||
|
mod query;
|
||||||
|
mod remove;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub use crate::cmd::_cmd::*;
|
||||||
|
|
||||||
|
pub trait Run {
|
||||||
|
fn run(&self) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Run for Cmd {
|
||||||
|
fn run(&self) -> Result<()> {
|
||||||
|
match self {
|
||||||
|
Cmd::Add(cmd) => cmd.run(),
|
||||||
|
Cmd::Import(cmd) => cmd.run(),
|
||||||
|
Cmd::Init(cmd) => cmd.run(),
|
||||||
|
Cmd::Query(cmd) => cmd.run(),
|
||||||
|
Cmd::Remove(cmd) => cmd.run(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,11 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use crate::app::{Query, Run};
|
use crate::cmd::{Query, Run};
|
||||||
|
use crate::config;
|
||||||
use crate::db::{Database, DatabaseFile};
|
use crate::db::{Database, DatabaseFile};
|
||||||
use crate::error::BrokenPipeHandler;
|
use crate::error::BrokenPipeHandler;
|
||||||
use crate::fzf::Fzf;
|
use crate::util::{self, Fzf};
|
||||||
use crate::{config, util};
|
|
||||||
|
|
||||||
impl Run for Query {
|
impl Run for Query {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
|
|
@ -2,10 +2,10 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
|
||||||
use crate::app::{Remove, Run};
|
use crate::cmd::{Remove, Run};
|
||||||
|
use crate::config;
|
||||||
use crate::db::DatabaseFile;
|
use crate::db::DatabaseFile;
|
||||||
use crate::fzf::Fzf;
|
use crate::util::{self, Fzf};
|
||||||
use crate::{config, util};
|
|
||||||
|
|
||||||
impl Run for Remove {
|
impl Run for Remove {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
|
|
@ -2,13 +2,14 @@ mod dir;
|
||||||
mod stream;
|
mod stream;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, Write};
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
pub use dir::{Dir, DirList, Epoch, Rank};
|
pub use dir::{Dir, DirList, Epoch, Rank};
|
||||||
pub use stream::Stream;
|
pub use stream::Stream;
|
||||||
use tempfile::{NamedTempFile, PersistError};
|
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Database<'file> {
|
pub struct Database<'file> {
|
||||||
|
|
@ -24,18 +25,8 @@ impl<'file> Database<'file> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let buffer = self.dirs.to_bytes()?;
|
let buffer = self.dirs.to_bytes()?;
|
||||||
let mut file = NamedTempFile::new_in(self.data_dir)
|
|
||||||
.with_context(|| format!("could not create temporary database in: {}", self.data_dir.display()))?;
|
|
||||||
|
|
||||||
// Preallocate enough space on the file, preventing copying later on. This optimization may
|
|
||||||
// fail on some filesystems, but it is safe to ignore it and proceed.
|
|
||||||
let _ = file.as_file().set_len(buffer.len() as _);
|
|
||||||
file.write_all(&buffer)
|
|
||||||
.with_context(|| format!("could not write to temporary database: {}", file.path().display()))?;
|
|
||||||
|
|
||||||
let path = db_path(&self.data_dir);
|
let path = db_path(&self.data_dir);
|
||||||
persist(file, &path).with_context(|| format!("could not replace database: {}", path.display()))?;
|
util::write(&path, &buffer).context("could not write to database")?;
|
||||||
|
|
||||||
self.modified = false;
|
self.modified = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -120,44 +111,6 @@ impl<'file> Database<'file> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn persist<P: AsRef<Path>>(file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
|
||||||
file.persist(path)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use rand::distributions::{Distribution, Uniform};
|
|
||||||
use rand::rngs::SmallRng;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
|
|
||||||
// File renames on Windows are not atomic and sometimes fail with `PermissionDenied`. This is
|
|
||||||
// extremely unlikely unless it's running in a loop on multiple threads. Nevertheless, we guard
|
|
||||||
// against it by retrying the rename a fixed number of times.
|
|
||||||
const MAX_TRIES: usize = 10;
|
|
||||||
let mut rng = None;
|
|
||||||
|
|
||||||
for _ in 0..MAX_TRIES {
|
|
||||||
match file.persist(&path) {
|
|
||||||
Ok(_) => break,
|
|
||||||
Err(e) if e.error.kind() == io::ErrorKind::PermissionDenied => {
|
|
||||||
let mut rng = rng.get_or_insert_with(SmallRng::from_entropy);
|
|
||||||
let between = Uniform::from(50..150);
|
|
||||||
let duration = Duration::from_millis(between.sample(&mut rng));
|
|
||||||
thread::sleep(duration);
|
|
||||||
file = e.file;
|
|
||||||
}
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DatabaseFile {
|
pub struct DatabaseFile {
|
||||||
buffer: Vec<u8>,
|
buffer: Vec<u8>,
|
||||||
data_dir: PathBuf,
|
data_dir: PathBuf,
|
||||||
|
|
|
||||||
15
src/error.rs
15
src/error.rs
|
|
@ -1,19 +1,20 @@
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
#[error("could not find fzf, is it installed?")]
|
|
||||||
pub struct FzfNotFound;
|
|
||||||
|
|
||||||
/// Custom error type for early exit.
|
/// Custom error type for early exit.
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug)]
|
||||||
#[error("")]
|
|
||||||
pub struct SilentExit {
|
pub struct SilentExit {
|
||||||
pub code: i32,
|
pub code: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for SilentExit {
|
||||||
|
fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait BrokenPipeHandler {
|
pub trait BrokenPipeHandler {
|
||||||
fn pipe_exit(self, device: &str) -> Result<()>;
|
fn pipe_exit(self, device: &str) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
70
src/fzf.rs
70
src/fzf.rs
|
|
@ -1,70 +0,0 @@
|
||||||
use std::io::{self, Read};
|
|
||||||
use std::mem;
|
|
||||||
use std::process::{Child, ChildStdin, Stdio};
|
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
|
||||||
|
|
||||||
use crate::error::{FzfNotFound, SilentExit};
|
|
||||||
use crate::{config, util};
|
|
||||||
|
|
||||||
pub struct Fzf {
|
|
||||||
child: Child,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Fzf {
|
|
||||||
pub fn new(multiple: bool) -> Result<Self> {
|
|
||||||
let bin = if cfg!(windows) { "fzf.exe" } else { "fzf" };
|
|
||||||
let mut command = util::get_command(bin).map_err(|_| FzfNotFound)?;
|
|
||||||
if multiple {
|
|
||||||
command.arg("-m");
|
|
||||||
}
|
|
||||||
command.arg("-n2..").stdin(Stdio::piped()).stdout(Stdio::piped());
|
|
||||||
if let Some(fzf_opts) = config::fzf_opts() {
|
|
||||||
command.env("FZF_DEFAULT_OPTS", fzf_opts);
|
|
||||||
} else {
|
|
||||||
command.args(&[
|
|
||||||
"--bind=ctrl-z:ignore",
|
|
||||||
"--exit-0",
|
|
||||||
"--height=40%",
|
|
||||||
"--inline-info",
|
|
||||||
"--no-sort",
|
|
||||||
"--reverse",
|
|
||||||
"--select-1",
|
|
||||||
]);
|
|
||||||
if cfg!(unix) {
|
|
||||||
command.arg("--preview=ls -p {2..}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let child = match command.spawn() {
|
|
||||||
Ok(child) => child,
|
|
||||||
Err(e) if e.kind() == io::ErrorKind::NotFound => bail!(FzfNotFound),
|
|
||||||
Err(e) => Err(e).context("could not launch fzf")?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Fzf { child })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stdin(&mut self) -> &mut ChildStdin {
|
|
||||||
self.child.stdin.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn select(mut self) -> Result<String> {
|
|
||||||
// Drop stdin to prevent deadlock.
|
|
||||||
mem::drop(self.child.stdin.take());
|
|
||||||
|
|
||||||
let mut stdout = self.child.stdout.take().unwrap();
|
|
||||||
let mut output = String::new();
|
|
||||||
stdout.read_to_string(&mut output).context("failed to read from fzf")?;
|
|
||||||
|
|
||||||
let status = self.child.wait().context("wait failed on fzf")?;
|
|
||||||
match status.code() {
|
|
||||||
Some(0) => Ok(output),
|
|
||||||
Some(1) => bail!("no match found"),
|
|
||||||
Some(2) => bail!("fzf returned an error"),
|
|
||||||
Some(code @ 130) => bail!(SilentExit { code }),
|
|
||||||
Some(128..=254) | None => bail!("fzf was terminated"),
|
|
||||||
_ => bail!("fzf returned an unknown error"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
src/main.rs
13
src/main.rs
|
|
@ -1,8 +1,13 @@
|
||||||
mod app;
|
#![allow(clippy::single_component_path_imports)]
|
||||||
|
|
||||||
|
// rstest_reuse must be imported at the top of the crate.
|
||||||
|
#[cfg(test)]
|
||||||
|
use rstest_reuse;
|
||||||
|
|
||||||
|
mod cmd;
|
||||||
mod config;
|
mod config;
|
||||||
mod db;
|
mod db;
|
||||||
mod error;
|
mod error;
|
||||||
mod fzf;
|
|
||||||
mod shell;
|
mod shell;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
|
@ -11,7 +16,7 @@ use std::{env, process};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use crate::app::{App, Run};
|
use crate::cmd::{Cmd, Run};
|
||||||
use crate::error::SilentExit;
|
use crate::error::SilentExit;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
@ -19,7 +24,7 @@ pub fn main() {
|
||||||
env::remove_var("RUST_LIB_BACKTRACE");
|
env::remove_var("RUST_LIB_BACKTRACE");
|
||||||
env::remove_var("RUST_BACKTRACE");
|
env::remove_var("RUST_BACKTRACE");
|
||||||
|
|
||||||
if let Err(e) = App::parse().run() {
|
if let Err(e) = Cmd::parse().run() {
|
||||||
match e.downcast::<SilentExit>() {
|
match e.downcast::<SilentExit>() {
|
||||||
Ok(SilentExit { code }) => process::exit(code),
|
Ok(SilentExit { code }) => process::exit(code),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
||||||
165
src/shell.rs
165
src/shell.rs
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::app::InitHook;
|
use crate::cmd::InitHook;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Opts<'a> {
|
pub struct Opts<'a> {
|
||||||
|
|
@ -32,22 +32,28 @@ make_template!(Powershell, "powershell.txt");
|
||||||
make_template!(Xonsh, "xonsh.txt");
|
make_template!(Xonsh, "xonsh.txt");
|
||||||
make_template!(Zsh, "zsh.txt");
|
make_template!(Zsh, "zsh.txt");
|
||||||
|
|
||||||
#[cfg(feature = "nix")]
|
#[cfg(feature = "nix-dev")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use assert_cmd::Command;
|
use assert_cmd::Command;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
use rstest_reuse::{apply, template};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[template]
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn bash_bash(
|
fn opts(
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
#[values(None, Some("z"))] cmd: Option<&str>,
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
||||||
#[values(false, true)] echo: bool,
|
#[values(false, true)] echo: bool,
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
#[values(false, true)] resolve_symlinks: bool,
|
||||||
) {
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[apply(opts)]
|
||||||
|
fn bash_bash(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 = Bash(&opts).render().unwrap();
|
let source = Bash(&opts).render().unwrap();
|
||||||
Command::new("bash")
|
Command::new("bash")
|
||||||
|
|
@ -58,13 +64,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn bash_shellcheck(
|
fn bash_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Bash(&opts).render().unwrap();
|
let source = Bash(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
@ -77,13 +78,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn bash_shfmt(
|
fn bash_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = Bash(&opts).render().unwrap();
|
let mut source = Bash(&opts).render().unwrap();
|
||||||
source.push('\n');
|
source.push('\n');
|
||||||
|
|
@ -97,13 +93,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn elvish_elvish(
|
fn elvish_elvish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] 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::new();
|
||||||
|
|
||||||
|
|
@ -117,13 +108,8 @@ mod tests {
|
||||||
Command::new("elvish").args(&["-c", &source, "-norc"]).assert().success().stdout("").stderr("");
|
Command::new("elvish").args(&["-c", &source, "-norc"]).assert().success().stdout("").stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn fish_fish(
|
fn fish_fish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Fish(&opts).render().unwrap();
|
let source = Fish(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
@ -139,13 +125,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn fish_fishindent(
|
fn fish_fishindent(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = Fish(&opts).render().unwrap();
|
let mut source = Fish(&opts).render().unwrap();
|
||||||
source.push('\n');
|
source.push('\n');
|
||||||
|
|
@ -162,13 +143,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn nushell_nushell(
|
fn nushell_nushell(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Nushell(&opts).render().unwrap();
|
let source = Nushell(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
@ -183,13 +159,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn posix_bash(
|
fn posix_bash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] 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();
|
||||||
|
|
||||||
|
|
@ -203,13 +174,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn posix_dash(
|
fn posix_dash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] 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();
|
||||||
|
|
||||||
|
|
@ -219,13 +185,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn posix_shellcheck_(
|
fn posix_shellcheck_(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] 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();
|
||||||
|
|
||||||
|
|
@ -238,13 +199,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn posix_shfmt(
|
fn posix_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = Posix(&opts).render().unwrap();
|
let mut source = Posix(&opts).render().unwrap();
|
||||||
source.push('\n');
|
source.push('\n');
|
||||||
|
|
@ -258,13 +214,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn powershell_pwsh(
|
fn powershell_pwsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = "Set-StrictMode -Version latest\n".to_string();
|
let mut source = "Set-StrictMode -Version latest\n".to_string();
|
||||||
Powershell(&opts).render_into(&mut source).unwrap();
|
Powershell(&opts).render_into(&mut source).unwrap();
|
||||||
|
|
@ -277,13 +228,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn xonsh_black(
|
fn xonsh_black(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = Xonsh(&opts).render().unwrap();
|
let mut source = Xonsh(&opts).render().unwrap();
|
||||||
source.push('\n');
|
source.push('\n');
|
||||||
|
|
@ -291,26 +237,16 @@ mod tests {
|
||||||
Command::new("black").args(&["--check", "--diff", "-"]).write_stdin(source).assert().success().stdout("");
|
Command::new("black").args(&["--check", "--diff", "-"]).write_stdin(source).assert().success().stdout("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn xonsh_mypy(
|
fn xonsh_mypy(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Xonsh(&opts).render().unwrap();
|
let source = Xonsh(&opts).render().unwrap();
|
||||||
|
|
||||||
Command::new("mypy").args(&["--command", &source, "--strict"]).assert().success().stderr("");
|
Command::new("mypy").args(&["--command", &source, "--strict"]).assert().success().stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn xonsh_pylint(
|
fn xonsh_pylint(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let mut source = Xonsh(&opts).render().unwrap();
|
let mut source = Xonsh(&opts).render().unwrap();
|
||||||
source.push('\n');
|
source.push('\n');
|
||||||
|
|
@ -323,13 +259,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn xonsh_xonsh(
|
fn xonsh_xonsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Xonsh(&opts).render().unwrap();
|
let source = Xonsh(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
@ -345,13 +276,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn zsh_shellcheck(
|
fn zsh_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Zsh(&opts).render().unwrap();
|
let source = Zsh(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
@ -365,13 +291,8 @@ mod tests {
|
||||||
.stderr("");
|
.stderr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[apply(opts)]
|
||||||
fn zsh_zsh(
|
fn zsh_zsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||||
#[values(None, Some("z"))] cmd: Option<&str>,
|
|
||||||
#[values(InitHook::None, InitHook::Prompt, InitHook::Pwd)] hook: InitHook,
|
|
||||||
#[values(false, true)] echo: bool,
|
|
||||||
#[values(false, true)] resolve_symlinks: bool,
|
|
||||||
) {
|
|
||||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||||
let source = Zsh(&opts).render().unwrap();
|
let source = Zsh(&opts).render().unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
163
src/util.rs
163
src/util.rs
|
|
@ -1,11 +1,172 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs::{self, File, OpenOptions};
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::mem;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::process::{Child, ChildStdin, Stdio};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
|
|
||||||
|
use crate::config;
|
||||||
use crate::db::Epoch;
|
use crate::db::Epoch;
|
||||||
|
use crate::error::SilentExit;
|
||||||
|
|
||||||
|
pub struct Fzf {
|
||||||
|
child: Child,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fzf {
|
||||||
|
const ERR_NOT_FOUND: &'static str = "could not find fzf, is it installed?";
|
||||||
|
|
||||||
|
pub fn new(multiple: bool) -> Result<Self> {
|
||||||
|
let bin = if cfg!(windows) { "fzf.exe" } else { "fzf" };
|
||||||
|
let mut command = get_command(bin).map_err(|_| anyhow!(Self::ERR_NOT_FOUND))?;
|
||||||
|
if multiple {
|
||||||
|
command.arg("-m");
|
||||||
|
}
|
||||||
|
command.arg("-n2..").stdin(Stdio::piped()).stdout(Stdio::piped());
|
||||||
|
if let Some(fzf_opts) = config::fzf_opts() {
|
||||||
|
command.env("FZF_DEFAULT_OPTS", fzf_opts);
|
||||||
|
} else {
|
||||||
|
command.args(&[
|
||||||
|
// Search result
|
||||||
|
"--no-sort",
|
||||||
|
// Interface
|
||||||
|
"--keep-right",
|
||||||
|
// Layout
|
||||||
|
"--height=40%",
|
||||||
|
"--info=inline",
|
||||||
|
"--layout=reverse",
|
||||||
|
// Scripting
|
||||||
|
"--exit-0",
|
||||||
|
"--select-1",
|
||||||
|
// Key/Event bindings
|
||||||
|
"--bind=ctrl-z:ignore",
|
||||||
|
]);
|
||||||
|
if cfg!(unix) {
|
||||||
|
command.env("SHELL", "sh");
|
||||||
|
command.arg(r"--preview=\command -p ls -p {2..}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = match command.spawn() {
|
||||||
|
Ok(child) => child,
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::NotFound => bail!(Self::ERR_NOT_FOUND),
|
||||||
|
Err(e) => Err(e).context("could not launch fzf")?,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Fzf { child })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdin(&mut self) -> &mut ChildStdin {
|
||||||
|
self.child.stdin.as_mut().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select(mut self) -> Result<String> {
|
||||||
|
// Drop stdin to prevent deadlock.
|
||||||
|
mem::drop(self.child.stdin.take());
|
||||||
|
|
||||||
|
let mut stdout = self.child.stdout.take().unwrap();
|
||||||
|
let mut output = String::new();
|
||||||
|
stdout.read_to_string(&mut output).context("failed to read from fzf")?;
|
||||||
|
|
||||||
|
let status = self.child.wait().context("wait failed on fzf")?;
|
||||||
|
match status.code() {
|
||||||
|
Some(0) => Ok(output),
|
||||||
|
Some(1) => bail!("no match found"),
|
||||||
|
Some(2) => bail!("fzf returned an error"),
|
||||||
|
Some(code @ 130) => bail!(SilentExit { code }),
|
||||||
|
Some(128..=254) | None => bail!("fzf was terminated"),
|
||||||
|
_ => bail!("fzf returned an unknown error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Similar to [`fs::write`], but atomic (best effort on Windows).
|
||||||
|
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
let contents = contents.as_ref();
|
||||||
|
let dir = path.parent().unwrap();
|
||||||
|
|
||||||
|
// Create a tmpfile.
|
||||||
|
let (mut tmp_file, tmp_path) = tmpfile(dir)?;
|
||||||
|
let result = (|| {
|
||||||
|
// Write to the tmpfile.
|
||||||
|
let _ = tmp_file.set_len(contents.len() as u64);
|
||||||
|
tmp_file.write_all(contents).with_context(|| format!("could not write to file: {}", tmp_path.display()))?;
|
||||||
|
|
||||||
|
// Set the owner of the tmpfile (UNIX only).
|
||||||
|
#[cfg(unix)]
|
||||||
|
if let Ok(metadata) = path.metadata() {
|
||||||
|
use nix::unistd::{self, Gid, Uid};
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
|
let uid = Uid::from_raw(metadata.uid());
|
||||||
|
let gid = Gid::from_raw(metadata.gid());
|
||||||
|
let _ = unistd::fchown(tmp_file.as_raw_fd(), Some(uid), Some(gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close and rename the tmpfile.
|
||||||
|
mem::drop(tmp_file);
|
||||||
|
rename(&tmp_path, path)
|
||||||
|
})();
|
||||||
|
// In case of an error, delete the tmpfile.
|
||||||
|
if result.is_err() {
|
||||||
|
let _ = fs::remove_file(&tmp_path);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Atomically create a tmpfile in the given directory.
|
||||||
|
fn tmpfile<P: AsRef<Path>>(dir: P) -> Result<(File, PathBuf)> {
|
||||||
|
const MAX_ATTEMPTS: usize = 5;
|
||||||
|
const TMP_NAME_LEN: usize = 16;
|
||||||
|
let dir = dir.as_ref();
|
||||||
|
|
||||||
|
let mut attempts = 0;
|
||||||
|
loop {
|
||||||
|
attempts += 1;
|
||||||
|
|
||||||
|
// Generate a random name for the tmpfile.
|
||||||
|
let mut name = String::with_capacity(TMP_NAME_LEN);
|
||||||
|
name.push_str("tmp_");
|
||||||
|
while name.len() < TMP_NAME_LEN {
|
||||||
|
name.push(fastrand::alphanumeric());
|
||||||
|
}
|
||||||
|
let path = dir.join(name);
|
||||||
|
|
||||||
|
// Atomically create the tmpfile.
|
||||||
|
match OpenOptions::new().write(true).create_new(true).open(&path) {
|
||||||
|
Ok(file) => break Ok((file, path)),
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::AlreadyExists && attempts < MAX_ATTEMPTS => (),
|
||||||
|
Err(e) => break Err(e).with_context(|| format!("could not create file: {}", path.display())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Similar to [`fs::rename`], but retries on Windows.
|
||||||
|
fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<()> {
|
||||||
|
const MAX_ATTEMPTS: usize = 5;
|
||||||
|
let from = from.as_ref();
|
||||||
|
let to = to.as_ref();
|
||||||
|
|
||||||
|
if cfg!(windows) {
|
||||||
|
let mut attempts = 0;
|
||||||
|
loop {
|
||||||
|
attempts += 1;
|
||||||
|
match fs::rename(from, to) {
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::PermissionDenied && attempts < MAX_ATTEMPTS => (),
|
||||||
|
result => break result,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs::rename(from, to)
|
||||||
|
}
|
||||||
|
.with_context(|| format!("could not rename file: {} -> {}", from.display(), to.display()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn canonicalize<P: AsRef<Path>>(path: &P) -> Result<PathBuf> {
|
pub fn canonicalize<P: AsRef<Path>>(path: &P) -> Result<PathBuf> {
|
||||||
dunce::canonicalize(path).with_context(|| format!("could not resolve path: {}", path.as_ref().display()))
|
dunce::canonicalize(path).with_context(|| format!("could not resolve path: {}", path.as_ref().display()))
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ fi
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ function __zoxide_zi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
@ -115,11 +115,12 @@ function {{cmd}}i() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load completions.
|
# Load completions.
|
||||||
# - Bash 4.0+ is needed to use `mapfile`.
|
# - Bash 4.4+ is required to use `@Q`.
|
||||||
# - Completions require line editing. Since Bash supports only two modes of
|
# - Completions require line editing. Since Bash supports only two modes of
|
||||||
# line editing (`vim` and `emacs`), we check if either them is enabled.
|
# line editing (`vim` and `emacs`), we check if either them is enabled.
|
||||||
# - Completions don't work on `dumb` terminals.
|
# - Completions don't work on `dumb` terminals.
|
||||||
if [[ ${BASH_VERSINFO:-0} -ge 4 && :"${SHELLOPTS}": =~ :(vi|emacs): && ${TERM} != 'dumb' ]]; then
|
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
|
||||||
# Use `printf '\e[5n'` to redraw line after fzf closes.
|
# Use `printf '\e[5n'` to redraw line after fzf closes.
|
||||||
\builtin bind '"\e[0n": redraw-current-line' &>/dev/null
|
\builtin bind '"\e[0n": redraw-current-line' &>/dev/null
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ if (builtin:not (builtin:eq $E:__zoxide_shlvl $E:SHLVL)) {
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ fn __zoxide_z {|@rest|
|
||||||
var path
|
var path
|
||||||
try {
|
try {
|
||||||
set path = (zoxide query --exclude $pwd -- $@rest)
|
set path = (zoxide query --exclude $pwd -- $@rest)
|
||||||
} except {
|
} catch {
|
||||||
} else {
|
} else {
|
||||||
__zoxide_cd $path
|
__zoxide_cd $path
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +70,7 @@ fn __zoxide_zi {|@rest|
|
||||||
var path
|
var path
|
||||||
try {
|
try {
|
||||||
set path = (zoxide query -i -- $@rest)
|
set path = (zoxide query -i -- $@rest)
|
||||||
} except {
|
} catch {
|
||||||
} else {
|
} else {
|
||||||
__zoxide_cd $path
|
__zoxide_cd $path
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ fn __zoxide_zi {|@rest|
|
||||||
edit:add-var __zoxide_zi~ $__zoxide_zi~
|
edit:add-var __zoxide_zi~ $__zoxide_zi~
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
@ -116,4 +116,4 @@ set edit:completion:arg-completer[{{cmd}}] = $__zoxide_z_complete~
|
||||||
#
|
#
|
||||||
# eval (zoxide init elvish | slurp)
|
# eval (zoxide init elvish | slurp)
|
||||||
#
|
#
|
||||||
# Note: zoxide only supports elvish v0.17.0 and above.
|
# Note: zoxide only supports elvish v0.18.0 and above.
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ end
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -84,8 +84,8 @@ function __zoxide_z_complete
|
||||||
# If the last argument is empty, use interactive selection.
|
# If the last argument is empty, use interactive selection.
|
||||||
set -l query $tokens[2..-1]
|
set -l query $tokens[2..-1]
|
||||||
set -l result (zoxide query -i -- $query)
|
set -l result (zoxide query -i -- $query)
|
||||||
and commandline -p "$tokens[1] "(string escape $result)
|
commandline --current-process "$tokens[1] "(string escape $result)
|
||||||
commandline -f repaint
|
commandline --function repaint
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ function __zoxide_zi
|
||||||
end
|
end
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ $'zoxide: PWD hooks are not supported on Nushell.(char nl)Use (char sq)zoxide in
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -86,7 +86,7 @@ def __zoxide_zi [...rest:string] {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ fi
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ __zoxide_zi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ if ($__zoxide_hooked -ne 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ function __zoxide_zi {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ if "__zoxide_hook" not in globals():
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -157,7 +157,7 @@ def __zoxide_zi(args: typing.List[str]) -> None:
|
||||||
|
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ fi
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-cmd, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ function __zoxide_zi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Commands for zoxide. Disable these using --no-cmd.
|
||||||
#
|
#
|
||||||
|
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! Test clap generated completions.
|
//! Test clap generated completions.
|
||||||
#![cfg(feature = "nix")]
|
#![cfg(feature = "nix-dev")]
|
||||||
|
|
||||||
use assert_cmd::Command;
|
use assert_cmd::Command;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
clap = { version = "3.0.0", features = ["derive"] }
|
clap = { version = "3.1.0", features = ["derive"] }
|
||||||
ignore = "0.4.18"
|
ignore = "0.4.18"
|
||||||
shell-words = "1.0.0"
|
shell-words = "1.0.0"
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,10 @@ use std::path::PathBuf;
|
||||||
use std::process::{self, Command};
|
use std::process::{self, Command};
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let nix_enabled = enable_nix();
|
|
||||||
|
|
||||||
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
let dir = dir.parent().with_context(|| format!("could not find workspace root: {}", dir.display()))?;
|
let dir = dir.parent().with_context(|| format!("could not find workspace root: {}", dir.display()))?;
|
||||||
env::set_current_dir(dir).with_context(|| format!("could not set current directory: {}", dir.display()))?;
|
env::set_current_dir(dir).with_context(|| format!("could not set current directory: {}", dir.display()))?;
|
||||||
|
let nix_enabled = enable_nix();
|
||||||
|
|
||||||
let app = App::parse();
|
let app = App::parse();
|
||||||
match app {
|
match app {
|
||||||
|
|
@ -147,8 +146,11 @@ fn enable_nix() -> bool {
|
||||||
println!("Detected Nix in environment, re-running in Nix.");
|
println!("Detected Nix in environment, re-running in Nix.");
|
||||||
let args = env::args();
|
let args = env::args();
|
||||||
let cmd = shell_words::join(args);
|
let cmd = shell_words::join(args);
|
||||||
let mut nix_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
nix_path.push("../shell.nix");
|
let status = Command::new("nix-shell")
|
||||||
let status = Command::new("nix-shell").args(&["--pure", "--run", &cmd, "--"]).arg(nix_path).status().unwrap();
|
.args(&["--pure", "--run", &cmd, "--", "shell.nix"])
|
||||||
|
.env("CARGO_TARGET_DIR", "target_nix")
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
process::exit(status.code().unwrap_or(1));
|
process::exit(status.code().unwrap_or(1));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue