use clap::{Parser, Subcommand}; use colored::*; use anyhow::Result; use weevil::version::WEEVIL_VERSION; mod commands; mod sdk; mod project; mod templates; use sdk::proxy::ProxyConfig; #[derive(Parser)] #[command(name = "weevil")] #[command(author = "Eric Ratliff ")] #[command(version = WEEVIL_VERSION)] #[command( about = "FTC robotics project generator - bores into complexity, emerges with clean code", long_about = None )] struct Cli { /// Use this HTTP/HTTPS proxy for all downloads #[arg(long, value_name = "URL", global = true)] proxy: Option, /// Skip proxy entirely — go direct even if HTTPS_PROXY is set #[arg(long, global = true)] no_proxy: bool, #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { /// Create a new FTC robot project New { /// Name of the robot project name: Option, /// Path to FTC SDK (optional, will auto-detect or download) #[arg(long)] ftc_sdk: Option, /// Path to Android SDK (optional, will auto-detect or download) #[arg(long)] android_sdk: Option, /// Template to use (basic, testing) #[arg(long, short = 't', value_name = "TEMPLATE")] template: Option, /// List available templates #[arg(long, conflicts_with = "name")] list_templates: bool, }, /// Check system health and diagnose issues Doctor, /// Setup development environment (system or project) Setup { /// Path to project directory (optional - without it, sets up system) path: Option, }, /// Remove Weevil-installed SDKs and dependencies Uninstall { /// Show what would be removed without actually removing anything #[arg(long)] dry_run: bool, /// Remove only specific items by number (use --dry-run first to see the list) #[arg(long, value_name = "NUM", num_args = 1..)] only: Option>, }, /// Upgrade an existing project to the latest generator version Upgrade { /// Path to the project directory path: String, }, /// Build and deploy project to Control Hub Deploy { /// Path to the project directory path: String, /// Force USB connection #[arg(long)] usb: bool, /// Force WiFi connection #[arg(long)] wifi: bool, /// Custom IP address #[arg(short, long)] ip: Option, }, /// Manage SDKs (FTC and Android) Sdk { #[command(subcommand)] command: SdkCommands, }, /// Show or update project configuration Config { /// Path to the project directory path: String, /// Set FTC SDK path for this project #[arg(long, value_name = "PATH")] set_sdk: Option, }, } #[derive(Subcommand)] enum SdkCommands { /// Install required SDKs Install, /// Show SDK status and locations Status, /// Update SDKs to latest versions Update, } fn main() -> Result<()> { // Enable colors on Windows #[cfg(windows)] colored::control::set_virtual_terminal(true).ok(); let cli = Cli::parse(); print_banner(); // Resolve proxy once at the top — every network-touching command uses it. let proxy = ProxyConfig::resolve(cli.proxy.as_deref(), cli.no_proxy)?; match cli.command { Commands::New { name, ftc_sdk, android_sdk, template, list_templates } => { if list_templates { commands::new::list_templates() } else if let Some(project_name) = name { commands::new::create_project( &project_name, ftc_sdk.as_deref(), android_sdk.as_deref(), template.as_deref(), &proxy ) } else { anyhow::bail!("Project name is required. Use --list-templates to see available templates."); } } Commands::Doctor => { commands::doctor::run_diagnostics() } Commands::Setup { path } => { commands::setup::setup_environment(path.as_deref(), &proxy) } Commands::Uninstall { dry_run, only } => { commands::uninstall::uninstall_dependencies(dry_run, only) } Commands::Upgrade { path } => { commands::upgrade::upgrade_project(&path) } Commands::Deploy { path, usb, wifi, ip } => { commands::deploy::deploy_project(&path, usb, wifi, ip.as_deref()) } Commands::Sdk { command } => match command { SdkCommands::Install => commands::sdk::install_sdks(&proxy), SdkCommands::Status => commands::sdk::show_status(), SdkCommands::Update => commands::sdk::update_sdks(&proxy), }, Commands::Config { path, set_sdk } => { if let Some(sdk_path) = set_sdk { commands::config::set_sdk(&path, &sdk_path) } else { commands::config::show_config(&path) } } } } fn print_banner() { println!("{}", "═══════════════════════════════════════════════════════════".bright_cyan()); println!( "{}", format!(" 🪲 Weevil - FTC Project Generator v{}", WEEVIL_VERSION) .bright_cyan() .bold() ); println!("{}", " Nexus Workshops LLC".bright_cyan()); println!("{}", "═══════════════════════════════════════════════════════════".bright_cyan()); println!(); }