Skip to content

Commit 9f56edd

Browse files
authored
feat: added support for fancy regex (#292)
1 parent ba6f6c5 commit 9f56edd

File tree

6 files changed

+60
-18
lines changed

6 files changed

+60
-18
lines changed

Cargo.lock

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

aw-query/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ serde_json = "1.0"
1212
chrono = { version = "0.4", features = ["serde"] }
1313
plex = "0.2"
1414
log = "0.4"
15-
regex = "1.5"
15+
fancy-regex = "0.10.0"
1616
aw-datastore = { path = "../aw-datastore" }
1717
aw-models = { path = "../aw-models" }
1818
aw-transform = { path = "../aw-transform" }

aw-query/src/functions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ mod qfunctions {
444444
Ok(DataType::List(filtered_tagged_events))
445445
}
446446

447-
use regex::RegexBuilder;
447+
use fancy_regex::RegexBuilder;
448448

449449
pub fn filter_keyvals_regex(
450450
args: Vec<DataType>,

aw-transform/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2021"
1010
serde = "1.0"
1111
rocket = "0.5.0-rc.1" # TODO: Remove this dependency
1212
serde_json = "1.0"
13-
regex = "1.5"
13+
fancy-regex = "0.10.0"
1414
log = "0.4"
1515
chrono = { version = "0.4", features = ["serde"] }
1616
aw-models = { path = "../aw-models" }

aw-transform/src/classify.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
///
33
/// Based on code in aw_research: https://github.com/ActivityWatch/aw-research/blob/master/aw_research/classify.py
44
use aw_models::Event;
5-
use regex::{Regex, RegexBuilder};
5+
use fancy_regex::Regex;
66

77
pub enum Rule {
88
None,
@@ -27,10 +27,16 @@ pub struct RegexRule {
2727
}
2828

2929
impl RegexRule {
30-
pub fn new(regex_str: &str, ignore_case: bool) -> Result<RegexRule, regex::Error> {
31-
let mut regex_builder = RegexBuilder::new(regex_str);
32-
regex_builder.case_insensitive(ignore_case);
33-
let regex = regex_builder.build()?;
30+
pub fn new(regex_str: &str, ignore_case: bool) -> Result<RegexRule, fancy_regex::Error> {
31+
// can't use `RegexBuilder::case_insensitive` because it's not supported by fancy_regex,
32+
// so we need to prefix with `(?i)` to make it case insensitive.
33+
let regex = if ignore_case {
34+
let regex_str = format!("(?i){}", regex_str);
35+
Regex::new(&regex_str)?
36+
} else {
37+
Regex::new(regex_str)?
38+
};
39+
3440
Ok(RegexRule { regex })
3541
}
3642
}
@@ -46,7 +52,7 @@ impl RuleTrait for RegexRule {
4652
.data
4753
.values()
4854
.filter(|val| val.is_string())
49-
.any(|val| self.regex.is_match(val.as_str().unwrap()))
55+
.any(|val| self.regex.is_match(val.as_str().unwrap()).unwrap())
5056
}
5157
}
5258

@@ -139,6 +145,18 @@ fn test_rule() {
139145
assert_eq!(rule_none.matches(&e_match), false);
140146
}
141147

148+
#[test]
149+
fn test_rule_lookahead() {
150+
// Originally requested by a user here, to match aw-server-python: https://canary.discord.com/channels/755040852727955476/755334543891759194/994291987878522961
151+
let mut e_match = Event::default();
152+
e_match
153+
.data
154+
.insert("test".into(), serde_json::json!("testing lookahead"));
155+
156+
let rule_from_regex = Rule::from(Regex::new("testing (?!lookahead)").unwrap());
157+
assert_eq!(rule_from_regex.matches(&e_match), false);
158+
}
159+
142160
#[test]
143161
fn test_categorize() {
144162
let mut e = Event::default();

aw-transform/src/filter_keyvals.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use regex::Regex;
1+
use fancy_regex::Regex;
22
use serde_json::value::Value;
33

44
use aw_models::Event;
@@ -42,7 +42,7 @@ pub fn filter_keyvals_regex(mut events: Vec<Event>, key: &str, regex: &Regex) ->
4242

4343
for event in events.drain(..) {
4444
if let Some(v) = event.data.get(key) {
45-
if regex.is_match(v.as_str().unwrap()) {
45+
if regex.is_match(v.as_str().unwrap()).unwrap() {
4646
filtered_events.push(event);
4747
}
4848
}
@@ -78,9 +78,8 @@ pub fn exclude_keyvals(mut events: Vec<Event>, key: &str, vals: &[Value]) -> Vec
7878
mod tests {
7979
use std::str::FromStr;
8080

81-
use chrono::DateTime;
82-
use chrono::Duration;
83-
use regex::RegexBuilder;
81+
use chrono::{DateTime, Duration};
82+
use fancy_regex::RegexBuilder;
8483
use serde_json::json;
8584

8685
use aw_models::Event;

0 commit comments

Comments
 (0)