1use std::ffi::OsString;
2
3use clap::{Parser, error::ErrorKind};
4
5use crate::cli::{Cli, OutputMode};
6use crate::errors::AppError;
7
8pub fn run() -> i32 {
9 run_with_args(std::env::args_os())
10}
11
12pub fn run_with_args<I, T>(args: I) -> i32
13where
14 I: IntoIterator<Item = T>,
15 T: Into<OsString> + Clone,
16{
17 let cli = match Cli::try_parse_from(args) {
18 Ok(cli) => cli,
19 Err(err) => {
20 let kind = err.kind();
21 match kind {
22 ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => {
23 print!("{err}");
24 return 0;
25 }
26 _ => {
27 eprint!("{err}");
28 return 64;
29 }
30 }
31 }
32 };
33
34 let output_mode = match cli.resolve_output_mode() {
35 Ok(mode) => mode,
36 Err(err) => {
37 eprintln!("{}", err.message());
38 return err.exit_code();
39 }
40 };
41
42 match crate::commands::run(&cli, output_mode) {
43 Ok(()) => 0,
44 Err(err) => report_error(&cli, output_mode, &err),
45 }
46}
47
48fn report_error(cli: &Cli, output_mode: OutputMode, err: &AppError) -> i32 {
49 if output_mode.is_json()
50 && let Err(output_err) =
51 crate::output::emit_json_error(cli.schema_version(), cli.command_id(), err)
52 {
53 eprintln!("{}", output_err.message());
54 }
55
56 if !output_mode.is_json() {
57 eprintln!("{}", err.message());
58 }
59
60 err.exit_code()
61}