use std::fs;
use std::io::{self, Read, Write};
use std::path::PathBuf;
use clap::Parser;
use parfit::{reflow, Options};
mod walker;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Cli {
#[arg(value_name = "PATH")]
paths: Vec<PathBuf>,
#[arg(short = 'w', long, default_value_t = 68)]
width: usize,
#[arg(short = 'r', long)]
recursive: bool,
#[arg(short = 'i', long = "in-place")]
in_place: bool,
#[arg(long = "include", value_name = "GLOB")]
includes: Vec<String>,
#[arg(long = "exclude", value_name = "GLOB")]
excludes: Vec<String>,
#[arg(short = 's', long = "skip", value_name = "REGEX")]
skips: Vec<String>,
#[arg(long)]
no_default_skips: bool,
#[arg(short = 'p', long, value_name = "STRING")]
prefix: Option<String>,
}
fn main() -> io::Result<()> {
let cli = Cli::parse();
let opts = build_options(&cli)?;
if cli.paths.is_empty() {
return run_stdin(&opts);
}
run_paths(&cli, &opts)
}
fn build_options(cli: &Cli) -> io::Result<Options> {
let mut opts = Options::new(cli.width);
if cli.no_default_skips {
opts = opts.with_default_skips(false);
}
for pattern in &cli.skips {
opts = opts
.with_skip(pattern)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))?;
}
if let Some(prefix) = &cli.prefix {
opts = opts.with_forced_prefix(prefix.clone());
}
Ok(opts)
}
fn run_stdin(opts: &Options) -> io::Result<()> {
let mut input = String::new();
io::stdin().read_to_string(&mut input)?;
io::stdout().write_all(reflow(&input, opts).as_bytes())
}
fn run_paths(cli: &Cli, opts: &Options) -> io::Result<()> {
let files = walker::walk(&cli.paths, cli.recursive, &cli.includes, &cli.excludes)?;
if files.is_empty() {
return Ok(());
}
if files.len() > 1 && !cli.in_place {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"multiple files would be processed; pass --in-place to rewrite them \
(or narrow the input to a single file for stdout)",
));
}
for path in &files {
let content = fs::read_to_string(path)?;
let wrapped = reflow(&content, opts);
if cli.in_place {
fs::write(path, wrapped)?;
} else {
io::stdout().write_all(wrapped.as_bytes())?;
}
}
Ok(())
}