use clish::help::{AppStyle, AppStyles};
use clish::prelude::*;
#[command(
name = "create",
aliases = ["init", "scaffold"],
param(name, help = "Project name", placeholder = "NAME"),
param(description, help = "Short project description"),
param(template, help = "Template to use", short = 't', placeholder = "TMPL", default = "default"),
param(tags, help = "Tags to apply (repeatable)", short = 'T'),
param(force, help = "Overwrite existing directory", short = 'f'),
param(git_init, help = "Initialize git repository", name = "git", short = 'g')
)]
fn create_project(
name: Pos<String>,
description: Pos<Option<String>>,
template: Named<String>,
tags: Named<Vec<String>>,
force: bool,
git_init: bool,
) {
println!("Creating project '{}'", name);
if let Some(desc) = description {
println!(" Description: {}", desc);
}
println!(" Template: {}", template);
if !tags.is_empty() {
println!(" Tags: {}", tags.join(", "));
}
if force {
println!(" (force: will overwrite existing)");
}
if git_init {
println!(" Initializing git repository");
}
}
#[command(
param(target, help = "Test target", short = 't', placeholder = "TARGET", default = "all"),
param(format, help = "Output format", short = 'f', choices = ["pretty", "terse", "json"], default = "pretty"),
param(jobs, help = "Number of parallel jobs", short = 'j', placeholder = "N"),
param(coverage, help = "Generate coverage report", short = 'c'),
param(verbose, help = "Verbose output", short = 'v'),
param(filter, help = "Filter tests by name pattern", hide = true)
)]
fn test(
target: Named<String>,
format: Named<String>,
jobs: Named<Option<u16>>,
coverage: bool,
verbose: bool,
filter: Named<Option<String>>,
) {
println!("Running tests for target: {}", target);
println!(" Format: {}", format);
if let Some(j) = jobs {
println!(" Parallel jobs: {}", j);
}
if coverage {
println!(" Coverage report enabled");
}
if verbose {
println!(" Verbose mode");
}
if let Some(f) = filter {
println!(" Filter: {}", f);
}
}
#[command(
deprecated = true,
deprecation_note = "use 'deploy' instead",
param(channel, help = "Release channel", short = 'c', placeholder = "CHANNEL", choices = ["stable", "beta", "nightly"], default = "stable"),
param(dry_run, help = "Validate without publishing", name = "dry-run", short = 'n'),
param(sign, help = "Sign the release", short = 's'),
param(skip_checks, help = "Skip pre-flight checks", name = "skip-checks"),
param(verify, help = "Verify integrity after publish", short = 'V', requires = ["dry_run"])
)]
fn publish(channel: Named<String>, dry_run: bool, sign: bool, skip_checks: bool, verify: bool) {
println!("Publishing to channel: {}", channel);
if dry_run {
println!(" (dry run — no changes made)");
return;
}
if sign {
println!(" Signing release");
}
if skip_checks {
println!(" (skipping pre-flight checks)");
}
if verify {
println!(" Verifying integrity");
}
println!(" Release published!");
}
#[command(
hidden = true,
param(all, help = "Remove all artifacts", short = 'a'),
param(path, help = "Target path for selective cleanup", hide = true),
param(
dry_run,
help = "Print what would be removed",
name = "dry-run",
short = 'n'
)
)]
fn clean(all: bool, path: Pos<Option<String>>, dry_run: bool) {
if dry_run {
if all {
println!("Would remove all artifacts");
} else if let Some(p) = path {
println!("Would clean: {}", p);
}
return;
}
if all {
println!("Removing all artifacts");
} else if let Some(p) = path {
println!("Cleaning: {}", p);
} else {
println!("Nothing to clean (use --all or specify a path)");
}
}
#[command(
help = "Search indexed projects",
details = "Searches through all registered projects in the local index.\nResults are ranked by relevance score.",
param(query, help = "Search terms (variadic)", placeholder = "TERM"),
param(
limit,
help = "Maximum results",
short = 'n',
placeholder = "NUM",
env = "CLISH_SEARCH_LIMIT"
),
param(json, help = "Output as JSON", short = 'j')
)]
fn search(query: Pos<Vec<String>>, limit: Named<Option<u32>>, json: bool) {
let limit = limit.unwrap_or(10);
println!("Searching for: {}", query.join(" "));
println!(" Limit: {}", limit);
if json {
println!(" Output: JSON");
}
for (i, term) in query.iter().enumerate() {
if i as u32 >= limit {
break;
}
println!(" [{}/{}] Results for '{}'", i + 1, limit, term);
}
}
fn main() {
app!()
.name("rigen")
.version("2.1.0")
.description("Project lifecycle toolkit")
.details("Rigen is a full-featured CLI for managing project scaffolds,\nrunning tests, publishing releases, and indexing the project catalog.")
.styles(AppStyles {
header: AppStyle::Markup("[bold cyan underline]"),
brand: AppStyle::Markup("[bold magenta]"),
..Default::default()
})
.run();
}