lean_ctx/core/patterns/
mysql.rs1pub 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 is_table_output(trimmed) {
8 return Some(compress_table(trimmed));
9 }
10
11 if cmd.contains("show databases") || cmd.contains("show tables") {
12 return Some(compress_show(trimmed));
13 }
14
15 if trimmed.starts_with("Query OK") || trimmed.starts_with("Empty set") {
16 return Some(trimmed.lines().next().unwrap_or(trimmed).to_string());
17 }
18
19 Some(compact_lines(trimmed, 20))
20}
21
22fn is_table_output(output: &str) -> bool {
23 let lines: Vec<&str> = output.lines().collect();
24 lines.len() >= 3
25 && lines
26 .iter()
27 .any(|l| l.starts_with('+') && l.contains("---"))
28}
29
30fn compress_table(output: &str) -> String {
31 let lines: Vec<&str> = output.lines().collect();
32 let data_lines: Vec<&&str> = lines
33 .iter()
34 .filter(|l| !l.starts_with('+') && !l.trim().is_empty())
35 .collect();
36
37 let row_count = if data_lines.len() > 1 {
38 data_lines.len() - 1
39 } else {
40 0
41 };
42
43 if row_count <= 20 {
44 return output.to_string();
45 }
46
47 let header_end = lines
48 .iter()
49 .enumerate()
50 .filter(|(_, l)| l.starts_with('+'))
51 .nth(1)
52 .map_or(3, |(i, _)| i + 1);
53
54 let preview_end = (header_end + 10).min(lines.len());
55 let preview = &lines[..preview_end];
56 format!("{}\n... ({row_count} rows total)", preview.join("\n"))
57}
58
59fn compress_show(output: &str) -> String {
60 let items: Vec<&str> = output
61 .lines()
62 .filter(|l| !l.starts_with('+') && !l.trim().is_empty() && !l.contains("---"))
63 .filter(|l| !l.contains("Database") && !l.contains("Tables_in"))
64 .map(|l| l.trim().trim_matches('|').trim())
65 .filter(|l| !l.is_empty())
66 .collect();
67
68 if items.is_empty() {
69 return "empty".to_string();
70 }
71 if items.len() <= 30 {
72 return format!("{} items: {}", items.len(), items.join(", "));
73 }
74 format!(
75 "{} items: {}, ... +{} more",
76 items.len(),
77 items[..20].join(", "),
78 items.len() - 20
79 )
80}
81
82fn compact_lines(text: &str, max: usize) -> String {
83 let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
84 if lines.len() <= max {
85 return lines.join("\n");
86 }
87 format!(
88 "{}\n... ({} more lines)",
89 lines[..max].join("\n"),
90 lines.len() - max
91 )
92}