Skip to main content

lean_ctx_patterns/
composer.rs

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