Skip to main content

lean_ctx/core/patterns/
helm.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("list") || cmd.contains("ls") {
8        return Some(compress_list(trimmed));
9    }
10    if cmd.contains("install") || cmd.contains("upgrade") {
11        return Some(compress_install(trimmed));
12    }
13    if cmd.contains("status") {
14        return Some(compress_status(trimmed));
15    }
16    if cmd.contains("template") || cmd.contains("dry-run") {
17        return Some(compress_template(trimmed));
18    }
19    if cmd.contains("repo") {
20        return Some(compress_repo(trimmed));
21    }
22
23    Some(compact_lines(trimmed, 15))
24}
25
26fn compress_list(output: &str) -> String {
27    let lines: Vec<&str> = output.lines().collect();
28    if lines.len() <= 1 {
29        return "no releases".to_string();
30    }
31
32    let header = lines[0];
33    let releases: Vec<&str> = lines[1..]
34        .iter()
35        .copied()
36        .filter(|l| !l.trim().is_empty())
37        .collect();
38    if releases.len() <= 15 {
39        return output.to_string();
40    }
41    format!(
42        "{header}\n{}\n... ({} more)",
43        releases[..10].join("\n"),
44        releases.len() - 10
45    )
46}
47
48fn compress_install(output: &str) -> String {
49    let mut name = String::new();
50    let mut status = String::new();
51    let mut notes_start = false;
52    let mut notes = Vec::new();
53
54    for line in output.lines() {
55        let trimmed = line.trim();
56        if trimmed.starts_with("NAME:") {
57            name = trimmed
58                .strip_prefix("NAME:")
59                .unwrap_or("")
60                .trim()
61                .to_string();
62        } else if trimmed.starts_with("STATUS:") {
63            status = trimmed
64                .strip_prefix("STATUS:")
65                .unwrap_or("")
66                .trim()
67                .to_string();
68        } else if trimmed == "NOTES:" {
69            notes_start = true;
70        } else if notes_start && !trimmed.is_empty() && notes.len() < 5 {
71            notes.push(trimmed.to_string());
72        }
73    }
74
75    let mut result = format!("{name}: {status}");
76    if !notes.is_empty() {
77        result.push_str(&format!("\nnotes: {}", notes.join(" | ")));
78    }
79    result
80}
81
82fn compress_status(output: &str) -> String {
83    let mut parts = Vec::new();
84    for line in output.lines() {
85        let trimmed = line.trim();
86        if trimmed.starts_with("NAME:")
87            || trimmed.starts_with("STATUS:")
88            || trimmed.starts_with("NAMESPACE:")
89            || trimmed.starts_with("REVISION:")
90            || trimmed.starts_with("LAST DEPLOYED:")
91        {
92            parts.push(trimmed.to_string());
93        }
94    }
95    if parts.is_empty() {
96        return compact_lines(output, 10);
97    }
98    parts.join("\n")
99}
100
101fn compress_template(output: &str) -> String {
102    let lines: Vec<&str> = output.lines().collect();
103    let yaml_docs: Vec<usize> = lines
104        .iter()
105        .enumerate()
106        .filter(|(_, l)| l.trim() == "---")
107        .map(|(i, _)| i)
108        .collect();
109
110    let mut kinds = Vec::new();
111    for line in &lines {
112        let trimmed = line.trim();
113        if trimmed.starts_with("kind:") {
114            kinds.push(
115                trimmed
116                    .strip_prefix("kind:")
117                    .unwrap_or("")
118                    .trim()
119                    .to_string(),
120            );
121        }
122    }
123
124    if kinds.is_empty() {
125        return format!("{} lines of YAML", lines.len());
126    }
127
128    let mut counts: std::collections::HashMap<&str, u32> = std::collections::HashMap::new();
129    for k in &kinds {
130        *counts.entry(k.as_str()).or_insert(0) += 1;
131    }
132    let summary: Vec<String> = counts.iter().map(|(k, v)| format!("  {k}: {v}")).collect();
133    format!(
134        "{} YAML docs ({} resources):\n{}",
135        yaml_docs.len().max(1),
136        kinds.len(),
137        summary.join("\n")
138    )
139}
140
141fn compress_repo(output: &str) -> String {
142    compact_lines(output, 10)
143}
144
145fn compact_lines(text: &str, max: usize) -> String {
146    let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
147    if lines.len() <= max {
148        return lines.join("\n");
149    }
150    format!(
151        "{}\n... ({} more lines)",
152        lines[..max].join("\n"),
153        lines.len() - max
154    )
155}