Merge 3a4b198cef
into 194f8e31e4
This commit is contained in:
commit
2fd3a8afa3
|
@ -704,6 +704,15 @@ version = "1.0.20"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.26"
|
||||
|
@ -831,6 +840,16 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -858,6 +877,15 @@ dependencies = [
|
|||
"winsafe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
|
@ -1004,5 +1032,6 @@ dependencies = [
|
|||
"rstest_reuse",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"walkdir",
|
||||
"which",
|
||||
]
|
||||
|
|
|
@ -30,6 +30,7 @@ fastrand = "2.0.0"
|
|||
glob = "0.3.0"
|
||||
ouroboros = "0.18.3"
|
||||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
walkdir = "2.5.0"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { version = "0.30.1", default-features = false, features = [
|
||||
|
|
|
@ -32,6 +32,8 @@ _zoxide() {
|
|||
_arguments "${_arguments_options[@]}" : \
|
||||
'-s+[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \
|
||||
'--score=[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \
|
||||
'-r[Recursively add directories]' \
|
||||
'--recursive[Recursively add directories]' \
|
||||
'-h[Print help]' \
|
||||
'--help[Print help]' \
|
||||
'-V[Print version]' \
|
||||
|
@ -138,6 +140,8 @@ _arguments "${_arguments_options[@]}" : \
|
|||
;;
|
||||
(remove)
|
||||
_arguments "${_arguments_options[@]}" : \
|
||||
'-r[Recursively remove directories]' \
|
||||
'--recursive[Recursively remove directories]' \
|
||||
'-h[Print help]' \
|
||||
'--help[Print help]' \
|
||||
'-V[Print version]' \
|
||||
|
|
|
@ -36,6 +36,8 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
|
|||
'zoxide;add' {
|
||||
[CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t')
|
||||
[CompletionResult]::new('--score', '--score', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t')
|
||||
[CompletionResult]::new('-r', '-r', [CompletionResultType]::ParameterName, 'Recursively add directories')
|
||||
[CompletionResult]::new('--recursive', '--recursive', [CompletionResultType]::ParameterName, 'Recursively add directories')
|
||||
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
|
||||
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
|
||||
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
|
||||
|
@ -118,6 +120,8 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
|
|||
break
|
||||
}
|
||||
'zoxide;remove' {
|
||||
[CompletionResult]::new('-r', '-r', [CompletionResultType]::ParameterName, 'Recursively remove directories')
|
||||
[CompletionResult]::new('--recursive', '--recursive', [CompletionResultType]::ParameterName, 'Recursively remove directories')
|
||||
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
|
||||
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
|
||||
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
|
||||
|
|
|
@ -67,7 +67,7 @@ _zoxide() {
|
|||
return 0
|
||||
;;
|
||||
zoxide__add)
|
||||
opts="-s -h -V --score --help --version <PATHS>..."
|
||||
opts="-s -r -h -V --score --recursive --help --version <PATHS>..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
@ -227,7 +227,7 @@ _zoxide() {
|
|||
return 0
|
||||
;;
|
||||
zoxide__remove)
|
||||
opts="-h -V --help --version [PATHS]..."
|
||||
opts="-r -h -V --recursive --help --version [PATHS]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
|
|
@ -32,6 +32,8 @@ set edit:completion:arg-completer[zoxide] = {|@words|
|
|||
&'zoxide;add'= {
|
||||
cand -s 'The rank to increment the entry if it exists or initialize it with if it doesn''t'
|
||||
cand --score 'The rank to increment the entry if it exists or initialize it with if it doesn''t'
|
||||
cand -r 'Recursively add directories'
|
||||
cand --recursive 'Recursively add directories'
|
||||
cand -h 'Print help'
|
||||
cand --help 'Print help'
|
||||
cand -V 'Print version'
|
||||
|
@ -105,6 +107,8 @@ set edit:completion:arg-completer[zoxide] = {|@words|
|
|||
cand --version 'Print version'
|
||||
}
|
||||
&'zoxide;remove'= {
|
||||
cand -r 'Recursively remove directories'
|
||||
cand --recursive 'Recursively remove directories'
|
||||
cand -h 'Print help'
|
||||
cand --help 'Print help'
|
||||
cand -V 'Print version'
|
||||
|
|
|
@ -33,6 +33,7 @@ complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "init" -d 'Generate sh
|
|||
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "query" -d 'Search for a directory in the database'
|
||||
complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "remove" -d 'Remove a directory from the database'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s s -l score -d 'The rank to increment the entry if it exists or initialize it with if it doesn\'t' -r
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s r -l recursive -d 'Recursively add directories'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s h -l help -d 'Print help'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s V -l version -d 'Print version'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -s h -l help -d 'Print help'
|
||||
|
@ -69,5 +70,6 @@ complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s l -l list -d 'Li
|
|||
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s s -l score -d 'Print score with results'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s h -l help -d 'Print help'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s V -l version -d 'Print version'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s r -l recursive -d 'Recursively remove directories'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s h -l help -d 'Print help'
|
||||
complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s V -l version -d 'Print version'
|
||||
|
|
|
@ -10,6 +10,7 @@ module completions {
|
|||
export extern "zoxide add" [
|
||||
...paths: path
|
||||
--score(-s): string # The rank to increment the entry if it exists or initialize it with if it doesn't
|
||||
--recursive(-r) # Recursively add directories
|
||||
--help(-h) # Print help
|
||||
--version(-V) # Print version
|
||||
]
|
||||
|
@ -90,6 +91,7 @@ module completions {
|
|||
# Remove a directory from the database
|
||||
export extern "zoxide remove" [
|
||||
...paths: path
|
||||
--recursive(-r) # Recursively remove directories
|
||||
--help(-h) # Print help
|
||||
--version(-V) # Print version
|
||||
]
|
||||
|
|
|
@ -15,6 +15,10 @@ const completion: Fig.Spec = {
|
|||
isOptional: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["-r", "--recursive"],
|
||||
description: "Recursively add directories",
|
||||
},
|
||||
{
|
||||
name: ["-h", "--help"],
|
||||
description: "Print help",
|
||||
|
@ -267,6 +271,10 @@ const completion: Fig.Spec = {
|
|||
name: "remove",
|
||||
description: "Remove a directory from the database",
|
||||
options: [
|
||||
{
|
||||
name: ["-r", "--recursive"],
|
||||
description: "Recursively remove directories",
|
||||
},
|
||||
{
|
||||
name: ["-h", "--help"],
|
||||
description: "Print help",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
|
@ -18,10 +18,17 @@ impl Run for Add {
|
|||
|
||||
let mut db = Database::open()?;
|
||||
|
||||
for path in &self.paths {
|
||||
// Build a unified iterator of PathBufs, whether recursive or not.
|
||||
let paths: Box<dyn Iterator<Item = PathBuf>> = if self.recursive {
|
||||
Box::new(self.paths.iter().flat_map(|p| util::walk_dir(p)))
|
||||
} else {
|
||||
Box::new(self.paths.iter().cloned())
|
||||
};
|
||||
|
||||
for path in paths {
|
||||
let path =
|
||||
if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }(
|
||||
path,
|
||||
&path,
|
||||
)?;
|
||||
let path = util::path_to_str(&path)?;
|
||||
|
||||
|
|
|
@ -63,6 +63,10 @@ pub struct Add {
|
|||
/// doesn't
|
||||
#[clap(short, long)]
|
||||
pub score: Option<f64>,
|
||||
|
||||
/// Recursively add directories
|
||||
#[clap(short, long, default_value_t = false)]
|
||||
pub recursive: bool,
|
||||
}
|
||||
|
||||
/// Edit the database
|
||||
|
@ -201,4 +205,8 @@ pub struct Query {
|
|||
pub struct Remove {
|
||||
#[clap(value_hint = ValueHint::DirPath)]
|
||||
pub paths: Vec<String>,
|
||||
|
||||
/// Recursively remove directories
|
||||
#[clap(short, long, default_value_t = false)]
|
||||
pub recursive: bool,
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ impl Run for Edit {
|
|||
match cmd {
|
||||
EditCommand::Decrement { path } => db.add(path, -1.0, now),
|
||||
EditCommand::Delete { path } => {
|
||||
db.remove(path);
|
||||
db.remove(path, false);
|
||||
}
|
||||
EditCommand::Increment { path } => db.add(path, 1.0, now),
|
||||
EditCommand::Reload => {}
|
||||
|
|
|
@ -9,10 +9,10 @@ impl Run for Remove {
|
|||
let mut db = Database::open()?;
|
||||
|
||||
for path in &self.paths {
|
||||
if !db.remove(path) {
|
||||
if !db.remove(path, self.recursive) {
|
||||
let path_abs = util::resolve_path(path)?;
|
||||
let path_abs = util::path_to_str(&path_abs)?;
|
||||
if path_abs == path || !db.remove(path_abs) {
|
||||
if path_abs == path || !db.remove(path_abs, self.recursive) {
|
||||
bail!("path not found in database: {path}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,17 +101,35 @@ impl Database {
|
|||
}
|
||||
|
||||
/// Removes the directory with `path` from the store. This does not preserve
|
||||
/// ordering, but is O(1).
|
||||
pub fn remove(&mut self, path: impl AsRef<str>) -> bool {
|
||||
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
|
||||
Some(idx) => {
|
||||
self.swap_remove(idx);
|
||||
true
|
||||
/// ordering, but is O(1). If recursive, this will remove all directories
|
||||
/// starting with `path`. This is O(n)
|
||||
pub fn remove(&mut self, path: impl AsRef<str>, recursive: bool) -> bool {
|
||||
if recursive {
|
||||
self.remove_recursive(path)
|
||||
} else {
|
||||
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
|
||||
Some(idx) => {
|
||||
self.swap_remove(idx);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_recursive(&mut self, path: impl AsRef<str>) -> bool {
|
||||
let mut removed = false;
|
||||
self.with_dirs_mut(|dirs| {
|
||||
dirs.retain(|dir| {
|
||||
let keep = !dir.path.starts_with(path.as_ref());
|
||||
removed |= !keep;
|
||||
keep
|
||||
});
|
||||
});
|
||||
self.with_dirty_mut(|dirty| *dirty = removed);
|
||||
removed
|
||||
}
|
||||
|
||||
pub fn swap_remove(&mut self, idx: usize) {
|
||||
self.with_dirs_mut(|dirs| dirs.swap_remove(idx));
|
||||
self.with_dirty_mut(|dirty| *dirty = true);
|
||||
|
@ -273,14 +291,14 @@ mod tests {
|
|||
|
||||
{
|
||||
let mut db = Database::open_dir(data_dir.path()).unwrap();
|
||||
assert!(db.remove(path));
|
||||
assert!(db.remove(path, false));
|
||||
db.save().unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let mut db = Database::open_dir(data_dir.path()).unwrap();
|
||||
assert!(db.dirs().is_empty());
|
||||
assert!(!db.remove(path));
|
||||
assert!(!db.remove(path, false));
|
||||
db.save().unwrap();
|
||||
}
|
||||
}
|
||||
|
|
10
src/util.rs
10
src/util.rs
|
@ -9,6 +9,7 @@ use std::{env, mem};
|
|||
#[cfg(windows)]
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{Context, Result, bail};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::db::{Dir, Epoch};
|
||||
use crate::error::SilentExit;
|
||||
|
@ -382,3 +383,12 @@ pub fn to_lowercase(s: impl AsRef<str>) -> String {
|
|||
let s = s.as_ref();
|
||||
if s.is_ascii() { s.to_ascii_lowercase() } else { s.to_lowercase() }
|
||||
}
|
||||
|
||||
/// Recursively walk a directory and yield all directories.
|
||||
pub fn walk_dir(path: &Path) -> impl Iterator<Item = PathBuf> {
|
||||
WalkDir::new(path)
|
||||
.into_iter()
|
||||
.filter_map(|p| p.ok())
|
||||
.filter(|p| p.file_type().is_dir())
|
||||
.map(|p| p.into_path())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue