Skip to main content

memo_cli/
app.rs

1use std::ffi::OsString;
2
3use clap::{Parser, error::ErrorKind};
4
5use crate::cli::{Cli, MemoCommand, 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    if let MemoCommand::Completion(args) = cli.command {
35        return crate::completion::run(args.shell);
36    }
37
38    let output_mode = match cli.resolve_output_mode() {
39        Ok(mode) => mode,
40        Err(err) => {
41            eprintln!("{}", err.message());
42            return err.exit_code();
43        }
44    };
45
46    match crate::commands::run(&cli, output_mode) {
47        Ok(()) => 0,
48        Err(err) => report_error(&cli, output_mode, &err),
49    }
50}
51
52fn report_error(cli: &Cli, output_mode: OutputMode, err: &AppError) -> i32 {
53    if output_mode.is_json()
54        && let Err(output_err) =
55            crate::output::emit_json_error(cli.schema_version(), cli.command_id(), err)
56    {
57        eprintln!("{}", output_err.message());
58    }
59
60    if !output_mode.is_json() {
61        eprintln!("{}", err.message());
62    }
63
64    err.exit_code()
65}