Skip to main content

lean_ctx/core/patterns/
find.rs

1use std::collections::HashMap;
2
3pub fn compress(output: &str) -> Option<String> {
4    let lines: Vec<&str> = output.lines().filter(|l| !l.trim().is_empty()).collect();
5    if lines.len() < 5 {
6        return None;
7    }
8
9    let mut by_dir: HashMap<String, Vec<String>> = HashMap::new();
10    let mut total_files = 0usize;
11
12    for line in &lines {
13        let path = line.trim().strip_prefix("./").unwrap_or(line.trim());
14
15        if should_skip(path) {
16            continue;
17        }
18
19        total_files += 1;
20
21        if let Some(slash_pos) = path.rfind('/') {
22            let dir = &path[..slash_pos];
23            let file = &path[slash_pos + 1..];
24            by_dir
25                .entry(dir.to_string())
26                .or_default()
27                .push(file.to_string());
28        } else {
29            by_dir
30                .entry(".".to_string())
31                .or_default()
32                .push(path.to_string());
33        }
34    }
35
36    if total_files == 0 {
37        return None;
38    }
39
40    let mut result = format!("{total_files}F {}D:\n", by_dir.len());
41    let mut sorted_dirs: Vec<_> = by_dir.iter().collect();
42    sorted_dirs.sort_by_key(|(dir, _)| (*dir).clone());
43
44    for (dir, files) in &sorted_dirs {
45        result.push_str(&format!("\n{dir}/"));
46        let show: Vec<_> = files.iter().take(10).collect();
47        let mut line_buf = String::new();
48        for f in &show {
49            if line_buf.len() + f.len() + 1 > 60 {
50                result.push_str(&format!("\n  {line_buf}"));
51                line_buf.clear();
52            }
53            if !line_buf.is_empty() {
54                line_buf.push(' ');
55            }
56            line_buf.push_str(f);
57        }
58        if !line_buf.is_empty() {
59            result.push_str(&format!("\n  {line_buf}"));
60        }
61        if files.len() > 10 {
62            result.push_str(&format!("\n  ... +{} more", files.len() - 10));
63        }
64    }
65
66    Some(result)
67}
68
69fn should_skip(path: &str) -> bool {
70    let skip_dirs = [
71        "node_modules/",
72        ".git/",
73        "target/debug/",
74        "target/release/",
75        "__pycache__/",
76        ".svelte-kit/",
77        ".next/",
78        "dist/",
79        ".DS_Store",
80    ];
81    skip_dirs.iter().any(|d| path.contains(d))
82}