zoxide-{add,remove} should accept multiple arguments (#243)
This commit is contained in:
parent
712d3403ef
commit
3bb21ede97
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- markdownlint-disable MD024 -->
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
@ -7,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `zoxide add` and `zoxide remove` now accept multiple arguments.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Nushell: errors on 0.33.0.
|
- Nushell: errors on 0.33.0.
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.41"
|
version = "1.0.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
|
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
|
|
@ -55,9 +57,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_cmd"
|
name = "assert_cmd"
|
||||||
version = "1.0.5"
|
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 = "a88b6bd5df287567ffdf4ddf4d33060048e1068308e5f62d81c6f9824a045a48"
|
checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"doc-comment",
|
"doc-comment",
|
||||||
|
|
@ -170,10 +172,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "difference"
|
name = "difflib"
|
||||||
version = "2.0.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
|
|
@ -208,6 +210,12 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
@ -233,9 +241,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.9.1"
|
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 = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
|
|
@ -248,23 +256,32 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.18"
|
version = "0.1.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.6.2"
|
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 = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
|
@ -286,9 +303,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.97"
|
version = "0.2.98"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
|
|
@ -320,9 +337,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "2.5.1"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f100fcfb41e5385e0991f74981732049f9b896821542a219420491046baafdc2"
|
checksum = "039f02eb0f69271f26abe3202189275d7aa2258b903cb0281b5de710a2570ff3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
@ -350,11 +367,12 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
version = "1.0.8"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df"
|
checksum = "bc3d91237f5de3bcd9d927e24d03b495adb6135097b001cea7403e2d573d00a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"difference",
|
"difflib",
|
||||||
|
"itertools",
|
||||||
"predicates-core",
|
"predicates-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -400,9 +418,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.27"
|
version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
@ -576,9 +594,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.73"
|
version = "1.0.74"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -637,9 +655,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,21 @@ categories = ["command-line-utilities", "filesystem"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
askama = { version="0.10.3", default-features=false }
|
askama = { version = "0.10.3", default-features = false }
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
clap = "3.0.0-beta.2"
|
clap = "3.0.0-beta.2"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
dunce = "1.0.1"
|
dunce = "1.0.1"
|
||||||
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"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
rand = { version="0.8.4", features=["getrandom", "small_rng"], default-features=false }
|
rand = { version = "0.8.4", features = [
|
||||||
|
"getrandom",
|
||||||
|
"small_rng",
|
||||||
|
], default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "1.0.1"
|
assert_cmd = "1.0.1"
|
||||||
|
|
|
||||||
20
README.md
20
README.md
|
|
@ -31,9 +31,9 @@ Read more about the matching algorithm [here][algorithm-matching].
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
### Step 1: Install `zoxide`
|
### *Step 1: Install `zoxide`*
|
||||||
|
|
||||||
`zoxide` supports most major platforms. If your platform isn't listed below,
|
`zoxide` runs on most major platforms. If your platform isn't listed below,
|
||||||
please [open an issue][issues].
|
please [open an issue][issues].
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
@ -131,12 +131,12 @@ To install `zoxide`, use a package manager:
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Step 2: Install `fzf` (optional)
|
### *Step 2: Install `fzf` (optional)*
|
||||||
|
|
||||||
[`fzf`][fzf] is a command-line fuzzy finder, used by `zoxide` for interactive
|
[`fzf`][fzf] is a command-line fuzzy finder, used by `zoxide` for interactive
|
||||||
selection ([installation instructions][fzf-installation]).
|
selection. It can be installed from [here][fzf-installation].
|
||||||
|
|
||||||
### Step 3: Add `zoxide` to your shell
|
### *Step 3: Import your data (optional)*
|
||||||
|
|
||||||
If you currently use any of the following utilities, you may want to import
|
If you currently use any of the following utilities, you may want to import
|
||||||
your data into `zoxide`:
|
your data into `zoxide`:
|
||||||
|
|
@ -159,7 +159,9 @@ zoxide import --from z path/to/db
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Now, initialize `zoxide` on your shell:
|
### *Step 4: Add `zoxide` to your shell*
|
||||||
|
|
||||||
|
To start using `zoxide`, add it to your shell.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><code>bash</code></summary>
|
<summary><code>bash</code></summary>
|
||||||
|
|
@ -195,7 +197,7 @@ zoxide init fish | source
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><code>nushell 0.32+</code></summary>
|
<summary><code>nushell v0.32+</code></summary>
|
||||||
|
|
||||||
Initialize the `zoxide` script:
|
Initialize the `zoxide` script:
|
||||||
|
|
||||||
|
|
@ -217,7 +219,7 @@ You can replace `__zoxide_prompt` with a custom prompt.
|
||||||
<details>
|
<details>
|
||||||
<summary><code>powershell</code></summary>
|
<summary><code>powershell</code></summary>
|
||||||
|
|
||||||
Add this to your configuration (the location is stored in `$profile`):
|
Add this to your configuration (find it with `echo $profile`):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Invoke-Expression (& {
|
Invoke-Expression (& {
|
||||||
|
|
@ -251,7 +253,7 @@ eval "$(zoxide init zsh)"
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Any POSIX shell</summary>
|
<summary>any POSIX shell</summary>
|
||||||
|
|
||||||
Add this to your configuration:
|
Add this to your configuration:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ _zoxide() {
|
||||||
_arguments "${_arguments_options[@]}" \
|
_arguments "${_arguments_options[@]}" \
|
||||||
'-h[Prints help information]' \
|
'-h[Prints help information]' \
|
||||||
'--help[Prints help information]' \
|
'--help[Prints help information]' \
|
||||||
':path:_files -/' \
|
'*::paths:_files -/' \
|
||||||
&& ret=0
|
&& ret=0
|
||||||
;;
|
;;
|
||||||
(import)
|
(import)
|
||||||
|
|
@ -75,7 +75,7 @@ _arguments "${_arguments_options[@]}" \
|
||||||
'()*--interactive=[]' \
|
'()*--interactive=[]' \
|
||||||
'-h[Prints help information]' \
|
'-h[Prints help information]' \
|
||||||
'--help[Prints help information]' \
|
'--help[Prints help information]' \
|
||||||
'::path:_files -/' \
|
'*::paths:_files -/' \
|
||||||
&& ret=0
|
&& ret=0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ _zoxide() {
|
||||||
;;
|
;;
|
||||||
|
|
||||||
zoxide__add)
|
zoxide__add)
|
||||||
opts=" -h --help <path> "
|
opts=" -h --help <paths>... "
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -127,7 +127,7 @@ _zoxide() {
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
zoxide__remove)
|
zoxide__remove)
|
||||||
opts=" -i -h --interactive --help <path> "
|
opts=" -i -h --interactive --help <paths>... "
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
.SH NAME
|
.SH NAME
|
||||||
zoxide-add - add a new directory or increment its rank
|
zoxide-add - add a new directory or increment its rank
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B zoxide add \fIPATH\fR
|
.B zoxide add \fI[PATHS]\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
If the directory is not already in the database, this command creates a new
|
If the directory is not already in the database, this command creates a new
|
||||||
entry for it with a default score of \fI1\fR, otherwise, it increments the
|
entry for it with a default score of \fI1\fR, otherwise, it increments the
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ Add this to your configuration (usually \fI~/.config/nu/config.toml\fR):
|
||||||
You can replace \fB__zoxide_prompt\fR with a custom prompt.
|
You can replace \fB__zoxide_prompt\fR with a custom prompt.
|
||||||
.TP
|
.TP
|
||||||
.B powershell
|
.B powershell
|
||||||
Add this to your configuration (the location is stored in \fI$profile\fR):
|
Add this to your configuration (find it with \fIecho $profile\fR):
|
||||||
.sp
|
.sp
|
||||||
.nf
|
.nf
|
||||||
\fBInvoke-Expression (& {
|
\fBInvoke-Expression (& {
|
||||||
|
|
@ -67,7 +67,7 @@ Add this to your configuration (usually \fI~/.zshrc\fR):
|
||||||
\fBeval "$(zoxide init zsh)"\fR
|
\fBeval "$(zoxide init zsh)"\fR
|
||||||
.fi
|
.fi
|
||||||
.TP
|
.TP
|
||||||
.B Any POSIX shell
|
.B any POSIX shell
|
||||||
.sp
|
.sp
|
||||||
Add this to your configuration:
|
Add this to your configuration:
|
||||||
.sp
|
.sp
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
.SH NAME
|
.SH NAME
|
||||||
zoxide-remove - remove a directory from the database
|
zoxide-remove - remove a directory from the database
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B zoxide remove \fIPATH [OPTIONS]\fR
|
.B zoxide remove \fI[PATHS] [OPTIONS]\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
If you'd like to permanently exclude a directory from the database, see the
|
If you'd like to permanently exclude a directory from the database, see the
|
||||||
\fB_ZO_EXCLUDE_DIRS\fR environment variable in \fBzoxide\fR(1).
|
\fB_ZO_EXCLUDE_DIRS\fR environment variable in \fBzoxide\fR(1).
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ pub enum App {
|
||||||
/// Add a new directory or increment its rank
|
/// Add a new directory or increment its rank
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
pub struct Add {
|
pub struct Add {
|
||||||
#[clap(value_hint = ValueHint::DirPath)]
|
#[clap(min_values = 1, required = true, value_hint = ValueHint::DirPath)]
|
||||||
pub path: PathBuf,
|
pub paths: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Import entries from another application
|
/// Import entries from another application
|
||||||
|
|
@ -126,12 +126,12 @@ pub struct Query {
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
pub struct Remove {
|
pub struct Remove {
|
||||||
// Use interactive selection
|
// Use interactive selection
|
||||||
#[clap(conflicts_with = "path", long, short, value_name = "keywords")]
|
#[clap(conflicts_with = "paths", long, short, value_name = "keywords")]
|
||||||
pub interactive: Option<Vec<String>>,
|
pub interactive: Option<Vec<String>>,
|
||||||
#[clap(
|
#[clap(
|
||||||
conflicts_with = "interactive",
|
conflicts_with = "interactive",
|
||||||
required_unless_present = "interactive",
|
required_unless_present = "interactive",
|
||||||
value_hint = ValueHint::DirPath
|
value_hint = ValueHint::DirPath
|
||||||
)]
|
)]
|
||||||
pub path: Option<String>,
|
pub paths: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,33 +9,41 @@ use std::path::Path;
|
||||||
|
|
||||||
impl Run for Add {
|
impl Run for Add {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
let path = if config::resolve_symlinks() {
|
|
||||||
util::canonicalize(&self.path)
|
|
||||||
} else {
|
|
||||||
util::resolve_path(&self.path)
|
|
||||||
}?;
|
|
||||||
let path = util::path_to_str(&path)?;
|
|
||||||
let now = util::current_time()?;
|
|
||||||
|
|
||||||
// These characters can't be printed cleanly to a single line, so they
|
// These characters can't be printed cleanly to a single line, so they
|
||||||
// can cause confusion when writing to fzf / stdout.
|
// can cause confusion when writing to fzf / stdout.
|
||||||
const EXCLUDE_CHARS: &[char] = &['\n', '\r'];
|
const EXCLUDE_CHARS: &[char] = &['\n', '\r'];
|
||||||
let mut exclude_dirs = config::exclude_dirs()?.into_iter();
|
|
||||||
if exclude_dirs.any(|pattern| pattern.matches(path)) || path.contains(EXCLUDE_CHARS) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
if !Path::new(path).is_dir() {
|
|
||||||
bail!("not a directory: {}", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data_dir = config::data_dir()?;
|
let data_dir = config::data_dir()?;
|
||||||
|
let exclude_dirs = config::exclude_dirs()?;
|
||||||
let max_age = config::maxage()?;
|
let max_age = config::maxage()?;
|
||||||
|
let now = util::current_time()?;
|
||||||
|
|
||||||
let mut db = DatabaseFile::new(data_dir);
|
let mut db = DatabaseFile::new(data_dir);
|
||||||
let mut db = db.open()?;
|
let mut db = db.open()?;
|
||||||
|
|
||||||
db.add(path, now);
|
for path in self.paths.iter() {
|
||||||
db.age(max_age);
|
let path = if config::resolve_symlinks() {
|
||||||
|
util::canonicalize(path)
|
||||||
|
} else {
|
||||||
|
util::resolve_path(path)
|
||||||
|
}?;
|
||||||
|
let path = util::path_to_str(&path)?;
|
||||||
|
|
||||||
|
// Ignore path if it contains unsupported characters, or if it's in
|
||||||
|
// the exclude list.
|
||||||
|
if path.contains(EXCLUDE_CHARS) || exclude_dirs.iter().any(|glob| glob.matches(path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if !Path::new(path).is_dir() {
|
||||||
|
bail!("not a directory: {}", path);
|
||||||
|
}
|
||||||
|
db.add(path, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if db.modified {
|
||||||
|
db.age(max_age);
|
||||||
|
db.save()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use std::fs;
|
||||||
|
|
||||||
impl Run for Import {
|
impl Run for Import {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
let buffer = &fs::read_to_string(&self.path).with_context(|| {
|
let buffer = fs::read_to_string(&self.path).with_context(|| {
|
||||||
format!("could not open database for importing: {}", &self.path.display())
|
format!("could not open database for importing: {}", &self.path.display())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
@ -20,12 +20,12 @@ impl Run for Import {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.from {
|
match self.from {
|
||||||
ImportFrom::Autojump => from_autojump(db, buffer),
|
ImportFrom::Autojump => from_autojump(db, &buffer),
|
||||||
ImportFrom::Z => from_z(db, buffer),
|
ImportFrom::Z => from_z(db, &buffer),
|
||||||
}
|
}
|
||||||
.context("import error")?;
|
.context("import error")?;
|
||||||
|
|
||||||
Ok(())
|
db.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::app::{Query, Run};
|
use crate::app::{Query, Run};
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::db::DatabaseFile;
|
use crate::db::{Database, DatabaseFile};
|
||||||
use crate::error::BrokenPipeHandler;
|
use crate::error::BrokenPipeHandler;
|
||||||
use crate::fzf::Fzf;
|
use crate::fzf::Fzf;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
@ -14,6 +14,12 @@ impl Run for Query {
|
||||||
let data_dir = config::data_dir()?;
|
let data_dir = config::data_dir()?;
|
||||||
let mut db = DatabaseFile::new(data_dir);
|
let mut db = DatabaseFile::new(data_dir);
|
||||||
let mut db = db.open()?;
|
let mut db = db.open()?;
|
||||||
|
self.query(&mut db).and(db.save())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Query {
|
||||||
|
fn query(&self, db: &mut Database) -> Result<()> {
|
||||||
let now = util::current_time()?;
|
let now = util::current_time()?;
|
||||||
|
|
||||||
let mut stream = db.stream(now).with_keywords(&self.keywords);
|
let mut stream = db.stream(now).with_keywords(&self.keywords);
|
||||||
|
|
|
||||||
|
|
@ -28,35 +28,25 @@ impl Run for Remove {
|
||||||
|
|
||||||
selection = fzf.wait_select()?;
|
selection = fzf.wait_select()?;
|
||||||
let paths = selection.lines().filter_map(|line| line.get(5..));
|
let paths = selection.lines().filter_map(|line| line.get(5..));
|
||||||
let mut not_found = Vec::new();
|
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if !db.remove(&path) {
|
if !db.remove(path) {
|
||||||
not_found.push(path);
|
bail!("path not found in database: {}", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !not_found.is_empty() {
|
|
||||||
let mut err = "path not found in database:".to_string();
|
|
||||||
for path in not_found {
|
|
||||||
err.push_str("\n ");
|
|
||||||
err.push_str(path.as_ref());
|
|
||||||
}
|
|
||||||
bail!(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// unwrap is safe here because path is required_unless_present = "interactive"
|
for path in self.paths.iter() {
|
||||||
let path = self.path.as_ref().unwrap();
|
if !db.remove(path) {
|
||||||
if !db.remove(path) {
|
let path_abs = util::resolve_path(path)?;
|
||||||
let path_abs = util::resolve_path(&path)?;
|
let path_abs = util::path_to_str(&path_abs)?;
|
||||||
let path_abs = util::path_to_str(&path_abs)?;
|
if path_abs != path && !db.remove(path_abs) {
|
||||||
if path_abs != path && !db.remove(path) {
|
bail!("path not found in database: {} ({})", path, path_abs)
|
||||||
bail!("path not found in database:\n {}", &path)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
db.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
|
||||||
pub struct Database<'file> {
|
pub struct Database<'file> {
|
||||||
pub dirs: DirList<'file>,
|
pub dirs: DirList<'file>,
|
||||||
pub modified: bool,
|
pub modified: bool,
|
||||||
pub data_dir: &'file PathBuf,
|
pub data_dir: &'file Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'file> Database<'file> {
|
impl<'file> Database<'file> {
|
||||||
|
|
@ -25,7 +25,7 @@ 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(|| {
|
let mut file = NamedTempFile::new_in(self.data_dir).with_context(|| {
|
||||||
format!("could not create temporary database in: {}", self.data_dir.display())
|
format!("could not create temporary database in: {}", self.data_dir.display())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
@ -125,16 +125,6 @@ impl<'file> Database<'file> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Database<'_> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// Since the error can't be properly handled here,
|
|
||||||
// pretty-print it instead.
|
|
||||||
if let Err(e) = self.save() {
|
|
||||||
let _ = writeln!(io::stderr(), "zoxide: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
||||||
use rand::distributions::{Distribution, Uniform};
|
use rand::distributions::{Distribution, Uniform};
|
||||||
|
|
@ -168,7 +158,7 @@ fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), Persi
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn persist<P: AsRef<Path>>(file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
fn persist<P: AsRef<Path>>(file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
||||||
file.persist(&path)?;
|
file.persist(path)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,6 +221,7 @@ mod tests {
|
||||||
let mut db = db.open().unwrap();
|
let mut db = db.open().unwrap();
|
||||||
db.add(path, now);
|
db.add(path, now);
|
||||||
db.add(path, now);
|
db.add(path, now);
|
||||||
|
db.save().unwrap();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut db = DatabaseFile::new(data_dir.path());
|
let mut db = DatabaseFile::new(data_dir.path());
|
||||||
|
|
@ -253,17 +244,20 @@ mod tests {
|
||||||
let mut db = DatabaseFile::new(data_dir.path());
|
let mut db = DatabaseFile::new(data_dir.path());
|
||||||
let mut db = db.open().unwrap();
|
let mut db = db.open().unwrap();
|
||||||
db.add(path, now);
|
db.add(path, now);
|
||||||
|
db.save().unwrap();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut db = DatabaseFile::new(data_dir.path());
|
let mut db = DatabaseFile::new(data_dir.path());
|
||||||
let mut db = db.open().unwrap();
|
let mut db = db.open().unwrap();
|
||||||
assert!(db.remove(path));
|
assert!(db.remove(path));
|
||||||
|
db.save().unwrap();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut db = DatabaseFile::new(data_dir.path());
|
let mut db = DatabaseFile::new(data_dir.path());
|
||||||
let mut db = db.open().unwrap();
|
let mut db = db.open().unwrap();
|
||||||
assert!(db.dirs.is_empty());
|
assert!(db.dirs.is_empty());
|
||||||
assert!(!db.remove(path));
|
assert!(!db.remove(path));
|
||||||
|
db.save().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ Set-Alias {{cmd}}i __zoxide_zi
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
|
|
||||||
{{ section }}
|
{{ section }}
|
||||||
# To initialize zoxide, add this to your configuration (the location is stored
|
# To initialize zoxide, add this to your configuration (find it with
|
||||||
# in $profile):
|
# `echo $profile`):
|
||||||
#
|
#
|
||||||
# Invoke-Expression (& { $hook = if ($PSVersionTable.PSVersion.Major -ge 6) { 'pwd' } else { 'prompt' } (zoxide init powershell --hook $hook) -join "`n" })
|
# Invoke-Expression (& { $hook = if ($PSVersionTable.PSVersion.Major -ge 6) { 'pwd' } else { 'prompt' } (zoxide init powershell --hook $hook) -join "`n" })
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue