Skip to content

Commit f0e3da2

Browse files
committed
feat: improve filter test reporting, add CLI usage hints, and fix TOML regex escaping for numeric placeholders
1 parent 66dd1c0 commit f0e3da2

4 files changed

Lines changed: 84 additions & 15 deletions

File tree

scratch/debug_escape.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
use regex;
2+
fn main() {
3+
println!("Escaped: {}", regex::escape("Step #/#:"));
4+
}

src/cli/learn.rs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,26 +90,66 @@ pub fn run_learn(args: &[String]) -> Result<()> {
9090
.bold()
9191
.bright_white()
9292
);
93-
let report = crate::pipeline::toml_filter::run_inline_tests(
94-
crate::pipeline::toml_filter::load_all_filters(),
95-
);
96-
let total = report.passes + report.failures.len();
93+
let all_filters = crate::pipeline::toml_filter::load_all_filters();
94+
let report = crate::pipeline::toml_filter::run_inline_tests(all_filters);
9795

98-
let status = if report.failures.is_empty() {
99-
"ALL PASSED".green()
100-
} else {
101-
"FAILURES DETECTED".red()
102-
};
96+
let (mut built_in_fails, mut user_fails) = (0, 0);
97+
let (mut built_in_total, mut user_total) = (0, 0);
10398

104-
println!(" Status: {} ({} / {})", status, report.passes, total);
99+
for filter in all_filters {
100+
let count = filter.inline_tests.len();
101+
if filter.name.starts_with("sys_") {
102+
built_in_total += count;
103+
} else {
104+
user_total += count;
105+
}
106+
}
107+
108+
for fail in &report.failures {
109+
if fail.contains("Filter 'sys_") {
110+
built_in_fails += 1;
111+
} else {
112+
user_fails += 1;
113+
}
114+
}
115+
116+
let total_tests = built_in_total + user_total;
117+
let total_passes = report.passes;
118+
119+
println!(
120+
" Total Tests: {} ({} passed, {} failed)",
121+
total_tests,
122+
total_passes,
123+
report.failures.len()
124+
);
125+
println!(
126+
" - Built-in: {} tests ({} failed)",
127+
built_in_total, built_in_fails
128+
);
129+
println!(
130+
" - User: {} tests ({} failed)",
131+
user_total, user_fails
132+
);
105133

106134
if !report.failures.is_empty() {
107-
println!("\n{}", "Details:".bold().red());
135+
println!("\n{}", "Failure Details:".bold().red());
108136
for f in report.failures {
109137
println!(" {} {}", "✗".red(), f);
110138
}
139+
if user_fails > 0 {
140+
println!(
141+
"\n{}",
142+
"TIP: Learned filters often fail if the noise pattern has changed. You can clear them by deleting ~/.omni/filters/learned.toml"
143+
.dimmed()
144+
);
145+
}
146+
} else {
147+
println!(
148+
"\n{}",
149+
"✓ All loaded filters pass their inline tests!".green()
150+
);
111151
}
112-
println!();
152+
113153
return Ok(());
114154
}
115155

src/cli/stats.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ fn run_detail(args: &[String], store: &Store) -> Result<()> {
484484
println!(
485485
"\n {}",
486486
format!(
487-
"Showing top 10 of {} commands with active savings.",
487+
"Showing top 10 of {} commands with active savings. --all-commands to see all",
488488
filtered_count
489489
)
490490
.bright_black()

src/session/learn.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,14 @@ pub fn generate_toml(
133133

134134
// Escape characters for RegEx safeties
135135
let escaped_prefix = regex::escape(&clean_prefix);
136-
let toml_safe = escaped_prefix.replace('\\', "\\\\").replace('"', "\\\"");
137-
strips.push(format!("\"^{}\"", toml_safe));
136+
// Replace the '#' placeholder with the memory-safe regex placeholder (single backslash \d+)
137+
let mem_regex = format!("^{}", escaped_prefix.replace('#', r"\d+"));
138+
139+
// Use toml crate to handle ALL string escaping correctly for TOML
140+
let toml_val = toml::Value::String(mem_regex);
141+
let toml_safe = toml_val.to_string();
142+
143+
strips.push(toml_safe);
138144
sample_lines.push_str(&format!("{}\n", clean_sample));
139145
}
140146

@@ -325,4 +331,23 @@ mod tests {
325331
// Will fire the thread in the background
326332
queue_for_learn("x".repeat(300).as_str(), "make build");
327333
}
334+
335+
#[test]
336+
fn test_generate_toml_with_numeric_placeholders() {
337+
let c = vec![PatternCandidate {
338+
trigger_prefix: "Step #/#:".to_string(),
339+
sample_line: "Step 1/2: FROM alpine".to_string(),
340+
count: 3,
341+
confidence: 0.85,
342+
suggested_action: LearnAction::Strip,
343+
}];
344+
let toml = generate_toml(&c, "numeric_test", None);
345+
// The generated regex in TOML will have escaped backslashes
346+
// Step #/#: -> Step \d+/\d+: -> Step \\d+/\\d+:
347+
assert!(
348+
toml.contains(r"Step \\d+/\\d+:"),
349+
"TOML did not contain expected regex. Got: {}",
350+
toml
351+
);
352+
}
328353
}

0 commit comments

Comments
 (0)