#![deny(clippy::all)]
use clap::Parser;
use rayon::prelude::*;
use serde_json::json;
use std::error::Error;
use std::path::PathBuf;
use wordcrab::{analyse_file, analyse_files, AnalysisOptions};
#[derive(Parser, Debug)]
#[clap(
name = "wordcrab",
about = "A command-line tool for counting lines, words and characters in documents.
It is a modern, cross-platform replacement for wc(1).
When analysis options (any combination of -l, -w, -c) are specified, wordcrab only analyses and reports the information requested. The order of output is always line, word, chars, filename. By default, -lwc is assumed.
Multiple output formats are supported in addition to the standard text output.
"
)]
struct Opt {
#[clap(short, long)]
debug: bool,
#[clap(short, long)]
lines: bool,
#[clap(short, long)]
words: bool,
#[clap(short, long)]
chars: bool,
#[clap(short, long, value_parser = ["text", "json", "yaml", "toml"], default_value = "text")]
output: String,
#[clap(name = "FILE", value_parser)]
files: Vec<PathBuf>,
}
fn main() -> Result<(), Box<dyn Error>> {
let mut opt = Opt::parse();
if opt.debug {
println!("raw opts:");
println!("{:#?}", opt);
}
if !opt.lines && !opt.words && !opt.chars {
opt.lines = true;
opt.words = true;
opt.chars = true;
};
let analysis_options = AnalysisOptions {
lines: opt.lines,
words: opt.words,
chars: opt.chars,
};
if opt.debug {
println!("parsed analysis options:");
println!("{:#?}", analysis_options);
}
let files = opt.files;
let filenames: Vec<&str> = files
.par_iter()
.map(|path| path.to_str().unwrap()) .collect();
match opt.output.as_str() {
"text" => filenames.par_iter().for_each(|filename| {
println!("{}", analyse_file(filename, analysis_options));
}),
"json" => {
let results = analyse_files(&filenames, analysis_options);
println!("{}", json!(results))
}
"toml" => {
let results = analyse_files(&filenames, analysis_options);
println!("{}", toml::to_string(&results)?)
}
"yaml" => {
let results = analyse_files(&filenames, analysis_options);
match serde_yaml::to_string(&results) {
Ok(yaml) => println!("{}", yaml),
Err(e) => panic!("{}", e),
}
}
_ => unreachable!(), }
Ok(())
}