lean_ctx/core/patterns/
swift.rs1pub fn compress(cmd: &str, output: &str) -> Option<String> {
2 let trimmed = output.trim();
3 if trimmed.is_empty() {
4 return Some("ok".to_string());
5 }
6
7 if cmd.contains("test") {
8 return Some(compress_test(trimmed));
9 }
10 if cmd.contains("build") {
11 return Some(compress_build(trimmed));
12 }
13 if cmd.contains("package resolve") || cmd.contains("package update") {
14 return Some(compress_resolve(trimmed));
15 }
16
17 Some(compact_lines(trimmed, 15))
18}
19
20fn compress_test(output: &str) -> String {
21 let mut passed = 0u32;
22 let mut failed = 0u32;
23 let mut failures = Vec::new();
24 let mut time = String::new();
25
26 for line in output.lines() {
27 let trimmed = line.trim();
28 if trimmed.contains("Test Case") && trimmed.contains("passed") {
29 passed += 1;
30 } else if trimmed.contains("Test Case") && trimmed.contains("failed") {
31 failed += 1;
32 failures.push(trimmed.to_string());
33 }
34 if trimmed.starts_with("Test Suite") && trimmed.contains("Executed") {
35 time = trimmed.to_string();
36 }
37 if trimmed.contains("Executed") && trimmed.contains("tests") {
38 if let Some(pos) = trimmed.find("Executed") {
39 time = trimmed[pos..].to_string();
40 }
41 }
42 }
43
44 if passed == 0 && failed == 0 {
45 return compact_lines(output, 10);
46 }
47
48 let mut result = format!("swift test: {passed} passed");
49 if failed > 0 {
50 result.push_str(&format!(", {failed} failed"));
51 }
52 if !time.is_empty() {
53 result.push_str(&format!("\n {time}"));
54 }
55 for f in failures.iter().take(5) {
56 result.push_str(&format!("\n FAIL: {f}"));
57 }
58 result
59}
60
61fn compress_build(output: &str) -> String {
62 let mut compiling = 0u32;
63 let mut linking = false;
64 let mut errors = Vec::new();
65 let mut warnings = 0u32;
66
67 for line in output.lines() {
68 let trimmed = line.trim();
69 if trimmed.starts_with("Compiling") || trimmed.contains("[") && trimmed.contains("]") {
70 compiling += 1;
71 }
72 if trimmed.starts_with("Linking") || trimmed.contains("Linking") {
73 linking = true;
74 }
75 if trimmed.contains("error:") {
76 errors.push(trimmed.to_string());
77 }
78 if trimmed.contains("warning:") {
79 warnings += 1;
80 }
81 }
82
83 if !errors.is_empty() {
84 let mut result = format!("{} errors", errors.len());
85 if warnings > 0 {
86 result.push_str(&format!(", {warnings} warnings"));
87 }
88 for e in errors.iter().take(10) {
89 result.push_str(&format!("\n {e}"));
90 }
91 return result;
92 }
93
94 let mut result = format!("Build ok ({compiling} compiled");
95 if linking {
96 result.push_str(", linked");
97 }
98 if warnings > 0 {
99 result.push_str(&format!(", {warnings} warnings"));
100 }
101 result.push(')');
102 result
103}
104
105fn compress_resolve(output: &str) -> String {
106 let mut fetched = 0u32;
107 let mut resolved = 0u32;
108 for line in output.lines() {
109 if line.contains("Fetching") {
110 fetched += 1;
111 }
112 if line.contains("Resolving") || line.contains("resolved") {
113 resolved += 1;
114 }
115 }
116 if fetched == 0 && resolved == 0 {
117 return compact_lines(output, 5);
118 }
119 format!("{fetched} fetched, {resolved} resolved")
120}
121
122fn compact_lines(text: &str, max: usize) -> String {
123 let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
124 if lines.len() <= max {
125 return lines.join("\n");
126 }
127 format!(
128 "{}\n... ({} more lines)",
129 lines[..max].join("\n"),
130 lines.len() - max
131 )
132}