diff --git a/src/cmd/query.rs b/src/cmd/query.rs index 362d80a3..95c8a88c 100644 --- a/src/cmd/query.rs +++ b/src/cmd/query.rs @@ -78,7 +78,7 @@ impl Query { fn get_stream<'a>(&self, db: &'a mut Database, now: Epoch) -> Result> { let mut options = StreamOptions::new(now) - .with_keywords(self.keywords.iter().map(|s| s.as_str())) + .with_keywords(self.transformed_keywords()) .with_exclude(config::exclude_dirs()?); if !self.all { let resolve_symlinks = config::resolve_symlinks(); @@ -117,4 +117,23 @@ impl Query { } .spawn() } + + /// ## Returns + /// `self.keywords` with file paths transformed into + /// their parent directory paths, directory paths unchanged + /// + /// ## Notes + /// - Heap allocates an iterator of Strings with length of self.keywords + /// - Only uses sans-IO Path methods + fn transformed_keywords(&self) -> impl Iterator + use<'_> { + self.keywords.iter().map(|keyword| { + let path = std::path::Path::new(keyword); + match path.parent() { + None => keyword, + Some(path) if path.to_str() == Some("") => keyword, + Some(path) => path.to_str().unwrap(), + } + .to_string() + }) + } } diff --git a/src/db/stream.rs b/src/db/stream.rs index 4af7d7a9..8d99e9f3 100644 --- a/src/db/stream.rs +++ b/src/db/stream.rs @@ -48,16 +48,16 @@ impl<'a> Stream<'a> { } fn filter_by_keywords(&self, path: &str) -> bool { - let (keywords_last, keywords) = match self.options.keywords.split_last() { + let (last_keyword, keywords) = match self.options.keywords.split_last() { Some(split) => split, None => return true, }; let path = util::to_lowercase(path); let mut path = path.as_str(); - match path.rfind(keywords_last) { + match path.rfind(last_keyword) { Some(idx) => { - if path[idx + keywords_last.len()..].contains(path::is_separator) { + if path[idx + last_keyword.len()..].contains(path::is_separator) { return false; } path = &path[..idx];