pub mod args;
pub mod commands;
pub mod parsers;
use std::{ffi::OsString, process};
use clap::Parser;
use crate::{
clap::args::JsonFlag,
error::{EXIT_USAGE, ErrorReport, NoErrorCode, usage_error},
printer::{Printer, StdoutPrinter},
};
pub fn parse<T: Parser>() -> T {
parse_from(std::env::args_os())
}
pub fn parse_from<T, I>(args: I) -> T
where
T: Parser,
I: IntoIterator,
I::Item: Into<OsString> + Clone,
{
let args: Vec<OsString> = args.into_iter().map(Into::into).collect();
let err = match T::try_parse_from(&args) {
Ok(parsed) => return parsed,
Err(err) => err,
};
if !err.use_stderr() || !json_requested(&args) {
err.exit()
}
let mut printer = StdoutPrinter::new(&JsonFlag { enabled: true });
let _ = printer.out(ErrorReport::<NoErrorCode>::from(usage_error(&err)));
process::exit(EXIT_USAGE)
}
fn json_requested(args: &[OsString]) -> bool {
args.iter()
.skip(1)
.take_while(|arg| *arg != "--")
.any(|arg| arg == "--json")
}
#[cfg(test)]
mod tests {
use std::ffi::OsString;
use super::json_requested;
fn args(words: &[&str]) -> Vec<OsString> {
words.iter().map(OsString::from).collect()
}
#[test]
fn json_counts_only_before_the_separator() {
assert!(json_requested(&args(&["app", "--json", "list"])));
assert!(json_requested(&args(&["app", "list", "--bad", "--json"])));
assert!(!json_requested(&args(&["app", "add", "--", "--json"])));
assert!(!json_requested(&args(&["--json", "list"])));
}
}