Skip to main content

lean_ctx/core/patterns/
composer.rs

1pub 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("install") || cmd.contains("update") || cmd.contains("require") {
8        return Some(compress_install(trimmed));
9    }
10    if cmd.contains("outdated") {
11        return Some(compress_outdated(trimmed));
12    }
13    if cmd.contains("show") || cmd.contains("info") {
14        return Some(compact_lines(trimmed, 15));
15    }
16
17    Some(compact_lines(trimmed, 15))
18}
19
20fn compress_install(output: &str) -> String {
21    let mut installed = 0u32;
22    let mut updated = 0u32;
23    let mut removed = 0u32;
24    let mut loading = false;
25
26    for line in output.lines() {
27        let trimmed = line.trim();
28        if trimmed.starts_with("- Installing") || trimmed.starts_with("- Downloading") {
29            installed += 1;
30        }
31        if trimmed.starts_with("- Updating") || trimmed.starts_with("- Upgrading") {
32            updated += 1;
33        }
34        if trimmed.starts_with("- Removing") {
35            removed += 1;
36        }
37        if trimmed.starts_with("Loading composer") {
38            loading = true;
39        }
40    }
41
42    if !loading && installed == 0 && updated == 0 {
43        return compact_lines(output, 10);
44    }
45
46    let mut parts = Vec::new();
47    if installed > 0 {
48        parts.push(format!("{installed} installed"));
49    }
50    if updated > 0 {
51        parts.push(format!("{updated} updated"));
52    }
53    if removed > 0 {
54        parts.push(format!("{removed} removed"));
55    }
56
57    let summary = output
58        .lines()
59        .rev()
60        .find(|l| l.contains("Package operations") || l.contains("Nothing to install"));
61    let mut result = format!("composer: {}", parts.join(", "));
62    if let Some(s) = summary {
63        result.push_str(&format!("\n  {}", s.trim()));
64    }
65    result
66}
67
68fn compress_outdated(output: &str) -> String {
69    let lines: Vec<&str> = output
70        .lines()
71        .filter(|l| {
72            let t = l.trim();
73            !t.is_empty() && !t.starts_with("Color legend")
74        })
75        .collect();
76
77    if lines.is_empty() {
78        return "all up to date".to_string();
79    }
80    if lines.len() <= 20 {
81        return lines.join("\n");
82    }
83    format!(
84        "{} outdated packages:\n{}\n... ({} more)",
85        lines.len(),
86        lines[..15].join("\n"),
87        lines.len() - 15
88    )
89}
90
91fn compact_lines(text: &str, max: usize) -> String {
92    let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
93    if lines.len() <= max {
94        return lines.join("\n");
95    }
96    format!(
97        "{}\n... ({} more lines)",
98        lines[..max].join("\n"),
99        lines.len() - max
100    )
101}