gcop_rs/cli.rs
1use clap::{Args, Parser, Subcommand, builder::styling};
2
3const STYLES: styling::Styles = styling::Styles::styled()
4 .header(styling::AnsiColor::Green.on_default().bold())
5 .usage(styling::AnsiColor::Green.on_default().bold())
6 .literal(styling::AnsiColor::Cyan.on_default().bold())
7 .placeholder(styling::AnsiColor::Cyan.on_default());
8
9#[derive(Parser)]
10#[command(name = "gcop-rs")]
11#[command(author, version, long_about = None)]
12#[command(styles = STYLES)]
13/// Top-level CLI options shared by all subcommands.
14pub struct Cli {
15 /// Selected subcommand and its arguments.
16 #[command(subcommand)]
17 pub command: Commands,
18
19 /// Enable verbose output.
20 #[arg(short, long, global = true)]
21 pub verbose: bool,
22
23 /// Override the default LLM provider (used by `commit` and `review`).
24 #[arg(short, long, global = true)]
25 pub provider: Option<String>,
26}
27
28/// Arguments for the `commit` subcommand.
29#[derive(Args, Debug)]
30pub struct CommitArgs {
31 /// Skip the interactive editor.
32 #[arg(short, long)]
33 pub no_edit: bool,
34
35 /// Skip confirmation before committing.
36 #[arg(short = 'y', long)]
37 pub yes: bool,
38
39 /// Generate and print a commit message without creating a commit.
40 #[arg(short, long)]
41 pub dry_run: bool,
42
43 /// Output format: `text` or `json` (`json` implies `--dry-run`).
44 #[arg(short, long, default_value = "text")]
45 pub format: String,
46
47 /// Shortcut for `--format json`.
48 #[arg(long)]
49 pub json: bool,
50
51 /// Split staged changes into multiple atomic commits.
52 #[arg(short = 's', long)]
53 pub split: bool,
54
55 /// Amend the last commit with a new AI-generated message.
56 #[arg(long)]
57 pub amend: bool,
58
59 /// Feedback or constraints passed to commit message generation.
60 #[arg(trailing_var_arg = true)]
61 pub feedback: Vec<String>,
62}
63
64#[derive(Subcommand)]
65/// Supported gcop-rs subcommands.
66pub enum Commands {
67 /// Generate a commit message for staged changes.
68 Commit(CommitArgs),
69
70 /// Review code changes.
71 Review {
72 /// Review target.
73 #[command(subcommand)]
74 target: ReviewTarget,
75
76 /// Output format: `text`, `json`, or `markdown`.
77 #[arg(short, long, default_value = "text")]
78 format: String,
79
80 /// Shortcut for `--format json`.
81 #[arg(long)]
82 json: bool,
83 },
84
85 /// Initialize a configuration file.
86 Init {
87 /// Force overwriting existing config.
88 #[arg(short, long)]
89 force: bool,
90
91 /// Initialize `.gcop/config.toml` at the current repository root.
92 #[arg(long)]
93 project: bool,
94 },
95
96 /// Manage configuration.
97 Config {
98 /// Optional configuration action. If omitted, defaults to interactive edit flow.
99 #[command(subcommand)]
100 action: Option<ConfigAction>,
101 },
102
103 /// Manage Git aliases.
104 Alias {
105 /// Force overwriting existing aliases.
106 #[arg(short, long)]
107 force: bool,
108
109 /// List all available aliases and their status.
110 #[arg(short, long)]
111 list: bool,
112
113 /// Remove all gcop-related aliases.
114 #[arg(short, long)]
115 remove: bool,
116 },
117
118 /// Show repository statistics.
119 Stats {
120 /// Output format: `text`, `json`, or `markdown`.
121 #[arg(short, long, default_value = "text")]
122 format: String,
123
124 /// Shortcut for `--format json`.
125 #[arg(long)]
126 json: bool,
127
128 /// Filter by author name or email.
129 #[arg(long)]
130 author: Option<String>,
131
132 /// Show per-author line-level contribution statistics.
133 #[arg(long)]
134 contrib: bool,
135 },
136
137 /// Manage git hooks (prepare-commit-msg)
138 Hook {
139 /// Hook action to run.
140 #[command(subcommand)]
141 action: HookAction,
142 },
143}
144
145#[derive(Subcommand, Debug)]
146/// Target scope for the `review` command.
147pub enum ReviewTarget {
148 /// Review unstaged working tree changes (`index -> workdir`).
149 Changes,
150
151 /// Review a specific commit.
152 Commit {
153 /// Commit hash.
154 hash: String,
155 },
156
157 /// Review a range of commits.
158 Range {
159 /// Commit range (for example `main..feature`).
160 range: String,
161 },
162
163 /// Review a specific file.
164 File {
165 /// Path to file.
166 path: String,
167 },
168}
169
170#[derive(Subcommand)]
171/// Actions for the `config` command.
172pub enum ConfigAction {
173 /// Edit the user config file with syntax/schema checks.
174 Edit,
175
176 /// Validate merged config and test provider-chain connectivity.
177 Validate,
178}
179
180#[derive(Subcommand)]
181/// Actions for the `hook` command.
182pub enum HookAction {
183 /// Install the `prepare-commit-msg` hook in the current repository.
184 Install {
185 /// Force overwriting an existing hook.
186 #[arg(short, long)]
187 force: bool,
188 },
189
190 /// Uninstall the `prepare-commit-msg` hook from the current repository.
191 Uninstall,
192
193 /// Run hook logic (called by Git, not intended for direct use).
194 #[command(hide = true)]
195 Run {
196 /// Path to the commit message file (provided by Git).
197 commit_msg_file: String,
198
199 /// Source of the commit message.
200 #[arg(default_value = "")]
201 source: String,
202
203 /// Commit SHA (for amend).
204 #[arg(default_value = "")]
205 sha: String,
206 },
207}