From 04950b2a58ee6bbe9f9250a9887595a984cb7283 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 29 Jul 2021 08:23:46 +0530 Subject: [PATCH] zoxide-remove should accept multiple arguments --- CHANGELOG.md | 2 +- contrib/completions/_zoxide | 2 +- contrib/completions/zoxide.bash | 2 +- man/zoxide-remove.1 | 2 +- src/app/_app.rs | 4 ++-- src/app/add.rs | 1 + src/app/import.rs | 2 +- src/app/query.rs | 8 +++++++- src/app/remove.rs | 28 +++++++++------------------- src/db/mod.rs | 16 +++++----------- 10 files changed, 29 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b5caf7..2300c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `zoxide add` now accepts multiple arguments. +- `zoxide add` and `zoxide remove` now accept multiple arguments. ### Fixed diff --git a/contrib/completions/_zoxide b/contrib/completions/_zoxide index 4ae73e7..1548e9b 100644 --- a/contrib/completions/_zoxide +++ b/contrib/completions/_zoxide @@ -75,7 +75,7 @@ _arguments "${_arguments_options[@]}" \ '()*--interactive=[]' \ '-h[Prints help information]' \ '--help[Prints help information]' \ -'::path:_files -/' \ +'*::paths:_files -/' \ && ret=0 ;; esac diff --git a/contrib/completions/zoxide.bash b/contrib/completions/zoxide.bash index 5a351bb..749b1ef 100644 --- a/contrib/completions/zoxide.bash +++ b/contrib/completions/zoxide.bash @@ -127,7 +127,7 @@ _zoxide() { return 0 ;; zoxide__remove) - opts=" -i -h --interactive --help " + opts=" -i -h --interactive --help ... " if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/man/zoxide-remove.1 b/man/zoxide-remove.1 index f0f186e..ee71640 100644 --- a/man/zoxide-remove.1 +++ b/man/zoxide-remove.1 @@ -2,7 +2,7 @@ .SH NAME zoxide-remove - remove a directory from the database .SH SYNOPSIS -.B zoxide remove \fIPATH [OPTIONS]\fR +.B zoxide remove \fI[PATHS] [OPTIONS]\fR .SH DESCRIPTION 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). diff --git a/src/app/_app.rs b/src/app/_app.rs index af96e9b..0ce7b2a 100644 --- a/src/app/_app.rs +++ b/src/app/_app.rs @@ -126,12 +126,12 @@ pub struct Query { #[derive(Clap, Debug)] pub struct Remove { // Use interactive selection - #[clap(conflicts_with = "path", long, short, value_name = "keywords")] + #[clap(conflicts_with = "paths", long, short, value_name = "keywords")] pub interactive: Option>, #[clap( conflicts_with = "interactive", required_unless_present = "interactive", value_hint = ValueHint::DirPath )] - pub path: Option, + pub paths: Vec, } diff --git a/src/app/add.rs b/src/app/add.rs index 37b767c..7f73400 100644 --- a/src/app/add.rs +++ b/src/app/add.rs @@ -42,6 +42,7 @@ impl Run for Add { if db.modified { db.age(max_age); + db.save()?; } Ok(()) diff --git a/src/app/import.rs b/src/app/import.rs index 128c3ec..cdb5bed 100644 --- a/src/app/import.rs +++ b/src/app/import.rs @@ -25,7 +25,7 @@ impl Run for Import { } .context("import error")?; - Ok(()) + db.save() } } diff --git a/src/app/query.rs b/src/app/query.rs index 3dfee24..5abd28d 100644 --- a/src/app/query.rs +++ b/src/app/query.rs @@ -1,6 +1,6 @@ use crate::app::{Query, Run}; use crate::config; -use crate::db::DatabaseFile; +use crate::db::{Database, DatabaseFile}; use crate::error::BrokenPipeHandler; use crate::fzf::Fzf; use crate::util; @@ -14,6 +14,12 @@ impl Run for Query { let data_dir = config::data_dir()?; let mut db = DatabaseFile::new(data_dir); 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 mut stream = db.stream(now).with_keywords(&self.keywords); diff --git a/src/app/remove.rs b/src/app/remove.rs index 99eb48c..fe8e90a 100644 --- a/src/app/remove.rs +++ b/src/app/remove.rs @@ -28,35 +28,25 @@ impl Run for Remove { selection = fzf.wait_select()?; let paths = selection.lines().filter_map(|line| line.get(5..)); - let mut not_found = Vec::new(); for path in paths { 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 => { - // unwrap is safe here because path is required_unless_present = "interactive" - let path = self.path.as_ref().unwrap(); - if !db.remove(path) { - let path_abs = util::resolve_path(&path)?; - let path_abs = util::path_to_str(&path_abs)?; - if path_abs != path && !db.remove(path) { - bail!("path not found in database:\n {}", &path) + for path in self.paths.iter() { + if !db.remove(path) { + let path_abs = util::resolve_path(&path)?; + let path_abs = util::path_to_str(&path_abs)?; + if path_abs != path && !db.remove(path_abs) { + bail!("path not found in database: {} ({})", path, path_abs) + } } } } } - Ok(()) + db.save() } } diff --git a/src/db/mod.rs b/src/db/mod.rs index 6808f06..8d67eb5 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; pub struct Database<'file> { pub dirs: DirList<'file>, pub modified: bool, - pub data_dir: &'file PathBuf, + pub data_dir: &'file Path, } impl<'file> Database<'file> { @@ -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)] fn persist>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> { use rand::distributions::{Distribution, Uniform}; @@ -231,6 +221,7 @@ mod tests { 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()); @@ -253,17 +244,20 @@ mod tests { let mut db = DatabaseFile::new(data_dir.path()); let mut db = db.open().unwrap(); db.add(path, now); + db.save().unwrap(); } { let mut db = DatabaseFile::new(data_dir.path()); let mut db = db.open().unwrap(); assert!(db.remove(path)); + db.save().unwrap(); } { let mut db = DatabaseFile::new(data_dir.path()); let mut db = db.open().unwrap(); assert!(db.dirs.is_empty()); assert!(!db.remove(path)); + db.save().unwrap(); } } }