From 9f91d446c12d17faea025d38ad71b91667ecc6b2 Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Sun, 24 Oct 2021 10:13:12 +0100 Subject: [PATCH] Feature/Bugfix: Allow multiple regexs to be used The -e and -v flags allow multiple values. Before values after the first were ignored. This change allows the user to specify multiple regexs and have them all applied. --- src/dir_walker.rs | 10 +++++----- src/main.rs | 38 ++++++++++++++++++++++---------------- src/node.rs | 4 ++-- src/utils.rs | 20 +++++++++++--------- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/dir_walker.rs b/src/dir_walker.rs index 939ae78..85ce955 100644 --- a/src/dir_walker.rs +++ b/src/dir_walker.rs @@ -20,8 +20,8 @@ use crate::platform::get_metadata; pub struct WalkData { pub ignore_directories: HashSet, - pub filter_regex: Option, - pub invert_filter_regex: Option, + pub filter_regex: Vec, + pub invert_filter_regex: Vec, pub allowed_filesystems: HashSet, pub use_apparent_size: bool, pub by_filecount: bool, @@ -90,15 +90,15 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool { } } - // Keeping `walk_data.filter_regex.is_some()` is important for performance reasons, it stops unnecessary work - if walk_data.filter_regex.is_some() + // Keeping `walk_data.filter_regex.is_empty()` is important for performance reasons, it stops unnecessary work + if !walk_data.filter_regex.is_empty() && entry.path().is_file() && is_filtered_out_due_to_regex(&walk_data.filter_regex, &entry.path()) { return true; } - if walk_data.invert_filter_regex.is_some() + if !walk_data.invert_filter_regex.is_empty() && entry.path().is_file() && is_filtered_out_due_to_invert_regex(&walk_data.invert_filter_regex, &entry.path()) { diff --git a/src/main.rs b/src/main.rs index fbd918b..f925cda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; use std::process; use self::display::draw_it; +use clap::Values; use clap::{App, AppSettings, Arg}; use dir_walker::walk_it; use dir_walker::WalkData; @@ -83,17 +84,20 @@ fn get_width_of_terminal() -> usize { } } -fn get_regex_value(maybe_value: Option<&str>) -> Option { - match maybe_value { - Some(v) => match Regex::new(v) { - Ok(r) => Some(r), - Err(e) => { - eprintln!("Ignoring bad value for regex {:?}", e); - process::exit(1); +fn get_regex_value(maybe_value: Option) -> Vec { + let mut result = vec![]; + if let Some(v) = maybe_value { + for reg in v { + match Regex::new(reg) { + Ok(r) => result.push(r), + Err(e) => { + eprintln!("Ignoring bad value for regex {:?}", e); + process::exit(1); + } } - }, - None => None, + } } + result } fn main() { @@ -225,8 +229,8 @@ fn main() { let summarize_file_types = options.is_present("types"); - let maybe_filter = get_regex_value(options.value_of("filter")); - let maybe_invert_filter = get_regex_value(options.value_of("invert_filter")); + let filter_regexs = get_regex_value(options.values_of("filter")); + let invert_filter_regexs = get_regex_value(options.values_of("invert_filter")); let number_of_lines = match value_t!(options.value_of("number_of_lines"), usize) { Ok(v) => v, @@ -269,6 +273,11 @@ fn main() { } }; + if options.is_present("filter") { + println!("Filtering by: {:?}", filter_regexs); + } + // todo incl invert regex + let ignored_full_path: HashSet = ignore_directories .into_iter() .flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone()))) @@ -276,8 +285,8 @@ fn main() { let walk_data = WalkData { ignore_directories: ignored_full_path, - filter_regex: maybe_filter, - invert_filter_regex: maybe_invert_filter, + filter_regex: filter_regexs, + invert_filter_regex: invert_filter_regexs, allowed_filesystems, use_apparent_size, by_filecount, @@ -299,9 +308,6 @@ fn main() { } }; - if options.is_present("filter") { - println!("Filtering by: {}", options.value_of("filter").unwrap()); - } if has_errors { eprintln!("Did not have permissions for all directories"); } diff --git a/src/node.rs b/src/node.rs index d30b7ef..ee84ab0 100644 --- a/src/node.rs +++ b/src/node.rs @@ -18,8 +18,8 @@ pub struct Node { pub fn build_node( dir: PathBuf, children: Vec, - filter_regex: &Option, - invert_filter_regex: &Option, + filter_regex: &[Regex], + invert_filter_regex: &[Regex], use_apparent_size: bool, is_symlink: bool, is_file: bool, diff --git a/src/utils.rs b/src/utils.rs index 51bef5d..47439ce 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -57,18 +57,20 @@ pub fn normalize_path>(path: P) -> PathBuf { path.as_ref().components().collect::() } -pub fn is_filtered_out_due_to_regex(filter_regex: &Option, dir: &Path) -> bool { - match filter_regex { - Some(fr) => !fr.is_match(&dir.as_os_str().to_string_lossy()), - None => false, +pub fn is_filtered_out_due_to_regex(filter_regex: &[Regex], dir: &Path) -> bool { + if filter_regex.is_empty() { + false + } else { + filter_regex + .iter() + .all(|f| !f.is_match(&dir.as_os_str().to_string_lossy())) } } -pub fn is_filtered_out_due_to_invert_regex(filter_regex: &Option, dir: &Path) -> bool { - match filter_regex { - Some(fr) => fr.is_match(&dir.as_os_str().to_string_lossy()), - None => false, - } +pub fn is_filtered_out_due_to_invert_regex(filter_regex: &[Regex], dir: &Path) -> bool { + filter_regex + .iter() + .any(|f| f.is_match(&dir.as_os_str().to_string_lossy())) } fn is_a_parent_of>(parent: P, child: P) -> bool {