collet 0.1.1

Relentless agentic coding orchestrator with zero-drop agent loops
Documentation
use std::path::{Path, PathBuf};

/// Supported file extensions for code analysis.
const SUPPORTED_EXTENSIONS: &[&str] = &[
    "rs", "py", "js", "ts", "tsx", "jsx", "go", "java", "c", "cpp", "h", "hpp", "rb", "swift",
    "kt", "scala",
];

/// Scan a directory for source files, respecting .gitignore.
pub fn scan_source_files(root: &Path) -> Vec<PathBuf> {
    let mut files = Vec::new();

    // Use the `ignore` crate which respects .gitignore natively
    let walker = ignore::WalkBuilder::new(root)
        .hidden(true) // skip hidden files/dirs
        .git_ignore(true) // respect .gitignore
        .git_global(true) // respect global gitignore
        .git_exclude(true) // respect .git/info/exclude
        .require_git(false) // honour .gitignore even outside a git repo (e.g. tempdir in tests)
        .add_custom_ignore_filename(".colletignore") // respect .colletignore
        .max_depth(Some(20)) // safety limit
        .build();

    for entry in walker {
        let entry = match entry {
            Ok(e) => e,
            Err(_) => continue,
        };

        if !entry.file_type().is_some_and(|ft| ft.is_file()) {
            continue;
        }

        let path = entry.path();

        // Check extension
        if let Some(ext) = path.extension().and_then(|e| e.to_str())
            && SUPPORTED_EXTENSIONS.contains(&ext)
        {
            files.push(path.to_path_buf());
        }
    }

    files.sort();
    files
}