treestat 1.1.0

A CLI that displays source file counts in a tree view by directory and language
Documentation
pub mod cli;
pub mod lang;
pub mod model;
pub mod render;
pub mod scanner;

use std::path::Path;

use cli::{Cli, Format};
use lang::build_extensions;
use render::{render_json, render_text};
use scanner::{compute_tree_counts, scan_tree};

pub fn run(cli: Cli) -> Result<String, String> {
    let start = std::time::Instant::now();
    let root = cli
        .path
        .canonicalize()
        .map_err(|e| format!("failed to resolve root path {:?}: {e}", cli.path))?;
    if !root.is_dir() {
        return Err(format!("path is not a directory: {}", root.display()));
    }

    let extensions = build_extensions(&cli.langs, &cli.ext, cli.headers)?;
    if extensions.is_empty() {
        return Err("no extensions selected; provide --lang or --ext".to_string());
    }

    let gitignore_patterns = if cli.no_gitignore {
        vec![]
    } else {
        scanner::load_gitignore_patterns(Path::new(&root))
    };

    let scan = scan_tree(Path::new(&root), &extensions, &cli, &gitignore_patterns)?;
    let tree_counts = compute_tree_counts(Path::new(&scan.root), &scan.dirs);
    let duration_secs = start.elapsed().as_secs_f64();

    let output = match cli.format {
        Format::Text => render_text(&scan, &tree_counts, &cli.langs, &cli, duration_secs),
        Format::Json => render_json(&scan, &tree_counts, &cli.langs, &cli, duration_secs, cli.json_pretty),
    };

    Ok(output)
}