use std::ffi::OsString;
use std::process::ExitCode;
use clap::Parser;
use super::errors::{classify_clap_error, classify_clap_exit_code, classify_command_error};
use super::exit::{CliError, CliExitCode};
use super::schema::Cli;
use super::validate::validate_cli;
use super::{commands::entry::run_command, db_path};
pub fn run() -> std::result::Result<(), CliError> {
run_from(std::env::args_os())
}
pub fn run_from<I, T>(args: I) -> std::result::Result<(), CliError>
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
let cli = Cli::try_parse_from(args).map_err(classify_clap_error)?;
validate_cli(&cli).map_err(classify_clap_error)?;
let db_path = cli.db.unwrap_or_else(db_path::default_db_path);
run_command(cli.command, &db_path).map_err(classify_command_error)
}
pub fn run_cli() -> ExitCode {
match try_run_cli(std::env::args_os()) {
Ok(code) => code.as_exit_code(),
Err(error) => {
if error.use_stderr() {
eprint!("{error}");
} else {
print!("{error}");
}
classify_clap_exit_code(error.kind()).as_exit_code()
}
}
}
fn try_run_cli<I, T>(args: I) -> std::result::Result<CliExitCode, clap::Error>
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
let cli = Cli::try_parse_from(args)?;
validate_cli(&cli)?;
let db_path = cli.db.unwrap_or_else(db_path::default_db_path);
match run_command(cli.command, &db_path) {
Ok(()) => Ok(CliExitCode::Ok),
Err(error) => {
let classified = classify_command_error(error);
eprintln!("{}", classified.message());
Ok(classified.exit_code())
}
}
}