use crate::source_loc::SourceLoc;
use clap::{Args, Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
#[derive(Parser, Debug, Clone)]
#[command(
version, about,
after_help(env!("CARGO_PKG_HOMEPAGE")),
propagate_version = true
)]
pub struct CliOpts {
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
pub verbose: u8,
#[command(subcommand)]
pub cmd: Command,
}
#[derive(Subcommand, Debug, Clone)]
pub enum Command {
Apply(ApplyOpts),
Reapply(ReapplyOpts),
Inspect,
ShowJsonSchema,
TestSamples(TestSamplesOpts),
}
#[derive(Args, Debug, Default, Clone)]
pub struct ApplyOpts {
#[arg(long, default_value = "Never", value_enum, ignore_case = true)]
pub confirm: AskConfirmation,
#[arg(long, default_value = "Ask", value_enum, ignore_case = true)]
pub update_mode: UpdateMode,
#[arg(short = 'y', long = "no-interaction")]
pub no_interaction: bool,
#[arg(long = "offline")]
pub offline: bool,
#[command(flatten)]
pub src: SourceLoc,
#[arg(
short = 'd',
long = "destination",
value_name = "FOLDER"
)]
pub dst_folder: PathBuf,
#[arg(short = 'v', long = "variables", value_parser = parse_keyvalue)]
pub key_value: Vec<(String, String)>,
}
#[derive(Args, Debug, Default, Clone)]
pub struct ReapplyOpts {
#[arg(long, default_value = "Never", value_enum, ignore_case = true)]
pub confirm: AskConfirmation,
#[arg(long, default_value = "Ask", value_enum, ignore_case = true)]
pub update_mode: UpdateMode,
#[arg(short = 'y', long = "no-interaction")]
pub no_interaction: bool,
#[arg(long = "offline")]
pub offline: bool,
#[arg(
short = 'd',
long = "destination",
default_value = ".",
value_name = "FOLDER"
)]
pub dst_folder: PathBuf,
#[arg(short = 'v', long = "variables", value_parser = parse_keyvalue)]
pub key_value: Vec<(String, String)>,
}
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum, Default)]
pub enum AskConfirmation {
#[default]
Auto,
Always,
Never,
}
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum, Default)]
pub enum UpdateMode {
#[default]
Ask,
Keep,
Override,
UpdateAsRemote,
CurrentAsLocal,
ShowDiff,
Merge,
}
impl std::fmt::Display for UpdateMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"{}",
self.to_possible_value()
.expect("UpdateMode should have a possible value")
.get_name()
))
}
}
fn parse_keyvalue(src: &str) -> Result<(String, String), String> {
let kv: Vec<&str> = src.splitn(2, '=').collect();
if kv.len() == 2 {
Ok((kv[0].to_owned(), kv[1].to_owned()))
} else {
Ok((src.to_owned(), "".to_owned()))
}
}
#[derive(Parser, Debug, Default, Clone)]
pub struct TestSamplesOpts {
#[command(flatten)]
pub src: SourceLoc,
#[arg(long = "offline")]
pub offline: bool,
#[arg(long = "review")]
pub review: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verify_cli() {
use clap::CommandFactory;
CliOpts::command().debug_assert()
}
}