use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser, Debug)]
#[command(name = "adrscope")]
#[command(author, version, about, long_about = None)]
pub struct Cli {
#[arg(short, long, global = true)]
pub verbose: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
Generate(GenerateArgs),
Wiki(WikiArgs),
Validate(ValidateArgs),
Stats(StatsArgs),
}
#[derive(Parser, Debug)]
pub struct GenerateArgs {
#[arg(short, long, default_value = "docs/decisions")]
pub input: String,
#[arg(short, long, default_value = "adrs.html")]
pub output: String,
#[arg(short, long, default_value = "Architecture Decision Records")]
pub title: String,
#[arg(long, value_enum, default_value = "auto")]
pub theme: ThemeArg,
#[arg(short, long, default_value = "**/*.md")]
pub pattern: String,
}
#[derive(Parser, Debug)]
pub struct WikiArgs {
#[arg(short, long, default_value = "docs/decisions")]
pub input: String,
#[arg(short, long, default_value = "wiki")]
pub output: String,
#[arg(long)]
pub pages_url: Option<String>,
#[arg(short, long, default_value = "**/*.md")]
pub pattern: String,
}
#[derive(Parser, Debug)]
pub struct ValidateArgs {
#[arg(short, long, default_value = "docs/decisions")]
pub input: String,
#[arg(short, long, default_value = "**/*.md")]
pub pattern: String,
#[arg(long)]
pub strict: bool,
}
#[derive(Parser, Debug)]
pub struct StatsArgs {
#[arg(short, long, default_value = "docs/decisions")]
pub input: String,
#[arg(short, long, default_value = "**/*.md")]
pub pattern: String,
#[arg(short, long, value_enum, default_value = "text")]
pub format: FormatArg,
}
#[derive(ValueEnum, Clone, Debug, Default)]
pub enum ThemeArg {
Light,
Dark,
#[default]
Auto,
}
impl From<ThemeArg> for crate::infrastructure::Theme {
fn from(arg: ThemeArg) -> Self {
match arg {
ThemeArg::Light => Self::Light,
ThemeArg::Dark => Self::Dark,
ThemeArg::Auto => Self::Auto,
}
}
}
#[derive(ValueEnum, Clone, Debug, Default)]
pub enum FormatArg {
#[default]
Text,
Json,
Markdown,
}
impl From<FormatArg> for crate::application::stats::StatsFormat {
fn from(arg: FormatArg) -> Self {
match arg {
FormatArg::Text => Self::Text,
FormatArg::Json => Self::Json,
FormatArg::Markdown => Self::Markdown,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::CommandFactory;
#[test]
fn test_cli_parses() {
Cli::command().debug_assert();
}
#[test]
fn test_generate_defaults() {
let args = GenerateArgs {
input: "docs/decisions".to_string(),
output: "adrs.html".to_string(),
title: "ADRs".to_string(),
theme: ThemeArg::Auto,
pattern: "**/*.md".to_string(),
};
assert_eq!(args.input, "docs/decisions");
assert_eq!(args.output, "adrs.html");
}
#[test]
fn test_theme_conversion() {
use crate::infrastructure::Theme;
assert!(matches!(Theme::from(ThemeArg::Light), Theme::Light));
assert!(matches!(Theme::from(ThemeArg::Dark), Theme::Dark));
assert!(matches!(Theme::from(ThemeArg::Auto), Theme::Auto));
}
#[test]
fn test_format_conversion() {
use crate::application::stats::StatsFormat;
assert!(matches!(
StatsFormat::from(FormatArg::Text),
StatsFormat::Text
));
assert!(matches!(
StatsFormat::from(FormatArg::Json),
StatsFormat::Json
));
assert!(matches!(
StatsFormat::from(FormatArg::Markdown),
StatsFormat::Markdown
));
}
}