use std::path::PathBuf;
use crate::{cli::cmd, core::bootstrap::AppContextArgs};
use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum FormatArg {
Auto,
Text,
Markdown,
Json,
Jsonl,
Plain,
}
impl FormatArg {
pub fn to_output_format_string(&self, use_json: bool) -> String {
match (use_json, self) {
(_, FormatArg::Text) => "text".to_string(),
(_, FormatArg::Markdown) => "markdown".to_string(),
(_, FormatArg::Json) => "json".to_string(),
(_, FormatArg::Jsonl) => "jsonl".to_string(),
(_, FormatArg::Plain) => "plain".to_string(),
(true, FormatArg::Auto) => "json".to_string(),
(false, FormatArg::Auto) => "text".to_string(),
}
}
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ColorMode {
Auto,
Always,
Never,
}
impl std::fmt::Display for ColorMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ColorMode::Auto => write!(f, "auto"),
ColorMode::Always => write!(f, "always"),
ColorMode::Never => write!(f, "never"),
}
}
}
#[derive(Parser, Debug)]
#[command(
name = "cw",
version,
author,
about = "🧙📜🪄📖✨ Commit Wizard - A Spellbook for Conventional Commits, Semantic Versioning, and Changelog Automation.",
propagate_version = true,
arg_required_else_help = true
)]
pub struct Cli {
#[command(flatten)]
pub global: GlobalArgs,
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Clone, Subcommand)]
pub enum Command {
Add(cmd::add::Args),
Bump(cmd::bump::Args),
Check(cmd::check::Args),
Commit(cmd::commit::Args),
Config(cmd::config::Args),
Doctor(cmd::doctor::Args),
Init(cmd::init::Args),
Push(cmd::push::Args),
Tag(cmd::tag::Args),
}
#[derive(Debug, Clone, Args)]
pub struct GlobalArgs {
#[arg(short = 'v', long = "verbose", action = ArgAction::Count, global = true)]
pub verbose: u8,
#[arg(short = 'q', long = "quiet", action = ArgAction::Count, global = true)]
pub quiet: u8,
#[arg(long, global = true)]
pub json: bool,
#[arg(long, global = true, default_value_t = FormatArg::Auto, value_enum, conflicts_with = "plain")]
pub format: FormatArg,
#[arg(long, short = 'p', global = true, conflicts_with = "format")]
pub plain: bool,
#[arg(long, global = true)]
pub dry_run: bool,
#[arg(long, value_enum, default_value_t = ColorMode::Auto, global = true)]
pub color: ColorMode,
#[arg(short = 'C', long = "cwd", global = true, default_value = ".")]
pub cwd: PathBuf,
#[arg(long, global = true, conflicts_with = "non_interactive")]
pub ci: bool,
#[arg(long, global = true, conflicts_with = "ci")]
pub non_interactive: bool,
#[arg(long, short = 'y', global = true)]
pub yes: bool,
#[arg(long, global = true)]
pub force: bool,
#[arg(long, global = true)]
pub config: Option<PathBuf>,
#[arg(long, global = true)]
pub registry: Option<String>,
#[arg(long = "registry-ref", global = true)]
pub registry_ref: Option<String>,
#[arg(long = "registry-section", global = true)]
pub registry_section: Option<String>,
}
impl From<GlobalArgs> for AppContextArgs {
fn from(args: GlobalArgs) -> Self {
Self {
verbose: args.verbose,
quiet: args.quiet,
json: args.json,
format: if args.plain {
"plain".to_string()
} else {
args.format.to_output_format_string(args.json)
},
dry_run: args.dry_run,
output_color: args.color.to_string(),
cwd: args.cwd,
ci: args.ci,
non_interactive: args.non_interactive,
auto_yes: args.yes,
force: args.force,
config_path: args.config,
registry: args.registry,
registry_ref: args.registry_ref,
registry_section: args.registry_section,
}
}
}