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