lean_ctx_patterns/
mise.rs1use crate::ansi::strip_ansi;
10
11pub fn compress(cmd: &str, output: &str) -> Option<String> {
12 let trimmed = output.trim();
13 if trimmed.is_empty() {
14 return Some("mise: ok".to_string());
15 }
16 if cmd.contains(" ls") || cmd.contains(" list") {
17 return Some(compress_ls(trimmed));
18 }
19 if cmd.contains("install") || cmd.contains("use") || cmd.contains("upgrade") {
20 return Some(compress_install(trimmed));
21 }
22 Some(fallback(trimmed))
23}
24
25fn compress_ls(output: &str) -> String {
26 let mut rows: Vec<String> = Vec::new();
27 for raw in output.lines() {
28 let line = strip_ansi(raw);
29 let cols: Vec<&str> = line.split_whitespace().collect();
30 if cols.len() >= 2 {
31 rows.push(format!("{} {}", cols[0], cols[1]));
32 }
33 }
34 if rows.is_empty() {
35 return fallback(output);
36 }
37 format!("mise: {} tool(s)\n{}", rows.len(), rows.join("\n"))
38}
39
40fn compress_install(output: &str) -> String {
41 let mut kept: Vec<String> = Vec::new();
42 for raw in output.lines() {
43 let line = strip_ansi(raw);
44 let t = line.trim();
45 if t.is_empty() {
46 continue;
47 }
48 let l = t.to_ascii_lowercase();
49 if l.contains("installed")
50 || l.contains("installing")
51 || l.contains("failed")
52 || l.contains("error")
53 || t.contains('✓')
54 {
55 kept.push(t.to_string());
56 }
57 }
58 if kept.is_empty() {
59 return "mise: ok".to_string();
60 }
61 kept.join("\n")
62}
63
64fn fallback(text: &str) -> String {
65 let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
66 let n = lines.len().min(10);
67 let mut s = lines[..n].join("\n");
68 if lines.len() > n {
69 s.push_str(&format!("\n... (+{} lines)", lines.len() - n));
70 }
71 s
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn ls_drops_source_path() {
80 let out = "node 20.10.0 ~/.config/mise/config.toml\npython 3.12.0 ~/.tool-versions\nrust 1.75.0 ~/.config/mise/config.toml";
81 let r = compress("mise ls", out).unwrap();
82 assert!(r.contains("3 tool(s)"), "{r}");
83 assert!(r.contains("node 20.10.0"), "{r}");
84 assert!(!r.contains("config.toml"), "drops source path: {r}");
85 }
86
87 #[test]
88 fn install_keeps_status() {
89 let out = "mise downloading node@20.10.0\nmise extracting node@20.10.0\nmise node@20.10.0 ✓ installed";
90 let r = compress("mise install node", out).unwrap();
91 assert!(r.contains("installed"), "{r}");
92 assert!(!r.contains("extracting"), "drops progress: {r}");
93 }
94
95 #[test]
96 fn empty_is_ok() {
97 assert_eq!(compress("mise ls", "").unwrap(), "mise: ok");
98 }
99}