use clap::{Args, Parser, Subcommand};
use std::ffi::OsString;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
#[derive(Parser)]
#[command(
version,
about,
arg_required_else_help(true),
args_conflicts_with_subcommands(true),
subcommand_negates_reqs(true)
)]
pub struct Cli {
#[arg(
short,
long,
required(true),
value_name = "FILE",
env = "CLAPTRAP_SPEC"
)]
pub spec: Option<PathBuf>,
#[arg(long, value_name = "FORMAT", env = "CLAPTRAP_SPEC_FORMAT", default_value_t = SpecFormat::Auto)]
pub spec_format: SpecFormat,
#[arg(long)]
pub show_panic: bool,
#[command(subcommand)]
pub command: Option<SubCommand>,
#[arg(last = true)]
pub args: Vec<OsString>,
}
#[derive(Subcommand)]
pub enum SubCommand {
Completion {
#[command(flatten)]
spec: SpecInfo,
#[arg(value_enum)]
shell: clap_complete::Shell,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
},
Man {
#[command(flatten)]
spec: SpecInfo,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
},
Script {
#[command(flatten)]
spec: SpecInfo,
#[arg(value_enum)]
shell: Shell,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
},
Doc {
#[command(flatten)]
spec: SpecInfo,
#[arg(value_enum, short = 'f', long, default_value_t = DocFormat::Markdown)]
format: DocFormat,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
},
Schema {
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
},
}
#[derive(Args, Debug, Clone)]
pub struct SpecInfo {
#[arg(short, long, value_name = "FILE", env = "CLAPTRAP_SPEC")]
pub spec: PathBuf,
#[arg(long, value_name = "FORMAT", env = "CLAPTRAP_SPEC_FORMAT", default_value_t = SpecFormat::Auto)]
pub spec_format: SpecFormat,
}
#[derive(clap::ValueEnum, Debug, Clone)]
#[non_exhaustive]
pub enum Shell {
Bash,
Fish,
#[expect(clippy::enum_variant_names)]
PowerShell,
Zsh,
}
#[derive(clap::ValueEnum, Debug, Copy, Clone, Default)]
#[non_exhaustive]
pub enum SpecFormat {
#[default]
Auto,
Json,
Yaml,
Toml,
}
impl Display for SpecFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Auto => write!(f, "auto"),
Self::Json => write!(f, "json"),
Self::Yaml => write!(f, "yaml"),
Self::Toml => write!(f, "toml"),
}
}
}
#[derive(clap::ValueEnum, Debug, Copy, Clone, Default)]
#[non_exhaustive]
pub enum DocFormat {
#[default]
Markdown,
}
impl Display for DocFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Markdown => write!(f, "markdown"),
}
}
}