1pub fn compress(cmd: &str, output: &str) -> Option<String> {
4 let trimmed = output.trim();
5 if trimmed.is_empty() {
6 return Some("ok".to_string());
7 }
8
9 if cmd.contains("test") {
10 return Some(compress_test(trimmed));
11 }
12 if cmd.contains("build") {
13 return Some(compress_build(trimmed));
14 }
15
16 Some(compact_lines(trimmed, 15))
17}
18
19fn compress_test(output: &str) -> String {
20 let mut passed = 0u32;
21 let mut failed = 0u32;
22 let mut failures = Vec::new();
23
24 for line in output.lines() {
25 let trimmed = line.trim();
26 if trimmed.contains("1/1 test") || trimmed.contains("test passed") {
27 passed += 1;
28 }
29 if trimmed.contains("FAIL") || trimmed.contains("test failed") {
30 failed += 1;
31 failures.push(trimmed.to_string());
32 }
33 if trimmed.contains("All")
34 && trimmed.contains("passed")
35 && let Some(n) = trimmed
36 .split_whitespace()
37 .nth(1)
38 .and_then(|w| w.parse().ok())
39 {
40 passed = n;
41 }
42 }
43
44 if passed == 0 && failed == 0 {
45 return compact_lines(output, 10);
46 }
47
48 let mut result = format!("zig test: {passed} passed");
49 if failed > 0 {
50 result.push_str(&format!(", {failed} failed"));
51 }
52 for f in failures.iter().take(5) {
53 result.push_str(&format!("\n {f}"));
54 }
55 result
56}
57
58fn compress_build(output: &str) -> String {
59 let errors: Vec<&str> = output
60 .lines()
61 .filter(|l| l.contains("error:") || l.contains("Error"))
62 .collect();
63 let warnings: Vec<&str> = output.lines().filter(|l| l.contains("warning:")).collect();
64
65 if !errors.is_empty() {
66 let mut result = format!("{} errors", errors.len());
67 if !warnings.is_empty() {
68 result.push_str(&format!(", {} warnings", warnings.len()));
69 }
70 for e in errors.iter().take(10) {
71 result.push_str(&format!("\n {}", e.trim()));
72 }
73 return result;
74 }
75
76 if !warnings.is_empty() {
77 return format!("ok ({} warnings)", warnings.len());
78 }
79
80 "ok".to_string()
81}
82
83fn compact_lines(text: &str, max: usize) -> String {
84 let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
85 if lines.len() <= max {
86 return lines.join("\n");
87 }
88 format!(
89 "{}\n{}",
90 lines[..max].join("\n"),
91 super::elision_marker(lines.len() - max)
92 )
93}