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