use clap::{Parser, Subcommand};
use kick_rs_cli::{generate, new};
use std::path::PathBuf;
use std::process::ExitCode;
#[derive(Parser)]
#[command(
name = "cargo-kick",
bin_name = "cargo kick",
version,
about = "Companion CLI for the kick-rs framework"
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
New {
name: String,
#[arg(long)]
path: Option<PathBuf>,
#[arg(long)]
force: bool,
},
#[command(alias = "g")]
Generate {
#[command(subcommand)]
kind: Generate,
},
}
#[derive(Subcommand)]
enum Generate {
Module {
name: String,
#[arg(long)]
path: Option<PathBuf>,
#[arg(long)]
force: bool,
},
Service {
spec: String,
#[arg(long)]
path: Option<PathBuf>,
#[arg(long)]
force: bool,
},
}
fn main() -> ExitCode {
let argv: Vec<String> = std::env::args()
.enumerate()
.filter(|(i, a)| !(*i == 1 && a == "kick"))
.map(|(_, a)| a)
.collect();
let cli = match Cli::try_parse_from(argv) {
Ok(c) => c,
Err(e) => {
let _ = e.print();
return ExitCode::from(if e.exit_code() == 0 { 0 } else { 2 });
}
};
match cli.command {
Command::New { name, path, force } => {
let args = new::NewArgs { name, path, force };
match new::run(&args) {
Ok(dest) => {
println!("✓ created kick-rs project at {}", dest.display());
println!(" next: cd {} && cargo run", dest.display());
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("error: {e}");
ExitCode::FAILURE
}
}
}
Command::Generate {
kind: Generate::Module { name, path, force },
} => {
let args = generate::GenerateModuleArgs {
name: name.clone(),
project_root: path,
force,
};
match generate::generate_module(&args) {
Ok(dir) => {
println!("✓ generated module at {}", dir.display());
println!(" next: register it in main.rs via");
println!(" .module(modules::{name}::define())");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("error: {e}");
ExitCode::FAILURE
}
}
}
Command::Generate {
kind: Generate::Service { spec, path, force },
} => {
let args = generate::GenerateServiceArgs {
spec: spec.clone(),
project_root: path,
force,
};
match generate::generate_service(&args) {
Ok(file) => {
let (module, service_snake) = spec.split_once('/').unwrap();
let pascal = generate::to_pascal_case(service_snake);
println!("✓ generated service at {}", file.display());
println!(" next: in src/modules/{module}/mod.rs, add");
println!(" use {service_snake}::{pascal};");
println!(" ...");
println!(" .service::<{pascal}>()");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("error: {e}");
ExitCode::FAILURE
}
}
}
}
}