use clap::{Args, Parser, Subcommand, ValueEnum};
#[derive(ValueEnum, Clone, Default, PartialEq, Debug)]
pub(crate) enum OutputFormat {
#[default]
Text,
Json,
}
#[derive(Parser)]
#[command(name = "commit-check")]
#[command(about = "A CLI tool for validating Conventional Commits")]
#[command(version = "0.1.0")]
#[command(author = "Your Name <your.email@example.com>")]
pub(crate) struct Cli {
#[command(subcommand)]
pub(crate) command: Option<Commands>,
#[arg(short, long)]
pub(crate) message: Option<String>,
#[arg(long, value_name = "BOOL")]
pub(crate) allow_custom_types: Option<bool>,
#[arg(long, value_name = "N")]
pub(crate) max_length: Option<usize>,
#[arg(long, value_name = "N")]
pub(crate) min_length: Option<usize>,
#[arg(long, value_name = "BOOL")]
pub(crate) enforce_lowercase: Option<bool>,
#[arg(long, value_name = "BOOL")]
pub(crate) disallow_period: Option<bool>,
#[arg(short, long)]
pub(crate) verbose: bool,
#[arg(long)]
pub(crate) fix: bool,
#[arg(long, value_name = "SCOPES")]
pub(crate) scopes: Option<String>,
#[arg(long, value_name = "BOOL")]
pub(crate) enforce_lowercase_scope: Option<bool>,
#[arg(long, value_name = "BOOL")]
pub(crate) require_scope: Option<bool>,
#[arg(long, value_name = "PATTERN")]
pub(crate) issue_pattern: Option<String>,
#[arg(long, value_name = "PREFIX", action = clap::ArgAction::Append)]
pub(crate) clean_starts_with: Vec<String>,
#[arg(long, value_name = "PATTERN", action = clap::ArgAction::Append)]
pub(crate) clean_regex: Vec<String>,
#[arg(long, value_enum, default_value = "text")]
pub(crate) format: OutputFormat,
#[arg(long, value_delimiter = ',')]
pub(crate) types: Option<Vec<String>>,
}
#[derive(Subcommand)]
pub(crate) enum Commands {
Validate(ValidateArgs),
Examples,
Types,
InstallHook(InstallHookArgs),
}
#[derive(Args)]
pub(crate) struct InstallHookArgs {
#[arg(long)]
pub(crate) force: bool,
#[arg(long, value_name = "ARGS")]
pub(crate) hook_args: Option<String>,
}
#[derive(Args)]
pub(crate) struct ValidateArgs {
pub(crate) message: Option<String>,
}
pub(crate) fn show_examples() {
println!("Examples of valid Conventional Commits:");
println!();
println!("Basic commits:");
println!(" feat: add user registration");
println!(" fix: resolve memory leak in parser");
println!(" docs: update installation guide");
println!(" style: format code with prettier");
println!(" refactor: extract validation logic");
println!(" test: add unit tests for auth module");
println!(" chore: update dependencies");
println!();
println!("With scope:");
println!(" feat(auth): implement OAuth2 flow");
println!(" fix(parser): handle edge case in tokenizer");
println!(" docs(api): add endpoint documentation");
println!();
println!("Breaking changes:");
println!(" feat!: change API response format");
println!(" feat: add new feature");
println!(" ");
println!(" BREAKING CHANGE: API response format has changed");
println!();
println!("With body and footer:");
println!(" fix: prevent racing of requests");
println!(" ");
println!(" Introduce a request id and a reference to latest request. Dismiss");
println!(" incoming responses other than from latest request.");
println!(" ");
println!(" Remove timeouts which were used to mitigate the racing issue but are");
println!(" obsolete now.");
println!(" ");
println!(" Reviewed-by: Z");
println!(" Refs: #123");
}
pub(crate) fn show_types() {
println!("Standard Conventional Commit types:");
println!();
println!(" feat - A new feature");
println!(" fix - A bug fix");
println!(" docs - Documentation only changes");
println!(" style - Changes that do not affect the meaning of the code");
println!(" refactor - A code change that neither fixes a bug nor adds a feature");
println!(" perf - A code change that improves performance");
println!(" test - Adding missing tests or correcting existing tests");
println!(" build - Changes to the build process or auxiliary tools");
println!(" ci - Changes to CI configuration files and scripts");
println!(" chore - Other changes that don't modify src or test files");
println!(" revert - Reverts a previous commit");
println!();
println!("Custom types are not allowed by default.");
println!("Use --allowed-types=feat,fix,custom to restrict to wanted types only.");
}
pub(crate) fn show_help_hint() {
println!();
println!("For examples of valid commits, run: commit-check examples");
println!("For information about commit types, run: commit-check types");
}