Skip to main content

bito_lint/commands/
readability.rs

1//! Readability command — Flesch-Kincaid Grade Level scoring.
2
3use anyhow::{Context, bail};
4use camino::Utf8PathBuf;
5use clap::Args;
6use owo_colors::OwoColorize;
7use tracing::{debug, instrument};
8
9use bito_lint_core::readability;
10
11use super::read_input_file;
12
13/// Arguments for the `readability` subcommand.
14#[derive(Args, Debug)]
15pub struct ReadabilityArgs {
16    /// File to analyze.
17    pub file: Utf8PathBuf,
18
19    /// Maximum acceptable grade level.
20    #[arg(long)]
21    pub max_grade: Option<f64>,
22}
23
24/// Score readability of a file using Flesch-Kincaid Grade Level.
25#[instrument(name = "cmd_readability", skip_all, fields(file = %args.file))]
26pub fn cmd_readability(
27    args: ReadabilityArgs,
28    global_json: bool,
29    config_max_grade: Option<f64>,
30    max_input_bytes: Option<usize>,
31) -> anyhow::Result<()> {
32    debug!(file = %args.file, max_grade = ?args.max_grade, "executing readability command");
33
34    let content = read_input_file(&args.file, max_input_bytes)?;
35
36    let strip_md = args.file.extension() == Some("md");
37    let max_grade = args.max_grade.or(config_max_grade);
38
39    let report = readability::check_readability(&content, strip_md, max_grade)
40        .with_context(|| format!("failed to check readability of {}", args.file))?;
41
42    if global_json {
43        println!("{}", serde_json::to_string_pretty(&report)?);
44    } else if report.over_max {
45        let max = report.max_grade.unwrap_or(0.0);
46        bail!(
47            "{} scores {:.1} (max: {:.0}). Simplify sentences or reduce jargon.",
48            args.file,
49            report.grade,
50            max,
51        );
52    } else if let Some(max) = report.max_grade {
53        println!(
54            "{} {} scores {:.1} (max: {:.0})",
55            "PASS:".green(),
56            args.file,
57            report.grade,
58            max,
59        );
60    } else {
61        println!("{:.1}", report.grade);
62    }
63
64    Ok(())
65}