nils-memo-cli 0.3.3

CLI crate for nils-memo-cli in the nils-cli workspace.
Documentation
use std::ffi::OsString;

use clap::{Parser, error::ErrorKind};

use crate::cli::{Cli, OutputMode};
use crate::errors::AppError;

pub fn run() -> i32 {
    run_with_args(std::env::args_os())
}

pub fn run_with_args<I, T>(args: I) -> i32
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    let cli = match Cli::try_parse_from(args) {
        Ok(cli) => cli,
        Err(err) => {
            let kind = err.kind();
            match kind {
                ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => {
                    print!("{err}");
                    return 0;
                }
                _ => {
                    eprint!("{err}");
                    return 64;
                }
            }
        }
    };

    let output_mode = match cli.resolve_output_mode() {
        Ok(mode) => mode,
        Err(err) => {
            eprintln!("{}", err.message());
            return err.exit_code();
        }
    };

    match crate::commands::run(&cli, output_mode) {
        Ok(()) => 0,
        Err(err) => report_error(&cli, output_mode, &err),
    }
}

fn report_error(cli: &Cli, output_mode: OutputMode, err: &AppError) -> i32 {
    if output_mode.is_json()
        && let Err(output_err) =
            crate::output::emit_json_error(cli.schema_version(), cli.command_id(), err)
    {
        eprintln!("{}", output_err.message());
    }

    if !output_mode.is_json() {
        eprintln!("{}", err.message());
    }

    err.exit_code()
}