use crate::schema::Kind;
use clap::{Args, Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
#[derive(Parser)]
#[command(
version,
about = "Control in-repo YAML work queues",
arg_required_else_help = true
)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand)]
pub enum Command {
Init(InitArgs),
Status(LedgerArgs),
Check(CheckArgs),
Add(Box<AddArgs>),
Start(IdArgs),
Archive(ArchiveArgs),
Park(ParkArgs),
Promote(PromoteArgs),
Show(IdArgs),
Fmt(FmtArgs),
Schema(SchemaArgs),
Instructions,
}
#[derive(Args)]
pub struct FmtArgs {
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(long)]
pub check: bool,
}
#[derive(Args)]
pub struct SchemaArgs {
#[arg(short = 'o', long, value_hint = clap::ValueHint::FilePath)]
pub out: Option<PathBuf>,
}
#[derive(Args, Clone)]
pub struct CheckArgs {
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(long)]
pub no_git: bool,
}
#[derive(Args, Clone)]
pub struct LedgerArgs {
#[arg(short = 'f', long, value_hint = clap::ValueHint::FilePath)]
pub file: Option<PathBuf>,
}
#[derive(Args)]
pub struct InitArgs {
#[arg(short = 'p', long)]
pub prefix: String,
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(long)]
pub force: bool,
}
#[derive(Args)]
pub struct AddArgs {
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(short = 't', long)]
pub title: String,
#[arg(short = 's', long)]
pub scope: String,
#[arg(short = 'o', long)]
pub outcome: String,
#[arg(short = 'a', long = "acceptance", required_unless_present = "horizon")]
pub acceptance: Vec<String>,
#[arg(long)]
pub patch: Option<String>,
#[arg(long)]
pub notes: Option<String>,
#[arg(long = "blocked-by")]
pub blocked_by: Vec<String>,
#[arg(long)]
pub plan: Option<String>,
#[arg(long = "link")]
pub links: Vec<String>,
#[arg(long, conflicts_with_all = ["before", "horizon"])]
pub after: Option<String>,
#[arg(long, conflicts_with_all = ["after", "horizon"])]
pub before: Option<String>,
#[arg(long, requires_all = ["kind", "open"])]
pub horizon: bool,
#[arg(long, value_parser = parse_kind)]
pub kind: Option<Kind>,
#[arg(long)]
pub open: Option<String>,
}
fn parse_kind(raw: &str) -> Result<Kind, String> {
match raw {
"research" => Ok(Kind::Research),
"evaluation" => Ok(Kind::Evaluation),
"deferred" => Ok(Kind::Deferred),
other => Err(format!(
"kind must be research, evaluation, or deferred (got {other})"
)),
}
}
#[derive(Args)]
pub struct IdArgs {
pub id: String,
#[command(flatten)]
pub ledger: LedgerArgs,
}
#[derive(Args)]
pub struct ArchiveArgs {
pub id: String,
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(short = 'e', long = "evidence", required = true)]
pub evidence: Vec<String>,
#[arg(long, value_enum, default_value = "completed")]
pub disposition: Disposition,
}
#[derive(Args)]
pub struct ParkArgs {
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(short = 't', long)]
pub title: String,
#[arg(short = 's', long)]
pub scope: String,
#[arg(short = 'o', long)]
pub outcome: String,
#[arg(long, value_parser = parse_kind)]
pub kind: Kind,
#[arg(long)]
pub open: String,
#[arg(long)]
pub notes: Option<String>,
#[arg(long)]
pub plan: Option<String>,
#[arg(long = "link")]
pub links: Vec<String>,
#[arg(long)]
pub patch: Option<String>,
}
#[derive(Args)]
pub struct PromoteArgs {
pub id: String,
#[command(flatten)]
pub ledger: LedgerArgs,
#[arg(short = 'a', long = "acceptance", required = true)]
pub acceptance: Vec<String>,
#[arg(long = "blocked-by")]
pub blocked_by: Vec<String>,
}
#[derive(Clone, Copy, ValueEnum)]
pub enum Disposition {
Completed,
Dropped,
}
impl Disposition {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Completed => "completed",
Self::Dropped => "dropped",
}
}
}