1use std::path::PathBuf;
2
3use crate::{cli::cmd, core::bootstrap::AppContextArgs};
4use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
7pub enum FormatArg {
8 Auto,
9 Text,
10 Markdown,
11 Json,
12 Jsonl,
13 Plain,
14}
15
16impl FormatArg {
17 pub fn to_output_format_string(&self, use_json: bool) -> String {
18 match (use_json, self) {
19 (_, FormatArg::Text) => "text".to_string(),
20 (_, FormatArg::Markdown) => "markdown".to_string(),
21 (_, FormatArg::Json) => "json".to_string(),
22 (_, FormatArg::Jsonl) => "jsonl".to_string(),
23 (_, FormatArg::Plain) => "plain".to_string(),
24 (true, FormatArg::Auto) => "json".to_string(),
25 (false, FormatArg::Auto) => "text".to_string(),
26 }
27 }
28}
29
30#[derive(Debug, Clone, Copy, ValueEnum)]
31pub enum ColorMode {
32 Auto,
33 Always,
34 Never,
35}
36
37impl std::fmt::Display for ColorMode {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 ColorMode::Auto => write!(f, "auto"),
41 ColorMode::Always => write!(f, "always"),
42 ColorMode::Never => write!(f, "never"),
43 }
44 }
45}
46
47#[derive(Parser, Debug)]
49#[command(
50 name = "cw",
51 version,
52 author,
53 about = "🧙📜🪄📖✨ Commit Wizard - A Spellbook for Conventional Commits, Semantic Versioning, and Changelog Automation.",
54 propagate_version = true,
55 arg_required_else_help = true
56)]
57pub struct Cli {
58 #[command(flatten)]
60 pub global: GlobalArgs,
61 #[command(subcommand)]
63 pub command: Command,
64}
65
66#[derive(Debug, Clone, Subcommand)]
67pub enum Command {
68 Add(cmd::add::Args),
70 Bump(cmd::bump::Args),
72 Check(cmd::check::Args),
74 Commit(cmd::commit::Args),
76 Config(cmd::config::Args),
78 Doctor(cmd::doctor::Args),
80 Init(cmd::init::Args),
82 Push(cmd::push::Args),
84 Tag(cmd::tag::Args),
86}
87
88#[derive(Debug, Clone, Args)]
89pub struct GlobalArgs {
90 #[arg(short = 'v', long = "verbose", action = ArgAction::Count, global = true)]
92 pub verbose: u8,
93 #[arg(short = 'q', long = "quiet", action = ArgAction::Count, global = true)]
95 pub quiet: u8,
96 #[arg(long, global = true)]
98 pub json: bool,
99 #[arg(long, global = true, default_value_t = FormatArg::Auto, value_enum, conflicts_with = "plain")]
101 pub format: FormatArg,
102 #[arg(long, short = 'p', global = true, conflicts_with = "format")]
104 pub plain: bool,
105 #[arg(long, global = true)]
107 pub dry_run: bool,
108 #[arg(long, value_enum, default_value_t = ColorMode::Auto, global = true)]
110 pub color: ColorMode,
111 #[arg(short = 'C', long = "cwd", global = true, default_value = ".")]
113 pub cwd: PathBuf,
114 #[arg(long, global = true, conflicts_with = "non_interactive")]
116 pub ci: bool,
117 #[arg(long, global = true, conflicts_with = "ci")]
119 pub non_interactive: bool,
120 #[arg(long, short = 'y', global = true)]
122 pub yes: bool,
123 #[arg(long, global = true)]
125 pub force: bool,
126 #[arg(long, global = true)]
128 pub config: Option<PathBuf>,
129 #[arg(long, global = true)]
131 pub registry: Option<String>,
132 #[arg(long = "registry-ref", global = true)]
134 pub registry_ref: Option<String>,
135 #[arg(long = "registry-section", global = true)]
137 pub registry_section: Option<String>,
138}
139
140impl From<GlobalArgs> for AppContextArgs {
141 fn from(args: GlobalArgs) -> Self {
142 Self {
143 verbose: args.verbose,
144 quiet: args.quiet,
145 json: args.json,
146 format: if args.plain {
147 "plain".to_string()
148 } else {
149 args.format.to_output_format_string(args.json)
150 },
151 dry_run: args.dry_run,
152 output_color: args.color.to_string(),
153 cwd: args.cwd,
154 ci: args.ci,
155 non_interactive: args.non_interactive,
156 auto_yes: args.yes,
157 force: args.force,
158 config_path: args.config,
159 registry: args.registry,
160 registry_ref: args.registry_ref,
161 registry_section: args.registry_section,
162 }
163 }
164}