Skip to content

Commit 2e7b1d7

Browse files
committed
Add support for exact match
1 parent 845fe79 commit 2e7b1d7

File tree

9 files changed

+61
-2
lines changed

9 files changed

+61
-2
lines changed

contrib/completions/_zoxide

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/_zoxide.ps1

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zoxide.bash

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zoxide.elv

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zoxide.fish

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zoxide.ts

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/cmd.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ pub struct Query {
180180
/// Exclude the current directory
181181
#[clap(long, value_hint = ValueHint::DirPath, value_name = "path")]
182182
pub exclude: Option<String>,
183+
184+
/// Only match exact
185+
#[clap(long, short)]
186+
pub exact: bool,
183187
}
184188

185189
/// Remove a directory from the database

src/cmd/query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ impl Query {
7979
fn get_stream<'a>(&self, db: &'a mut Database, now: Epoch) -> Result<Stream<'a>> {
8080
let mut options = StreamOptions::new(now)
8181
.with_keywords(self.keywords.iter().map(|s| s.as_str()))
82-
.with_exclude(config::exclude_dirs()?);
82+
.with_exclude(config::exclude_dirs()?)
83+
.with_exact(self.exact);
8384
if !self.all {
8485
let resolve_symlinks = config::resolve_symlinks();
8586
options = options.with_exists(true).with_resolve_symlinks(resolve_symlinks);

src/db/stream.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use std::ffi::OsString;
12
use std::iter::Rev;
23
use std::ops::Range;
4+
use std::path::{Component, PathBuf};
35
use std::{fs, path};
46

57
use glob::Pattern;
@@ -40,6 +42,10 @@ impl<'a> Stream<'a> {
4042
continue;
4143
}
4244

45+
if !self.filter_by_exact(&dir.path) {
46+
continue;
47+
}
48+
4349
let dir = &self.db.dirs()[idx];
4450
return Some(dir);
4551
}
@@ -91,6 +97,34 @@ impl<'a> Stream<'a> {
9197
if self.options.resolve_symlinks { fs::symlink_metadata } else { fs::metadata };
9298
resolver(path).map(|metadata| metadata.is_dir()).unwrap_or_default()
9399
}
100+
101+
fn filter_by_exact(&self, path: &str) -> bool {
102+
if !self.options.exact {
103+
return true;
104+
}
105+
106+
let path = util::to_lowercase(path);
107+
let path = PathBuf::from(path);
108+
let mut components: Vec<Component> = path.components().collect();
109+
110+
for keyword in self.options.keywords.iter().rev().map(OsString::from) {
111+
let idx = components.iter().rposition(|component| {
112+
if let Component::Normal(sub_path) = component {
113+
sub_path == &keyword
114+
} else {
115+
false
116+
}
117+
});
118+
119+
if let Some(idx) = idx {
120+
components = components.drain(0..idx).collect();
121+
} else {
122+
return false;
123+
};
124+
}
125+
126+
true
127+
}
94128
}
95129

96130
pub struct StreamOptions {
@@ -109,6 +143,9 @@ pub struct StreamOptions {
109143
/// Whether to resolve symlinks when checking if a directory exists.
110144
resolve_symlinks: bool,
111145

146+
// Whether to only allow exact match of directory names.
147+
exact: bool,
148+
112149
/// Directories that do not exist and haven't been accessed since TTL will
113150
/// be lazily removed.
114151
ttl: Epoch,
@@ -122,6 +159,7 @@ impl StreamOptions {
122159
exclude: Vec::new(),
123160
exists: false,
124161
resolve_symlinks: false,
162+
exact: false,
125163
ttl: now.saturating_sub(3 * MONTH),
126164
}
127165
}
@@ -149,6 +187,11 @@ impl StreamOptions {
149187
self.resolve_symlinks = resolve_symlinks;
150188
self
151189
}
190+
191+
pub fn with_exact(mut self, exact: bool) -> Self {
192+
self.exact = exact;
193+
self
194+
}
152195
}
153196

154197
#[cfg(test)]

0 commit comments

Comments
 (0)