flatten_rust/
lib.rs

1use std::collections::HashSet;
2use std::fs;
3use std::path::Path;
4
5pub struct FlattenConfig {
6    pub skip_folders: HashSet<String>,
7    pub skip_extensions: HashSet<String>,
8    pub show_skipped: bool,
9    pub max_file_size: u64,
10    pub include_hidden: bool,
11    pub max_depth: usize,
12}
13
14impl Default for FlattenConfig {
15    fn default() -> Self {
16        Self {
17            skip_folders: HashSet::new(),
18            skip_extensions: HashSet::new(),
19            show_skipped: false,
20            max_file_size: 104857600, // 100MB
21            include_hidden: false,
22            max_depth: usize::MAX,
23        }
24    }
25}
26
27impl FlattenConfig {
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    pub fn should_skip_path(&self, path: &Path) -> bool {
33        if let Some(name) = path.file_name() {
34            if let Some(name_str) = name.to_str() {
35                // Skip hidden files unless explicitly included
36                if !self.include_hidden && name_str.starts_with('.') {
37                    return true;
38                }
39                return self.skip_folders.contains(name_str);
40            }
41        }
42        false
43    }
44
45    pub fn should_skip_file(&self, path: &Path) -> bool {
46        if let Some(extension) = path.extension() {
47            if let Some(ext_str) = extension.to_str() {
48                return self.skip_extensions.contains(ext_str);
49            }
50        }
51        false
52    }
53}
54
55pub fn create_test_structure() -> anyhow::Result<tempfile::TempDir> {
56    let temp_dir = tempfile::TempDir::new()?;
57
58    // Create basic structure
59    fs::create_dir_all(temp_dir.path().join("src"))?;
60    fs::create_dir_all(temp_dir.path().join("tests"))?;
61    fs::create_dir_all(temp_dir.path().join("node_modules"))?;
62
63    // Create files
64    fs::write(
65        temp_dir.path().join("src/main.rs"),
66        "fn main() { println!(\"Hello\"); }",
67    )?;
68    fs::write(
69        temp_dir.path().join("src/lib.rs"),
70        "pub fn hello() { \"world\" }",
71    )?;
72    fs::write(
73        temp_dir.path().join("tests/integration.rs"),
74        "#[test] fn test_integration() {}",
75    )?;
76    fs::write(temp_dir.path().join("README.md"), "# Test Project")?;
77    fs::write(
78        temp_dir.path().join("Cargo.toml"),
79        "[package]\nname = \"test\"\nversion = \"0.1.0\"",
80    )?;
81
82    // Create a binary file
83    fs::write(temp_dir.path().join("test.bin"), b"\x00\x01\x02\x03\x04")?;
84
85    Ok(temp_dir)
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use std::fs;
92
93    #[test]
94    fn test_config_skip_folders() {
95        let mut config = FlattenConfig::new();
96        config.skip_folders.insert("node_modules".to_string());
97        config.skip_folders.insert(".git".to_string());
98
99        assert!(config.should_skip_path(Path::new("/project/node_modules")));
100        assert!(config.should_skip_path(Path::new("/project/.git")));
101        assert!(!config.should_skip_path(Path::new("/project/src")));
102    }
103
104    #[test]
105    fn test_config_skip_extensions() {
106        let mut config = FlattenConfig::new();
107        config.skip_extensions.insert("exe".to_string());
108        config.skip_extensions.insert("bin".to_string());
109
110        assert!(config.should_skip_file(Path::new("/project/test.exe")));
111        assert!(config.should_skip_file(Path::new("/project/test.bin")));
112        assert!(!config.should_skip_file(Path::new("/project/test.rs")));
113    }
114
115    #[test]
116    fn test_create_test_structure() {
117        let temp_dir = create_test_structure().unwrap();
118
119        assert!(temp_dir.path().join("src").exists());
120        assert!(temp_dir.path().join("tests").exists());
121        assert!(temp_dir.path().join("node_modules").exists());
122        assert!(temp_dir.path().join("src/main.rs").exists());
123        assert!(temp_dir.path().join("README.md").exists());
124    }
125
126    #[test]
127    fn test_file_content_reading() {
128        let temp_dir = create_test_structure().unwrap();
129        let main_rs_path = temp_dir.path().join("src/main.rs");
130
131        let content = fs::read_to_string(&main_rs_path).unwrap();
132        assert!(content.contains("fn main()"));
133    }
134}