From 40b3926bfe3f849d3c14ef25dbafca9b4f18c963 Mon Sep 17 00:00:00 2001 From: Scrim Date: Sun, 17 Dec 2023 12:19:56 -0500 Subject: [PATCH] feat: add flag to exclude directories from results and filtering --- src/builder.rs | 21 +++++++++++++++++++++ src/filter.rs | 5 ++++- src/search.rs | 14 +++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 6351a40..aafde82 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -25,6 +25,8 @@ pub struct SearchBuilder { hidden: bool, /// Filters Vector, defaults to empty vec filters: Vec, + /// When set to false, will not apply filters to directories and will exclude them from results. + dirs: bool, } impl SearchBuilder { @@ -42,6 +44,7 @@ impl SearchBuilder { self.ignore_case, self.hidden, self.filters.clone(), + self.dirs, ) } @@ -233,6 +236,23 @@ impl SearchBuilder { ); self } + + /// Choose whether to apply filters to directories and include matches in search results. Defaults to true. + /// ### Arguments + /// * `value` + /// ### Examples + /// ```rust + /// use rust_search::SearchBuilder; + /// + /// let search: Vec = SearchBuilder::default() + /// .dirs(false) + /// .build() + /// .collect(); + /// ``` + pub fn dirs(mut self, value: bool) -> Self { + self.dirs = value; + self + } } impl Default for SearchBuilder { @@ -249,6 +269,7 @@ impl Default for SearchBuilder { ignore_case: false, hidden: false, filters: vec![], + dirs: true, } } } diff --git a/src/filter.rs b/src/filter.rs index 2f8c308..e020008 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -14,8 +14,11 @@ pub enum FilterType { } impl FilterType { - pub fn apply(&self, dir: &DirEntry) -> bool { + pub fn apply(&self, dir: &DirEntry, filter_dirs: bool) -> bool { if let Ok(m) = dir.metadata() { + if !filter_dirs && m.file_type().is_dir() { + return true; + } match self { Self::Created(cmp, time) => { if let Ok(created) = m.created() { diff --git a/src/search.rs b/src/search.rs index 89a235c..a053633 100644 --- a/src/search.rs +++ b/src/search.rs @@ -59,6 +59,7 @@ impl Search { /// * `ignore_case` - Whether to ignore case or not /// * `hidden` - Whether to search hidden files or not /// * `filters` - Vector of filters to search by `DirEntry` data + /// * `dirs` - Whether to apply filters to directories and include them in results. #[allow(clippy::too_many_arguments)] pub(crate) fn new( search_location: impl AsRef, @@ -71,6 +72,7 @@ impl Search { ignore_case: bool, with_hidden: bool, filters: Vec, + dirs: bool, ) -> Self { let regex_search_input = utils::build_regex_search_input(search_input, file_ext, strict, ignore_case); @@ -85,7 +87,7 @@ impl Search { // filters getting applied to walker // only if all filters are true then the walker will return the file - walker.filter_entry(move |dir| filters.iter().all(|f| f.apply(dir))); + walker.filter_entry(move |entry| filters.iter().all(|f| f.apply(entry, dirs))); if let Some(locations) = more_locations { for location in locations { @@ -101,6 +103,16 @@ impl Search { Box::new(move |path_entry| { if let Ok(entry) = path_entry { + if !dirs { + // if dirs is false and entry is a directory, + // proceed with the search without sending its path or incrementing the counter + if let Ok(m) = entry.metadata() { + if m.file_type().is_dir() { + return WalkState::Continue; + } + } + } + let path = entry.path(); if let Some(file_name) = path.file_name() { // Lossy means that if the file name is not valid UTF-8