feat: Add template system to weevil new command

Implements template-based project creation allowing teams to start with
professional example code instead of empty projects.

Features:
- Two templates: 'basic' (minimal) and 'testing' (45-test showcase)
- Template variable substitution ({{PROJECT_NAME}}, etc.)
- Template validation with helpful error messages
- `weevil new --list-templates` command
- Template files embedded in binary at compile time

Technical details:
- Templates stored in templates/basic/ and templates/testing/
- Files ending in .template have variables replaced
- Uses include_dir! macro to embed templates in binary
- Returns file count for user feedback

Testing template includes:
- 3 complete subsystems (MotorCycler, WallApproach, TurnController)
- Hardware abstraction layer with mock implementations
- 45 comprehensive tests (unit, integration, system)
- Professional documentation (DESIGN_AND_TEST_PLAN.md, etc.)

Usage:
  weevil new my-robot                    # basic template
  weevil new my-robot --template testing # testing showcase
  weevil new --list-templates            # show available templates

This enables FTC teams to learn from working code and best practices
rather than starting from scratch.
This commit is contained in:
Eric Ratliff
2026-02-02 19:14:50 -06:00
parent 0431425f38
commit 60679e097f
42 changed files with 5521 additions and 82 deletions

View File

@@ -3,12 +3,6 @@ use colored::*;
use anyhow::Result;
use weevil::version::WEEVIL_VERSION;
// Import ProxyConfig through our own `mod sdk`, not through the `weevil`
// library crate. Both re-export the same source, but Rust treats
// `weevil::sdk::proxy::ProxyConfig` and `sdk::proxy::ProxyConfig` as
// distinct types when a binary and its lib are compiled together.
// The command modules already see the local-mod version, so main must match.
mod commands;
mod sdk;
mod project;
@@ -42,7 +36,7 @@ enum Commands {
/// Create a new FTC robot project
New {
/// Name of the robot project
name: String,
name: Option<String>,
/// Path to FTC SDK (optional, will auto-detect or download)
#[arg(long)]
@@ -51,6 +45,14 @@ enum Commands {
/// Path to Android SDK (optional, will auto-detect or download)
#[arg(long)]
android_sdk: Option<String>,
/// Template to use (basic, testing)
#[arg(long, short = 't', value_name = "TEMPLATE")]
template: Option<String>,
/// List available templates
#[arg(long, conflicts_with = "name")]
list_templates: bool,
},
/// Check system health and diagnose issues
@@ -139,8 +141,20 @@ fn main() -> Result<()> {
let proxy = ProxyConfig::resolve(cli.proxy.as_deref(), cli.no_proxy)?;
match cli.command {
Commands::New { name, ftc_sdk, android_sdk } => {
commands::new::create_project(&name, ftc_sdk.as_deref(), android_sdk.as_deref(), &proxy)
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()