250 lines
7.5 KiB
Rust
250 lines
7.5 KiB
Rust
use clap::{Parser, Subcommand};
|
|
use colored::*;
|
|
use anyhow::Result;
|
|
use anvil::version::ANVIL_VERSION;
|
|
|
|
mod commands {
|
|
pub use anvil::commands::*;
|
|
}
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "anvil")]
|
|
#[command(author = "Eric Ratliff <eric@nxlearn.net>")]
|
|
#[command(version = ANVIL_VERSION)]
|
|
#[command(
|
|
about = "Arduino project generator and build tool - forges clean embedded projects",
|
|
long_about = None
|
|
)]
|
|
struct Cli {
|
|
#[command(subcommand)]
|
|
command: Commands,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
enum Commands {
|
|
/// Create a new Arduino project
|
|
New {
|
|
/// Project name
|
|
name: Option<String>,
|
|
|
|
/// Template to use (basic)
|
|
#[arg(long, short = 't', value_name = "TEMPLATE")]
|
|
template: Option<String>,
|
|
|
|
/// Board preset (uno, mega, nano, leonardo, micro)
|
|
#[arg(long, short = 'b', value_name = "BOARD")]
|
|
board: Option<String>,
|
|
|
|
/// List available templates
|
|
#[arg(long, conflicts_with = "name")]
|
|
list_templates: bool,
|
|
|
|
/// List available board presets
|
|
#[arg(long, conflicts_with = "name")]
|
|
list_boards: bool,
|
|
},
|
|
|
|
/// Check system health and diagnose issues
|
|
Doctor {
|
|
/// Automatically install missing tools
|
|
#[arg(long)]
|
|
fix: bool,
|
|
},
|
|
|
|
/// Install arduino-cli and required cores
|
|
Setup,
|
|
|
|
/// List connected boards and serial ports
|
|
Devices {
|
|
/// Save a port to .anvil.local for this project
|
|
#[arg(long, conflicts_with_all = ["get", "clear"])]
|
|
set: bool,
|
|
|
|
/// Show the saved port for this project
|
|
#[arg(long, conflicts_with_all = ["set", "clear"])]
|
|
get: bool,
|
|
|
|
/// Remove .anvil.local (revert to auto-detect)
|
|
#[arg(long, conflicts_with_all = ["set", "get"])]
|
|
clear: bool,
|
|
|
|
/// Port name (e.g. COM3, /dev/ttyUSB0). Auto-detects if omitted with --set.
|
|
port_or_dir: Option<String>,
|
|
|
|
/// Path to project directory (defaults to current directory)
|
|
#[arg(long, short = 'd', value_name = "DIR")]
|
|
dir: Option<String>,
|
|
},
|
|
|
|
/// Update project scripts to the latest version
|
|
Refresh {
|
|
/// Path to project directory (defaults to current directory)
|
|
dir: Option<String>,
|
|
|
|
/// Overwrite scripts even if they have been modified
|
|
#[arg(long)]
|
|
force: bool,
|
|
},
|
|
|
|
/// Manage board profiles in .anvil.toml
|
|
Board {
|
|
/// Board name (e.g. mega, nano)
|
|
name: Option<String>,
|
|
|
|
/// Add a board to the project
|
|
#[arg(long, conflicts_with_all = ["remove", "listall", "default"])]
|
|
add: bool,
|
|
|
|
/// Remove a board from the project
|
|
#[arg(long, conflicts_with_all = ["add", "listall", "default"])]
|
|
remove: bool,
|
|
|
|
/// Set the default board
|
|
#[arg(long, conflicts_with_all = ["add", "remove", "listall"])]
|
|
default: bool,
|
|
|
|
/// Browse all available boards
|
|
#[arg(long, conflicts_with_all = ["add", "remove", "default"])]
|
|
listall: bool,
|
|
|
|
/// Board identifier (from anvil board --listall)
|
|
#[arg(long, value_name = "ID")]
|
|
id: Option<String>,
|
|
|
|
/// Baud rate override
|
|
#[arg(long, value_name = "RATE")]
|
|
baud: Option<u32>,
|
|
|
|
/// Path to project directory (defaults to current directory)
|
|
#[arg(long, short = 'd', value_name = "DIR")]
|
|
dir: Option<String>,
|
|
},
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
#[cfg(windows)]
|
|
colored::control::set_virtual_terminal(true).ok();
|
|
|
|
let cli = Cli::parse();
|
|
|
|
print_banner();
|
|
|
|
match cli.command {
|
|
Commands::New { name, template, board, list_templates, list_boards } => {
|
|
if list_boards {
|
|
commands::new::list_boards()
|
|
} else if list_templates {
|
|
commands::new::list_templates()
|
|
} else if let Some(project_name) = name {
|
|
commands::new::create_project(
|
|
&project_name,
|
|
template.as_deref(),
|
|
board.as_deref(),
|
|
)
|
|
} else {
|
|
anyhow::bail!(
|
|
"Project name required.\n\
|
|
Usage: anvil new <name>\n\
|
|
Usage: anvil new <name> --board mega\n\
|
|
List boards: anvil new --list-boards\n\
|
|
List templates: anvil new --list-templates"
|
|
);
|
|
}
|
|
}
|
|
Commands::Doctor { fix } => {
|
|
commands::doctor::run_diagnostics(fix)
|
|
}
|
|
Commands::Setup => {
|
|
commands::setup::run_setup()
|
|
}
|
|
Commands::Devices { set, get, clear, port_or_dir, dir } => {
|
|
if set {
|
|
commands::devices::set_port(
|
|
port_or_dir.as_deref(),
|
|
dir.as_deref(),
|
|
)
|
|
} else if get {
|
|
commands::devices::get_port(
|
|
dir.as_deref().or(port_or_dir.as_deref()),
|
|
)
|
|
} else if clear {
|
|
commands::devices::clear_port(
|
|
dir.as_deref().or(port_or_dir.as_deref()),
|
|
)
|
|
} else {
|
|
commands::devices::scan_devices()
|
|
}
|
|
}
|
|
Commands::Refresh { dir, force } => {
|
|
commands::refresh::run_refresh(
|
|
dir.as_deref(),
|
|
force,
|
|
)
|
|
}
|
|
Commands::Board { name, add, remove, default, listall, id, baud, dir } => {
|
|
if listall {
|
|
commands::board::listall_boards(name.as_deref())
|
|
} else if add {
|
|
let board_name = name.as_deref().ok_or_else(|| {
|
|
anyhow::anyhow!(
|
|
"Board name required.\n\
|
|
Usage: anvil board --add mega\n\
|
|
Browse available boards: anvil board --listall"
|
|
)
|
|
})?;
|
|
commands::board::add_board(
|
|
board_name,
|
|
id.as_deref(),
|
|
baud,
|
|
dir.as_deref(),
|
|
)
|
|
} else if remove {
|
|
let board_name = name.as_deref().ok_or_else(|| {
|
|
anyhow::anyhow!(
|
|
"Board name required.\n\
|
|
Usage: anvil board --remove mega"
|
|
)
|
|
})?;
|
|
commands::board::remove_board(
|
|
board_name,
|
|
dir.as_deref(),
|
|
)
|
|
} else if default {
|
|
let board_name = name.as_deref().ok_or_else(|| {
|
|
anyhow::anyhow!(
|
|
"Board name required.\n\
|
|
Usage: anvil board --default uno\n\
|
|
List boards: anvil board"
|
|
)
|
|
})?;
|
|
commands::board::set_default_board(
|
|
board_name,
|
|
dir.as_deref(),
|
|
)
|
|
} else {
|
|
commands::board::list_boards(dir.as_deref())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn print_banner() {
|
|
println!(
|
|
"{}",
|
|
"================================================================"
|
|
.bright_cyan()
|
|
);
|
|
println!(
|
|
"{}",
|
|
format!(" Anvil - Arduino Build Tool v{}", ANVIL_VERSION)
|
|
.bright_cyan()
|
|
.bold()
|
|
);
|
|
println!("{}", " Nexus Workshops LLC".bright_cyan());
|
|
println!(
|
|
"{}",
|
|
"================================================================"
|
|
.bright_cyan()
|
|
);
|
|
println!();
|
|
} |