use clap::Parser;
use md_formatter::cli::{Args, InputSource};
use md_formatter::{extract_frontmatter, parse_markdown, Formatter};
use std::fs;
use std::io::{self, Read};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let sources = args.get_input_sources()?;
let mut has_errors = false;
let mut files_checked = 0;
let mut files_would_change = 0;
for source in sources {
match process_source(&source, &args) {
Ok(changed) => {
if args.check {
files_checked += 1;
if changed {
files_would_change += 1;
has_errors = true;
}
}
}
Err(e) => {
eprintln!("Error: {}", e);
has_errors = true;
}
}
}
if args.check && files_checked > 0 {
if files_would_change > 0 {
eprintln!("{} file(s) would be reformatted", files_would_change);
} else {
eprintln!("All {} file(s) are formatted correctly", files_checked);
}
}
if has_errors {
std::process::exit(1);
}
Ok(())
}
fn process_source(source: &InputSource, args: &Args) -> Result<bool, Box<dyn std::error::Error>> {
let (content, path_for_output) = match source {
InputSource::Stdin => {
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
(buffer, None)
}
InputSource::File(path) => {
let content = fs::read_to_string(path)?;
(content, Some(path.clone()))
}
};
let (frontmatter, markdown_content) = extract_frontmatter(&content);
let events = parse_markdown(markdown_content);
let wrap_mode: md_formatter::WrapMode = args.wrap.into();
let ordered_list_mode: md_formatter::OrderedListMode = args.ordered_list.into();
let mut formatter = Formatter::with_options(args.width, wrap_mode, ordered_list_mode);
let formatted = formatter.format(events);
let final_output = if let Some(fm) = frontmatter {
fm + &formatted
} else {
formatted
};
let changed = content != final_output;
if let Some(path) = path_for_output {
if args.check {
if changed {
eprintln!("Would reformat: {}", path.display());
}
} else if args.write {
if changed {
fs::write(&path, &final_output)?;
eprintln!("Formatted: {}", path.display());
}
} else {
print!("{}", final_output);
}
} else {
print!("{}", final_output);
}
Ok(changed)
}