hakoniwa_cli/
cli.rs

1mod argparse;
2mod pathsearch;
3mod subcommands;
4
5use clap::builder::styling::{AnsiColor, Styles};
6use clap::{Parser, Subcommand};
7use clap_verbosity_flag::{InfoLevel, Verbosity};
8
9const AFTER_HELP: &str =
10    "To view the user documentation, please visit https://github.com/souk4711/hakoniwa.";
11
12fn styles() -> Styles {
13    Styles::styled()
14        .header(AnsiColor::Yellow.on_default())
15        .usage(AnsiColor::Green.on_default())
16        .literal(AnsiColor::Green.on_default())
17        .placeholder(AnsiColor::Green.on_default())
18}
19
20#[derive(Parser)]
21#[command(name = "hakoniwa", version)]
22#[command(about, long_about = None)]
23#[command(disable_help_subcommand = true, after_help = AFTER_HELP)]
24#[command(styles = styles())]
25struct Cli {
26    #[command(subcommand)]
27    command: Commands,
28
29    #[command(flatten, next_display_order = 100)]
30    verbose: Verbosity<InfoLevel>,
31}
32
33#[allow(clippy::large_enum_variant)]
34#[derive(Subcommand)]
35enum Commands {
36    /// Generate SHELL autocompletions
37    Completion(subcommands::CompletionCommand),
38
39    /// Run a COMMAND in a container
40    Run(subcommands::RunCommand),
41}
42
43pub fn execute() -> i32 {
44    let cli = Cli::parse();
45
46    let level_filter = cli.verbose.log_level_filter();
47    let debugging = level_filter >= log::LevelFilter::Debug;
48    let timestamp: Option<env_logger::fmt::TimestampPrecision> = if debugging {
49        Some(env_logger::fmt::TimestampPrecision::Seconds)
50    } else {
51        None
52    };
53    env_logger::builder()
54        .format_level(debugging)
55        .format_target(false)
56        .format_timestamp(timestamp)
57        .filter_level(level_filter)
58        .init();
59
60    let r = match &cli.command {
61        Commands::Completion(cmd) => cmd.execute(),
62        Commands::Run(cmd) => cmd.execute(),
63    };
64
65    if let Err(err) = r {
66        log::error!("{err}");
67        1
68    } else {
69        r.unwrap()
70    }
71}