From 58553d704fd969ccd4798908da8a439378b0b9d1 Mon Sep 17 00:00:00 2001 From: Dylan Bowker Date: Sat, 19 Oct 2024 17:56:59 -0600 Subject: [PATCH] feat: `strsim` fuzzy matching feature is now enabled on by default --- CHANGELOG.md | 4 +-- Cargo.toml | 13 +++++---- src/simple/autocomplete/context.rs | 29 ++++++++++++------- src/simple/autocomplete/global.rs | 25 ++++++++++------ src/simple/autocomplete/keyword.rs | 21 +++++++++----- .../internal/eddie/eddie_global_keyword.rs | 7 +++-- 6 files changed, 62 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 822b051..34624a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,7 @@ # 0.6.3 -* 2024-10-19: Removed unnecessary `collect` on some iterators. Thank you for - pointing this out, `clippy`. This should provide a small performance - improvement. +* 2024-10-19: `strsim` fuzzy matching feature is now enabled on by default. # 0.6.2 diff --git a/Cargo.toml b/Cargo.toml index fe50328..d03e245 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,17 @@ repository = "https://github.com/leontoeides/indicium" rust-version = "1.73.0" [features] -default = [ "simple", "dep:strsim", "dep:ahash" ] -simple = [] +default = [ "simple" ] + +simple = [ "strsim", "ahash" ] select2 = [ "simple", "dep:serde" ] -fuzzy = [ "dep:strsim" ] # Deprecated feature. Redirects to `strsim` feature. -ahash = [ "dep:ahash" ] + +fuzzy = [ "dep:strsim" ] +strsim = [ "dep:strsim" ] eddie = [ "dep:eddie" ] + +ahash = [ "dep:ahash" ] gxhash = [ "dep:gxhash" ] -strsim = [ "dep:strsim" ] [dependencies] ahash = { version = "0.8", optional = true } diff --git a/src/simple/autocomplete/context.rs b/src/simple/autocomplete/context.rs index 55d8f91..5dbc6f3 100644 --- a/src/simple/autocomplete/context.rs +++ b/src/simple/autocomplete/context.rs @@ -115,7 +115,7 @@ impl SearchIndex { // Intersect the autocompletions for the last keyword with the // search results for the preceding keywords. This way, only // relevant autocompletions are returned: - let mut autocompletions = self + let mut autocompletions: Vec<&KString> = self .b_tree_map // Get matching keywords starting with (partial) keyword string: .range(KString::from_ref(&last_keyword)..) @@ -143,12 +143,14 @@ impl SearchIndex { .take(*maximum_autocomplete_options) // `range` returns a key-value pair. We're autocompleting the // key (keyword), so discard the value (record key): - .map(|(key, _value)| key); + .map(|(key, _value)| key) + // Collect all keyword autocompletions into a `Vec`: + .collect(); // If `eddie` fuzzy matching enabled, examine the resulting // auto-complete options before using them: #[cfg(feature = "eddie")] - if autocompletions.peek().is_none() { + if autocompletions.is_empty() { // No autocomplete options were found for the user's last // (partial) keyword. Attempt to use fuzzy string search to find // other autocomplete options: @@ -164,13 +166,15 @@ impl SearchIndex { // `eddie_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so // discard the keys: - .map(|(keyword, _keys)| keyword); + .map(|(keyword, _keys)| keyword) + // Collect all keyword autocompletions into a `Vec`: + .collect(); } // if // If `strsim` fuzzy matching enabled, examine the resulting // auto-complete options before using them: #[cfg(all(feature = "strsim", not(feature = "eddie")))] - if autocompletions.peek().is_none() { + if autocompletions.is_empty() { // No autocomplete options were found for the user's last // (partial) keyword. Attempt to use fuzzy string search to find // other autocomplete options: @@ -186,28 +190,31 @@ impl SearchIndex { // `strsim_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so // discard the keys: - .map(|(keyword, _keys)| keyword); + .map(|(keyword, _keys)| keyword) + // Collect all keyword autocompletions into a `Vec`: + .collect(); } // if // Push a blank placeholder onto the end of the keyword list. We // will be putting our autocompletions for the last keyword into // this spot: - let mut autocompleted_string = keywords.clone(); - autocompleted_string.push("".into()); + keywords.push("".into()); // Build autocompleted search strings from the autocompletions // derived from the last keyword: autocompletions + // Iterate over each autocompleted last keyword: + .into_iter() // Use the prepended `keywords` and autocompleted last keyword // to build an autocompleted search string: .map(|last_keyword| { // Remove previous autocompleted last keyword from list: - autocompleted_string.pop(); + keywords.pop(); // Add current autocompleted last keyword to end of list: - autocompleted_string.push(last_keyword.clone()); + keywords.push(last_keyword.clone()); // Join all keywords together into a single `String` using a // space delimiter: - autocompleted_string.join(" ").trim_end().to_string() + keywords.join(" ").trim_end().to_string() }) // Collect all string autocompletions into a `Vec`: .collect() diff --git a/src/simple/autocomplete/global.rs b/src/simple/autocomplete/global.rs index 8f35a55..4995cd5 100644 --- a/src/simple/autocomplete/global.rs +++ b/src/simple/autocomplete/global.rs @@ -113,7 +113,7 @@ impl SearchIndex { // autocompleting: keywords.pop().map_or_else(Vec::new, |last_keyword| { // Autocomplete the last keyword: - let mut autocompletions = self + let mut autocompletions: Vec<&KString> = self .b_tree_map // Get matching keywords starting with (partial) keyword string: .range(KString::from_ref(&last_keyword)..) @@ -141,7 +141,9 @@ impl SearchIndex { // .filter(|autocompletion| *autocompletion != &keyword) // Only return `maximum_autocomplete_options` number of // keywords: - .take(*maximum_autocomplete_options); + .take(*maximum_autocomplete_options) + // Collect all keyword autocompletions into a `Vec`: + .collect(); // If `eddie` fuzzy matching enabled, examine the resulting // auto-complete options before using them: @@ -162,7 +164,9 @@ impl SearchIndex { // `eddie_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so // discard the keys: - .map(|(keyword, _keys)| keyword); + .map(|(keyword, _keys)| keyword) + // Collect all keyword autocompletions into a `Vec`: + .collect(); } // if // If `strsim` fuzzy matching enabled, examine the resulting @@ -184,28 +188,31 @@ impl SearchIndex { // `strsim_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so // discard the keys: - .map(|(keyword, _keys)| keyword); + .map(|(keyword, _keys)| keyword) + // Collect all keyword autocompletions into a `Vec`: + .collect(); } // if // Push a blank placeholder onto the end of the keyword list. We // will be putting our autocompletions for the last keyword into // this spot: - let mut autocompleted_string = keywords.clone(); - autocompleted_string.push("".into()); + keywords.push("".into()); // Build autocompleted search strings from the autocompletions // derived from the last keyword: autocompletions + // Iterate over each autocompleted last keyword: + .into_iter() // Use the prepended `keywords` and autocompleted last keyword // to build an autocompleted search string: .map(|autocompletion| { // Remove previous autocompleted last keyword from list: - autocompleted_string.pop(); + keywords.pop(); // Add current autocompleted last keyword to end of list: - autocompleted_string.push(autocompletion.clone()); + keywords.push(autocompletion.clone()); // Join all keywords together into a single `String` using a // space delimiter: - autocompleted_string.join(" ").trim_end().to_string() + keywords.join(" ").trim_end().to_string() }) // Collect all string autocompletions into a `Vec`: .collect() diff --git a/src/simple/autocomplete/keyword.rs b/src/simple/autocomplete/keyword.rs index 2977282..0e36b84 100644 --- a/src/simple/autocomplete/keyword.rs +++ b/src/simple/autocomplete/keyword.rs @@ -103,7 +103,7 @@ impl SearchIndex { tracing::debug!("autocompleting: {:?}", keyword); // Attempt to get matching keywords from `BTreeMap`: - let autocomplete_options = self + let autocomplete_options: Vec<&KString> = self .b_tree_map // Get matching keywords starting with (partial) keyword string: .range(KString::from_ref(&keyword)..) @@ -121,12 +121,14 @@ impl SearchIndex { // in New York), do not return "new" as an auto-completed keyword: // .filter(|autocompletion| *autocompletion != &keyword) // Only return `maximum_autocomplete_options` number of keywords: - .take(*maximum_autocomplete_options); + .take(*maximum_autocomplete_options) + // Collect all keyword autocompletions into a `Vec`: + .collect(); // If `eddie` fuzzy matching enabled, examine the resulting // auto-complete options before returning them: #[cfg(feature = "eddie")] - if autocomplete_options.peek().is_none() { + if autocomplete_options.is_empty() { // No autocomplete options were found for the user's last // (partial) keyword. Attempt to use fuzzy string search to find // other autocomplete options: @@ -138,7 +140,9 @@ impl SearchIndex { // `eddie_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so discard // the keys: - .map(|(keyword, _keys)| keyword.as_str()); + .map(|(keyword, _keys)| keyword.as_str()) + // Collect all keyword autocompletions into a `Vec`: + .collect() } else { // There were some matches. Return the results without processing: autocomplete_options @@ -150,7 +154,7 @@ impl SearchIndex { // If `strsim` fuzzy matching enabled, examine the resulting // auto-complete options before returning them: #[cfg(all(feature = "strsim", not(feature = "eddie")))] - if autocomplete_options.peek().is_none() { + if autocomplete_options.is_empty() { // No autocomplete options were found for the user's last // (partial) keyword. Attempt to use fuzzy string search to find // other autocomplete options: @@ -162,12 +166,15 @@ impl SearchIndex { // `strsim_autocomplete` returns both the keyword and keys. // We're autocompleting the last (partial) keyword, so discard // the keys: - .map(|(keyword, _keys)| keyword.as_str()); + .map(|(keyword, _keys)| keyword.as_str()) + // Collect all keyword autocompletions into a `Vec`: + .collect() } else { // There were some matches. Return the results without processing: autocomplete_options .into_iter() .map(kstring::KStringBase::as_str) + .collect() } // if // If fuzzy string searching disabled, return the resulting @@ -175,7 +182,7 @@ impl SearchIndex { #[cfg(not(any(feature = "strsim", feature = "eddie")))] autocomplete_options .into_iter() - .map(KString::as_str) + .map(|kstring| kstring.as_str()) .collect() } // fn } // impl diff --git a/src/simple/internal/eddie/eddie_global_keyword.rs b/src/simple/internal/eddie/eddie_global_keyword.rs index f0e24c4..1495e91 100644 --- a/src/simple/internal/eddie/eddie_global_keyword.rs +++ b/src/simple/internal/eddie/eddie_global_keyword.rs @@ -16,7 +16,10 @@ impl SearchIndex { /// matches, these `eddie_keyword_*` methods can be used to find the best /// match for substitution. - pub(crate) fn eddie_global_keyword(&self, user_keyword: &str) -> Option<&KString> { + pub(crate) fn eddie_global_keyword( + &self, + user_keyword: &str + ) -> Option<&KString> { // Build an index keyword range to fuzzy match against. // // | Example | User Keyword | Length | Index Keyword Must Start With... | @@ -52,7 +55,7 @@ impl SearchIndex { // fuzzy match against: match byte_index { Some(byte_index) => &user_keyword[0..byte_index], - None => return vec![], + None => return None, } // match } else { // The user's keyword is too short. Do not perform any fuzzy