From 3a6ab38c432142df4a61c719d7703981d7e6ff94 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Fri, 16 Apr 2021 08:03:56 +0530 Subject: [PATCH] Improvements to matching algorithm --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- README.md | 2 +- man/zoxide.1 | 2 +- src/db/query.rs | 57 ++++++++++++++++++++++++++++++------------------- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8187b2f..ca13c6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Manpages for each subcommand. + ### Fixed - `cd -` on fish shells. diff --git a/Cargo.toml b/Cargo.toml index d5eaff7..b0d6333 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "zoxide" version = "0.6.0" authors = ["Ajeet D'Souza <98ajeet@gmail.com>"] edition = "2018" -description = "A faster way to navigate your filesystem" +description = "A smarter cd command" repository = "https://github.com/ajeetdsouza/zoxide/" license = "MIT" keywords = ["cli"] diff --git a/README.md b/README.md index 9209d96..9b1a518 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![crates.io][crates.io-badge]][crates.io] -> A faster way to navigate your filesystem +> A smarter cd command `zoxide` is a blazing fast replacement for your `cd` command, inspired by [`z`][z] and [`z.lua`][z.lua]. It keeps track of the directories you use most diff --git a/man/zoxide.1 b/man/zoxide.1 index 84fa168..b047754 100644 --- a/man/zoxide.1 +++ b/man/zoxide.1 @@ -1,6 +1,6 @@ .TH "zoxide" "1" "2021-04-12" "zoxide" "zoxide" .SH NAME -zoxide - a faster way to navigate your filesystem +zoxide - a smarter cd command .SH SYNOPSIS .B zoxide \fISUBCOMMAND [OPTIONS]\fR .SH DESCRIPTION diff --git a/src/db/query.rs b/src/db/query.rs index f145085..bf5d12c 100644 --- a/src/db/query.rs +++ b/src/db/query.rs @@ -8,36 +8,25 @@ impl Query { I: IntoIterator, S: AsRef, { - Query( - keywords - .into_iter() - .map(|s: S| s.as_ref().to_lowercase()) - .collect(), - ) - } - - pub fn keywords(&self) -> &[String] { - &self.0 + Query(keywords.into_iter().map(|s: S| to_lowercase(s)).collect()) } pub fn matches>(&self, path: S) -> bool { - let path = path.as_ref().to_lowercase(); - let keywords = self.keywords(); - - let get_filenames = || { - let query_name = Path::new(keywords.last()?).file_name()?.to_str().unwrap(); - let dir_name = Path::new(&path).file_name()?.to_str().unwrap(); - Some((query_name, dir_name)) + let keywords = &self.0; + let keywords_last = match keywords.last() { + Some(keyword) => keyword, + None => return true, }; - if let Some((query_name, dir_name)) = get_filenames() { - if !dir_name.contains(query_name) { - return false; - } + let path = to_lowercase(path); + + let query_name = get_filename(keywords_last); + let dir_name = get_filename(&path); + if !dir_name.contains(query_name) { + return false; } let mut subpath = path.as_str(); - for keyword in keywords.iter() { match subpath.find(keyword) { Some(idx) => subpath = &subpath[idx + keyword.len()..], @@ -49,6 +38,30 @@ impl Query { } } +fn get_filename(path: &str) -> &str { + if cfg!(windows) { + Path::new(path) + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + } else { + match path.rfind('/') { + Some(idx) => &path[idx + 1..], + None => path, + } + } +} + +fn to_lowercase>(s: S) -> String { + let s = s.as_ref(); + if s.is_ascii() { + s.to_ascii_lowercase() + } else { + s.to_lowercase() + } +} + #[cfg(test)] mod tests { use super::Query;