acta-build 0.4.0

Build-time helper for acta: compute path-column width from a project's source tree
Documentation
//! Build-time helper for [acta](https://crates.io/crates/acta).
//!
//! Call from your `build.rs` to compute a sensible default `path_width` for
//! `acta::Formatter` based on the longest source-file path in your project.
//!
//! # Example
//!
//! Add to your `Cargo.toml`:
//!
//! ```toml
//! [build-dependencies]
//! acta-build = "0.1"
//! ```
//!
//! In `build.rs`:
//!
//! ```no_run
//! # fn example() {
//! let width = acta_build::walk_src_max_width("src", "src/");
//! println!("cargo:rustc-env=ACTA_PATH_WIDTH={width}");
//! println!("cargo:rerun-if-changed=src");
//! # }
//! ```
//!
//! Then in your code:
//!
//! ```ignore
//! let width: usize = env!("ACTA_PATH_WIDTH").parse().unwrap_or(40);
//! let formatter = acta::Formatter::new().with_path_width(width);
//! ```

use std::path::Path;
use walkdir::WalkDir;

/// Walk `dir` recursively, find every `.rs` file, and return
/// `max(path_len_after_stripping(strip_prefix)) + 4`.
///
/// Returns 40 if `dir` does not exist or contains no .rs files
#[must_use]
pub fn walk_src_max_width(dir: impl AsRef<Path>, strip_prefix: &str) -> usize {
    WalkDir::new(dir.as_ref())
        .into_iter()
        .filter_map(Result::ok)
        .filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
        .map(|e| {
            let display = e.path().to_string_lossy().replace('\\', "/");
            display.strip_prefix(strip_prefix).unwrap_or(&display).len()
        })
        .max()
        .map_or(40, |max| max + 4)
}