Update SearchQueryCondition to support logical or and contains types; also update non-regex types to escape regex

pull/137/head
Chip Senkbeil 2 years ago
parent 193bb6d237
commit a8107aed3a
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- New `contains` and `or` types for `SearchQueryCondition`
### Changed
- `SearchQueryCondition` now escapes regex for all types except `regex`
- Removed `min_depth` option from search
- Updated search to properly use binary detection, filter out common ignore
file patterns, and execute in parallel via the `ignore` crate and `num_cpus`

1
Cargo.lock generated

@ -772,6 +772,7 @@ dependencies = [
"portable-pty",
"predicates",
"rand 0.8.5",
"regex",
"rstest",
"schemars",
"serde",

@ -30,6 +30,7 @@ num_cpus = "1.13.1"
once_cell = "1.13.0"
portable-pty = "0.7.0"
rand = { version = "0.8.5", features = ["getrandom"] }
regex = "1.1"
serde = { version = "1.0.142", features = ["derive"] }
serde_bytes = "0.11.7"
serde_json = "1.0.83"

@ -70,20 +70,33 @@ impl SearchQueryTarget {
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case", deny_unknown_fields, tag = "type")]
pub enum SearchQueryCondition {
/// Begins with some text
/// Text is found anywhere (all regex patterns are escaped)
Contains { value: String },
/// Begins with some text (all regex patterns are escaped)
EndsWith { value: String },
/// Matches some text exactly
/// Matches some text exactly (all regex patterns are escaped)
Equals { value: String },
/// Any of the conditions match
Or { value: Vec<SearchQueryCondition> },
/// Matches some regex
Regex { value: String },
/// Begins with some text
/// Begins with some text (all regex patterns are escaped)
StartsWith { value: String },
}
impl SearchQueryCondition {
/// Creates a new instance with `Contains` variant
pub fn contains(value: impl Into<String>) -> Self {
Self::Contains {
value: value.into(),
}
}
/// Creates a new instance with `EndsWith` variant
pub fn ends_with(value: impl Into<String>) -> Self {
Self::EndsWith {
@ -98,6 +111,17 @@ impl SearchQueryCondition {
}
}
/// Creates a new instance with `Or` variant
pub fn or<I, C>(value: I) -> Self
where
I: IntoIterator<Item = C>,
C: Into<SearchQueryCondition>,
{
Self::Or {
value: value.into_iter().map(|s| s.into()).collect(),
}
}
/// Creates a new instance with `Regex` variant
pub fn regex(value: impl Into<String>) -> Self {
Self::Regex {
@ -115,10 +139,21 @@ impl SearchQueryCondition {
/// Converts the condition in a regex string
pub fn to_regex_string(&self) -> String {
match self {
Self::EndsWith { value } => format!(r"{value}$"),
Self::Equals { value } => format!(r"^{value}$"),
Self::Contains { value } => regex::escape(value),
Self::EndsWith { value } => format!(r"{}$", regex::escape(value)),
Self::Equals { value } => format!(r"^{}$", regex::escape(value)),
Self::Regex { value } => value.to_string(),
Self::StartsWith { value } => format!(r"^{value}"),
Self::StartsWith { value } => format!(r"^{}", regex::escape(value)),
Self::Or { value } => {
let mut s = String::new();
for (i, condition) in value.iter().enumerate() {
if i > 0 {
s.push('|');
}
s.push_str(&condition.to_regex_string());
}
s
}
}
}
}
@ -349,3 +384,45 @@ impl SearchQueryMatchData {
schemars::schema_for!(SearchQueryMatchData)
}
}
#[cfg(test)]
mod tests {
use super::*;
mod search_query_condition {
use super::*;
#[test]
fn to_regex_string_should_convert_to_appropriate_regex_and_escape_as_needed() {
assert_eq!(
SearchQueryCondition::contains("t^es$t").to_regex_string(),
r"t\^es\$t"
);
assert_eq!(
SearchQueryCondition::ends_with("t^es$t").to_regex_string(),
r"t\^es\$t$"
);
assert_eq!(
SearchQueryCondition::equals("t^es$t").to_regex_string(),
r"^t\^es\$t$"
);
assert_eq!(
SearchQueryCondition::or([
SearchQueryCondition::contains("t^es$t"),
SearchQueryCondition::equals("t^es$t"),
SearchQueryCondition::regex("^test$"),
])
.to_regex_string(),
r"t\^es\$t|^t\^es\$t$|^test$"
);
assert_eq!(
SearchQueryCondition::regex("test").to_regex_string(),
"test"
);
assert_eq!(
SearchQueryCondition::starts_with("t^es$t").to_regex_string(),
r"^t\^es\$t"
);
}
}
}

Loading…
Cancel
Save