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.
This commit is contained in:
andy.boot
2021-10-24 10:13:12 +01:00
parent 1b07c3c4f3
commit 9f91d446c1
4 changed files with 40 additions and 32 deletions
+5 -5
View File
@@ -20,8 +20,8 @@ use crate::platform::get_metadata;
pub struct WalkData { pub struct WalkData {
pub ignore_directories: HashSet<PathBuf>, pub ignore_directories: HashSet<PathBuf>,
pub filter_regex: Option<Regex>, pub filter_regex: Vec<Regex>,
pub invert_filter_regex: Option<Regex>, pub invert_filter_regex: Vec<Regex>,
pub allowed_filesystems: HashSet<u64>, pub allowed_filesystems: HashSet<u64>,
pub use_apparent_size: bool, pub use_apparent_size: bool,
pub by_filecount: 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 // Keeping `walk_data.filter_regex.is_empty()` is important for performance reasons, it stops unnecessary work
if walk_data.filter_regex.is_some() if !walk_data.filter_regex.is_empty()
&& entry.path().is_file() && entry.path().is_file()
&& is_filtered_out_due_to_regex(&walk_data.filter_regex, &entry.path()) && is_filtered_out_due_to_regex(&walk_data.filter_regex, &entry.path())
{ {
return true; return true;
} }
if walk_data.invert_filter_regex.is_some() if !walk_data.invert_filter_regex.is_empty()
&& entry.path().is_file() && entry.path().is_file()
&& is_filtered_out_due_to_invert_regex(&walk_data.invert_filter_regex, &entry.path()) && is_filtered_out_due_to_invert_regex(&walk_data.invert_filter_regex, &entry.path())
{ {
+19 -13
View File
@@ -8,6 +8,7 @@ use std::collections::HashSet;
use std::process; use std::process;
use self::display::draw_it; use self::display::draw_it;
use clap::Values;
use clap::{App, AppSettings, Arg}; use clap::{App, AppSettings, Arg};
use dir_walker::walk_it; use dir_walker::walk_it;
use dir_walker::WalkData; use dir_walker::WalkData;
@@ -83,18 +84,21 @@ fn get_width_of_terminal() -> usize {
} }
} }
fn get_regex_value(maybe_value: Option<&str>) -> Option<Regex> { fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> {
match maybe_value { let mut result = vec![];
Some(v) => match Regex::new(v) { if let Some(v) = maybe_value {
Ok(r) => Some(r), for reg in v {
match Regex::new(reg) {
Ok(r) => result.push(r),
Err(e) => { Err(e) => {
eprintln!("Ignoring bad value for regex {:?}", e); eprintln!("Ignoring bad value for regex {:?}", e);
process::exit(1); process::exit(1);
} }
},
None => None,
} }
} }
}
result
}
fn main() { fn main() {
let default_height = get_height_of_terminal(); let default_height = get_height_of_terminal();
@@ -225,8 +229,8 @@ fn main() {
let summarize_file_types = options.is_present("types"); let summarize_file_types = options.is_present("types");
let maybe_filter = get_regex_value(options.value_of("filter")); let filter_regexs = get_regex_value(options.values_of("filter"));
let maybe_invert_filter = get_regex_value(options.value_of("invert_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) { let number_of_lines = match value_t!(options.value_of("number_of_lines"), usize) {
Ok(v) => v, 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<PathBuf> = ignore_directories let ignored_full_path: HashSet<PathBuf> = ignore_directories
.into_iter() .into_iter()
.flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone()))) .flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone())))
@@ -276,8 +285,8 @@ fn main() {
let walk_data = WalkData { let walk_data = WalkData {
ignore_directories: ignored_full_path, ignore_directories: ignored_full_path,
filter_regex: maybe_filter, filter_regex: filter_regexs,
invert_filter_regex: maybe_invert_filter, invert_filter_regex: invert_filter_regexs,
allowed_filesystems, allowed_filesystems,
use_apparent_size, use_apparent_size,
by_filecount, by_filecount,
@@ -299,9 +308,6 @@ fn main() {
} }
}; };
if options.is_present("filter") {
println!("Filtering by: {}", options.value_of("filter").unwrap());
}
if has_errors { if has_errors {
eprintln!("Did not have permissions for all directories"); eprintln!("Did not have permissions for all directories");
} }
+2 -2
View File
@@ -18,8 +18,8 @@ pub struct Node {
pub fn build_node( pub fn build_node(
dir: PathBuf, dir: PathBuf,
children: Vec<Node>, children: Vec<Node>,
filter_regex: &Option<Regex>, filter_regex: &[Regex],
invert_filter_regex: &Option<Regex>, invert_filter_regex: &[Regex],
use_apparent_size: bool, use_apparent_size: bool,
is_symlink: bool, is_symlink: bool,
is_file: bool, is_file: bool,
+11 -9
View File
@@ -57,18 +57,20 @@ pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
path.as_ref().components().collect::<PathBuf>() path.as_ref().components().collect::<PathBuf>()
} }
pub fn is_filtered_out_due_to_regex(filter_regex: &Option<Regex>, dir: &Path) -> bool { pub fn is_filtered_out_due_to_regex(filter_regex: &[Regex], dir: &Path) -> bool {
match filter_regex { if filter_regex.is_empty() {
Some(fr) => !fr.is_match(&dir.as_os_str().to_string_lossy()), false
None => 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<Regex>, dir: &Path) -> bool { pub fn is_filtered_out_due_to_invert_regex(filter_regex: &[Regex], dir: &Path) -> bool {
match filter_regex { filter_regex
Some(fr) => fr.is_match(&dir.as_os_str().to_string_lossy()), .iter()
None => false, .any(|f| f.is_match(&dir.as_os_str().to_string_lossy()))
}
} }
fn is_a_parent_of<P: AsRef<Path>>(parent: P, child: P) -> bool { fn is_a_parent_of<P: AsRef<Path>>(parent: P, child: P) -> bool {