Add board presets, devices --clear, and test/UX fixes
Board presets: - anvil new --board mega (uno, mega, nano, nano-old, leonardo, micro) - anvil new --list-boards shows presets with compatible clones - FQBN and baud rate flow into .anvil.toml via template variables - Defaults to uno when --board is omitted Devices --clear: - anvil devices --clear deletes .anvil.local, reverts to auto-detect
This commit is contained in:
@@ -4,6 +4,8 @@ use serde::Deserialize;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub mod presets;
|
||||||
|
|
||||||
/// Information about a detected serial port.
|
/// Information about a detected serial port.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PortInfo {
|
pub struct PortInfo {
|
||||||
|
|||||||
134
src/board/presets.rs
Normal file
134
src/board/presets.rs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/// Board presets for common Arduino boards.
|
||||||
|
///
|
||||||
|
/// Each preset provides a known-good FQBN and default baud rate.
|
||||||
|
/// Users can always override the FQBN in .anvil.toml after creation.
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BoardPreset {
|
||||||
|
/// Short name used on the command line (e.g. "uno", "mega")
|
||||||
|
pub name: &'static str,
|
||||||
|
/// Fully Qualified Board Name for arduino-cli
|
||||||
|
pub fqbn: &'static str,
|
||||||
|
/// Default serial baud rate
|
||||||
|
pub baud: u32,
|
||||||
|
/// Human-readable description
|
||||||
|
pub description: &'static str,
|
||||||
|
/// Common clones and compatible boards
|
||||||
|
pub also_known_as: &'static str,
|
||||||
|
/// Required core (for display in help text)
|
||||||
|
pub core: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Built-in board presets.
|
||||||
|
///
|
||||||
|
/// Only includes boards whose core is installed by `anvil setup`
|
||||||
|
/// (arduino:avr). Users targeting other platforms can set the FQBN
|
||||||
|
/// manually in .anvil.toml.
|
||||||
|
pub const PRESETS: &[BoardPreset] = &[
|
||||||
|
BoardPreset {
|
||||||
|
name: "uno",
|
||||||
|
fqbn: "arduino:avr:uno",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Uno (ATmega328P)",
|
||||||
|
also_known_as: "SparkFun RedBoard, Elegoo Uno R3, DFRobot DFRduino, SunFounder Uno",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
BoardPreset {
|
||||||
|
name: "mega",
|
||||||
|
fqbn: "arduino:avr:mega:cpu=atmega2560",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Mega 2560",
|
||||||
|
also_known_as: "Elegoo Mega R3, Robotdyn Mega, SunFounder Mega",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
BoardPreset {
|
||||||
|
name: "nano",
|
||||||
|
fqbn: "arduino:avr:nano:cpu=atmega328",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Nano (new bootloader)",
|
||||||
|
also_known_as: "Elegoo Nano, Makerfire Nano V3",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
BoardPreset {
|
||||||
|
name: "nano-old",
|
||||||
|
fqbn: "arduino:avr:nano:cpu=atmega328old",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Nano (old bootloader)",
|
||||||
|
also_known_as: "pre-2018 Nano clones, most cheap Nano boards",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
BoardPreset {
|
||||||
|
name: "leonardo",
|
||||||
|
fqbn: "arduino:avr:leonardo",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Leonardo (ATmega32U4)",
|
||||||
|
also_known_as: "SparkFun Pro Micro (Leonardo mode), Freetronics LeoStick",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
BoardPreset {
|
||||||
|
name: "micro",
|
||||||
|
fqbn: "arduino:avr:micro",
|
||||||
|
baud: 115200,
|
||||||
|
description: "Arduino Micro (ATmega32U4)",
|
||||||
|
also_known_as: "SparkFun Pro Micro, Adafruit ItsyBitsy 32u4",
|
||||||
|
core: "arduino:avr",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Default board used when --board is not specified.
|
||||||
|
pub const DEFAULT_PRESET: &str = "uno";
|
||||||
|
|
||||||
|
/// Look up a board preset by short name (case-insensitive).
|
||||||
|
pub fn find_preset(name: &str) -> Option<&'static BoardPreset> {
|
||||||
|
let lower = name.to_lowercase();
|
||||||
|
PRESETS.iter().find(|p| p.name == lower)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List all preset names for display.
|
||||||
|
pub fn preset_names() -> Vec<&'static str> {
|
||||||
|
PRESETS.iter().map(|p| p.name).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_preset_uno() {
|
||||||
|
let p = find_preset("uno").unwrap();
|
||||||
|
assert_eq!(p.fqbn, "arduino:avr:uno");
|
||||||
|
assert_eq!(p.baud, 115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_preset_case_insensitive() {
|
||||||
|
assert!(find_preset("Mega").is_some());
|
||||||
|
assert!(find_preset("NANO").is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_preset_unknown() {
|
||||||
|
assert!(find_preset("esp32").is_none());
|
||||||
|
assert!(find_preset("stm32").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_preset_exists() {
|
||||||
|
assert!(find_preset(DEFAULT_PRESET).is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all_presets_have_avr_core() {
|
||||||
|
for p in PRESETS {
|
||||||
|
assert_eq!(p.core, "arduino:avr", "{} should use arduino:avr core", p.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preset_names() {
|
||||||
|
let names = preset_names();
|
||||||
|
assert!(names.contains(&"uno"));
|
||||||
|
assert!(names.contains(&"mega"));
|
||||||
|
assert!(names.contains(&"nano"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -274,6 +274,31 @@ pub fn set_port(port: Option<&str>, project_dir: Option<&str>) -> Result<()> {
|
|||||||
|
|
||||||
// -- Helpers --------------------------------------------------------------
|
// -- Helpers --------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Delete .anvil.local from the given project directory.
|
||||||
|
pub fn clear_port(project_dir: Option<&str>) -> Result<()> {
|
||||||
|
let project_path = resolve_project_dir(project_dir)?;
|
||||||
|
require_anvil_project(&project_path)?;
|
||||||
|
|
||||||
|
let local_file = project_path.join(".anvil.local");
|
||||||
|
if !local_file.exists() {
|
||||||
|
println!(
|
||||||
|
"{} No .anvil.local file found -- nothing to clear.",
|
||||||
|
"--".bright_black()
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::remove_file(&local_file)
|
||||||
|
.context("Failed to delete .anvil.local")?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{} Removed .anvil.local -- port will be auto-detected.",
|
||||||
|
"ok".green()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_project_dir(project_dir: Option<&str>) -> Result<PathBuf> {
|
fn resolve_project_dir(project_dir: Option<&str>) -> Result<PathBuf> {
|
||||||
match project_dir {
|
match project_dir {
|
||||||
Some(dir) => Ok(PathBuf::from(dir)),
|
Some(dir) => Ok(PathBuf::from(dir)),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use anyhow::{Result, bail};
|
|||||||
use colored::*;
|
use colored::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::board::presets::{self, BoardPreset};
|
||||||
use crate::templates::{TemplateManager, TemplateContext};
|
use crate::templates::{TemplateManager, TemplateContext};
|
||||||
use crate::version::ANVIL_VERSION;
|
use crate::version::ANVIL_VERSION;
|
||||||
|
|
||||||
@@ -28,7 +29,52 @@ pub fn list_templates() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_project(name: &str, template: Option<&str>) -> Result<()> {
|
pub fn list_boards() -> Result<()> {
|
||||||
|
println!("{}", "Available board presets:".bright_cyan().bold());
|
||||||
|
println!();
|
||||||
|
|
||||||
|
for preset in presets::PRESETS {
|
||||||
|
let marker = if preset.name == presets::DEFAULT_PRESET {
|
||||||
|
" (default)"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
" {}{}",
|
||||||
|
preset.name.bright_white().bold(),
|
||||||
|
marker.bright_cyan()
|
||||||
|
);
|
||||||
|
println!(" {}", preset.description);
|
||||||
|
if !preset.also_known_as.is_empty() {
|
||||||
|
println!(" Also: {}", preset.also_known_as.bright_black());
|
||||||
|
}
|
||||||
|
println!(" FQBN: {}", preset.fqbn.bright_black());
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
" {}",
|
||||||
|
"Usage: anvil new <project-name> --board mega".bright_yellow()
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
println!(
|
||||||
|
" {}",
|
||||||
|
"For boards not listed here, create a project and edit the".bright_black()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
" {}",
|
||||||
|
"fqbn value in .anvil.toml to any valid arduino-cli FQBN.".bright_black()
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_project(
|
||||||
|
name: &str,
|
||||||
|
template: Option<&str>,
|
||||||
|
board: Option<&str>,
|
||||||
|
) -> Result<()> {
|
||||||
// Validate project name
|
// Validate project name
|
||||||
validate_project_name(name)?;
|
validate_project_name(name)?;
|
||||||
|
|
||||||
@@ -52,6 +98,25 @@ pub fn create_project(name: &str, template: Option<&str>) -> Result<()> {
|
|||||||
bail!("Invalid template");
|
bail!("Invalid template");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve board preset
|
||||||
|
let preset: &BoardPreset = match board {
|
||||||
|
Some(b) => {
|
||||||
|
match presets::find_preset(b) {
|
||||||
|
Some(p) => p,
|
||||||
|
None => {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
format!("Unknown board preset: '{}'", b).red().bold()
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
list_boards()?;
|
||||||
|
bail!("Invalid board preset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => presets::find_preset(presets::DEFAULT_PRESET).unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
format!("Creating Arduino project: {}", name)
|
format!("Creating Arduino project: {}", name)
|
||||||
@@ -59,6 +124,14 @@ pub fn create_project(name: &str, template: Option<&str>) -> Result<()> {
|
|||||||
.bold()
|
.bold()
|
||||||
);
|
);
|
||||||
println!("{}", format!("Template: {}", template_name).bright_cyan());
|
println!("{}", format!("Template: {}", template_name).bright_cyan());
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
format!("Board: {} ({})", preset.name, preset.description).bright_cyan()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
format!("FQBN: {}", preset.fqbn).bright_black()
|
||||||
|
);
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
// Create project directory
|
// Create project directory
|
||||||
@@ -69,6 +142,8 @@ pub fn create_project(name: &str, template: Option<&str>) -> Result<()> {
|
|||||||
let context = TemplateContext {
|
let context = TemplateContext {
|
||||||
project_name: name.to_string(),
|
project_name: name.to_string(),
|
||||||
anvil_version: ANVIL_VERSION.to_string(),
|
anvil_version: ANVIL_VERSION.to_string(),
|
||||||
|
fqbn: preset.fqbn.to_string(),
|
||||||
|
baud: preset.baud,
|
||||||
};
|
};
|
||||||
|
|
||||||
let file_count = TemplateManager::extract(template_name, &project_path, &context)?;
|
let file_count = TemplateManager::extract(template_name, &project_path, &context)?;
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ pub fn run_refresh(project_dir: Option<&str>, force: bool) -> Result<()> {
|
|||||||
let context = TemplateContext {
|
let context = TemplateContext {
|
||||||
project_name: config.project.name.clone(),
|
project_name: config.project.name.clone(),
|
||||||
anvil_version: ANVIL_VERSION.to_string(),
|
anvil_version: ANVIL_VERSION.to_string(),
|
||||||
|
fqbn: config.build.fqbn.clone(),
|
||||||
|
baud: config.monitor.baud,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract template into a temp directory so we can compare
|
// Extract template into a temp directory so we can compare
|
||||||
|
|||||||
33
src/main.rs
33
src/main.rs
@@ -31,9 +31,17 @@ enum Commands {
|
|||||||
#[arg(long, short = 't', value_name = "TEMPLATE")]
|
#[arg(long, short = 't', value_name = "TEMPLATE")]
|
||||||
template: Option<String>,
|
template: Option<String>,
|
||||||
|
|
||||||
|
/// Board preset (uno, mega, nano, leonardo, micro)
|
||||||
|
#[arg(long, short = 'b', value_name = "BOARD")]
|
||||||
|
board: Option<String>,
|
||||||
|
|
||||||
/// List available templates
|
/// List available templates
|
||||||
#[arg(long, conflicts_with = "name")]
|
#[arg(long, conflicts_with = "name")]
|
||||||
list_templates: bool,
|
list_templates: bool,
|
||||||
|
|
||||||
|
/// List available board presets
|
||||||
|
#[arg(long, conflicts_with = "name")]
|
||||||
|
list_boards: bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Check system health and diagnose issues
|
/// Check system health and diagnose issues
|
||||||
@@ -45,13 +53,17 @@ enum Commands {
|
|||||||
/// List connected boards and serial ports
|
/// List connected boards and serial ports
|
||||||
Devices {
|
Devices {
|
||||||
/// Save a port to .anvil.local for this project
|
/// Save a port to .anvil.local for this project
|
||||||
#[arg(long, conflicts_with = "get")]
|
#[arg(long, conflicts_with_all = ["get", "clear"])]
|
||||||
set: bool,
|
set: bool,
|
||||||
|
|
||||||
/// Show the saved port for this project
|
/// Show the saved port for this project
|
||||||
#[arg(long, conflicts_with = "set")]
|
#[arg(long, conflicts_with_all = ["set", "clear"])]
|
||||||
get: bool,
|
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 name (e.g. COM3, /dev/ttyUSB0). Auto-detects if omitted with --set.
|
||||||
port_or_dir: Option<String>,
|
port_or_dir: Option<String>,
|
||||||
|
|
||||||
@@ -80,18 +92,23 @@ fn main() -> Result<()> {
|
|||||||
print_banner();
|
print_banner();
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::New { name, template, list_templates } => {
|
Commands::New { name, template, board, list_templates, list_boards } => {
|
||||||
if list_templates {
|
if list_boards {
|
||||||
|
commands::new::list_boards()
|
||||||
|
} else if list_templates {
|
||||||
commands::new::list_templates()
|
commands::new::list_templates()
|
||||||
} else if let Some(project_name) = name {
|
} else if let Some(project_name) = name {
|
||||||
commands::new::create_project(
|
commands::new::create_project(
|
||||||
&project_name,
|
&project_name,
|
||||||
template.as_deref(),
|
template.as_deref(),
|
||||||
|
board.as_deref(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Project name required.\n\
|
"Project name required.\n\
|
||||||
Usage: anvil new <n>\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"
|
List templates: anvil new --list-templates"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -102,7 +119,7 @@ fn main() -> Result<()> {
|
|||||||
Commands::Setup => {
|
Commands::Setup => {
|
||||||
commands::setup::run_setup()
|
commands::setup::run_setup()
|
||||||
}
|
}
|
||||||
Commands::Devices { set, get, port_or_dir, dir } => {
|
Commands::Devices { set, get, clear, port_or_dir, dir } => {
|
||||||
if set {
|
if set {
|
||||||
commands::devices::set_port(
|
commands::devices::set_port(
|
||||||
port_or_dir.as_deref(),
|
port_or_dir.as_deref(),
|
||||||
@@ -112,6 +129,10 @@ fn main() -> Result<()> {
|
|||||||
commands::devices::get_port(
|
commands::devices::get_port(
|
||||||
dir.as_deref().or(port_or_dir.as_deref()),
|
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 {
|
} else {
|
||||||
commands::devices::scan_devices()
|
commands::devices::scan_devices()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ static BASIC_TEMPLATE: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/basic")
|
|||||||
pub struct TemplateContext {
|
pub struct TemplateContext {
|
||||||
pub project_name: String,
|
pub project_name: String,
|
||||||
pub anvil_version: String,
|
pub anvil_version: String,
|
||||||
|
pub fqbn: String,
|
||||||
|
pub baud: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TemplateManager;
|
pub struct TemplateManager;
|
||||||
@@ -140,6 +142,8 @@ fn substitute_variables(text: &str, context: &TemplateContext) -> String {
|
|||||||
text.replace("{{PROJECT_NAME}}", &context.project_name)
|
text.replace("{{PROJECT_NAME}}", &context.project_name)
|
||||||
.replace("{{ANVIL_VERSION}}", &context.anvil_version)
|
.replace("{{ANVIL_VERSION}}", &context.anvil_version)
|
||||||
.replace("{{ANVIL_VERSION_CURRENT}}", ANVIL_VERSION)
|
.replace("{{ANVIL_VERSION_CURRENT}}", ANVIL_VERSION)
|
||||||
|
.replace("{{FQBN}}", &context.fqbn)
|
||||||
|
.replace("{{BAUD}}", &context.baud.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -172,10 +176,15 @@ mod tests {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "my_project".to_string(),
|
project_name: "my_project".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:mega:cpu=atmega2560".to_string(),
|
||||||
|
baud: 9600,
|
||||||
};
|
};
|
||||||
let input = "Name: {{PROJECT_NAME}}, Version: {{ANVIL_VERSION}}";
|
let input = "Name: {{PROJECT_NAME}}, Version: {{ANVIL_VERSION}}, FQBN: {{FQBN}}, Baud: {{BAUD}}";
|
||||||
let output = substitute_variables(input, &ctx);
|
let output = substitute_variables(input, &ctx);
|
||||||
assert_eq!(output, "Name: my_project, Version: 1.0.0");
|
assert_eq!(
|
||||||
|
output,
|
||||||
|
"Name: my_project, Version: 1.0.0, FQBN: arduino:avr:mega:cpu=atmega2560, Baud: 9600"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -190,6 +199,8 @@ mod tests {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "test_proj".to_string(),
|
project_name: "test_proj".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
let count = TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
let count = TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -220,6 +231,8 @@ mod tests {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "my_sensor".to_string(),
|
project_name: "my_sensor".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ name = "{{PROJECT_NAME}}"
|
|||||||
anvil_version = "{{ANVIL_VERSION}}"
|
anvil_version = "{{ANVIL_VERSION}}"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
fqbn = "arduino:avr:uno"
|
fqbn = "{{FQBN}}"
|
||||||
warnings = "more"
|
warnings = "more"
|
||||||
include_dirs = ["lib/hal", "lib/app"]
|
include_dirs = ["lib/hal", "lib/app"]
|
||||||
extra_flags = ["-Werror"]
|
extra_flags = ["-Werror"]
|
||||||
|
|
||||||
[monitor]
|
[monitor]
|
||||||
baud = 115200
|
baud = {{BAUD}}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ fn test_basic_template_extracts_all_expected_files() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "test_proj".to_string(),
|
project_name: "test_proj".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
let count = TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
let count = TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -27,6 +29,8 @@ fn test_template_creates_sketch_directory() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "blink".to_string(),
|
project_name: "blink".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -55,6 +59,8 @@ fn test_template_creates_hal_files() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "sensor".to_string(),
|
project_name: "sensor".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -86,6 +92,8 @@ fn test_template_creates_app_header() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "my_sensor".to_string(),
|
project_name: "my_sensor".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -110,6 +118,8 @@ fn test_template_creates_test_infrastructure() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "blink".to_string(),
|
project_name: "blink".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -146,6 +156,8 @@ fn test_template_test_file_references_correct_app() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "motor_ctrl".to_string(),
|
project_name: "motor_ctrl".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -165,6 +177,8 @@ fn test_template_cmake_references_correct_project() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "my_bot".to_string(),
|
project_name: "my_bot".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -184,6 +198,8 @@ fn test_template_creates_dot_files() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "blink".to_string(),
|
project_name: "blink".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -212,6 +228,8 @@ fn test_template_creates_readme() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "blink".to_string(),
|
project_name: "blink".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -233,6 +251,8 @@ fn test_template_creates_valid_config() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "blink".to_string(),
|
project_name: "blink".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -312,6 +332,8 @@ fn test_full_project_structure() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "full_test".to_string(),
|
project_name: "full_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -361,6 +383,8 @@ fn test_no_unicode_in_template_output() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "ascii_test".to_string(),
|
project_name: "ascii_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -408,6 +432,8 @@ fn test_unknown_template_fails() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "test".to_string(),
|
project_name: "test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = TemplateManager::extract("nonexistent", tmp.path(), &ctx);
|
let result = TemplateManager::extract("nonexistent", tmp.path(), &ctx);
|
||||||
@@ -431,6 +457,8 @@ fn test_template_creates_self_contained_scripts() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "standalone".to_string(),
|
project_name: "standalone".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -453,6 +481,8 @@ fn test_build_sh_reads_anvil_toml() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "toml_reader".to_string(),
|
project_name: "toml_reader".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -478,6 +508,8 @@ fn test_upload_sh_reads_anvil_toml() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "uploader".to_string(),
|
project_name: "uploader".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -511,6 +543,8 @@ fn test_monitor_sh_reads_anvil_toml() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "serial_mon".to_string(),
|
project_name: "serial_mon".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -536,6 +570,8 @@ fn test_scripts_have_shebangs() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "shebangs".to_string(),
|
project_name: "shebangs".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -558,6 +594,8 @@ fn test_scripts_no_anvil_binary_dependency() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "no_anvil_dep".to_string(),
|
project_name: "no_anvil_dep".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -605,6 +643,8 @@ fn test_gitignore_excludes_build_cache() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "gitcheck".to_string(),
|
project_name: "gitcheck".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -630,6 +670,8 @@ fn test_readme_documents_self_contained_workflow() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "docs_check".to_string(),
|
project_name: "docs_check".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -663,6 +705,8 @@ fn test_scripts_tolerate_missing_toml_keys() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "grep_safe".to_string(),
|
project_name: "grep_safe".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
|
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
@@ -698,6 +742,8 @@ fn test_bat_scripts_no_unescaped_parens_in_echo() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "parens_test".to_string(),
|
project_name: "parens_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -757,6 +803,8 @@ fn test_scripts_read_anvil_local_for_port() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "local_test".to_string(),
|
project_name: "local_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -777,6 +825,8 @@ fn test_anvil_toml_template_has_no_port() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "no_port".to_string(),
|
project_name: "no_port".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -806,6 +856,8 @@ fn test_bat_scripts_call_detect_port_ps1() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "ps1_test".to_string(),
|
project_name: "ps1_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -826,6 +878,8 @@ fn test_detect_port_ps1_is_valid() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "ps1_valid".to_string(),
|
project_name: "ps1_valid".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -856,6 +910,8 @@ fn test_refresh_freshly_extracted_is_up_to_date() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "fresh_proj".to_string(),
|
project_name: "fresh_proj".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -884,6 +940,8 @@ fn test_refresh_detects_modified_script() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "mod_proj".to_string(),
|
project_name: "mod_proj".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -951,6 +1009,8 @@ fn test_scripts_read_vid_pid_from_anvil_local() {
|
|||||||
let ctx = TemplateContext {
|
let ctx = TemplateContext {
|
||||||
project_name: "vidpid_test".to_string(),
|
project_name: "vidpid_test".to_string(),
|
||||||
anvil_version: "1.0.0".to_string(),
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:uno".to_string(),
|
||||||
|
baud: 115200,
|
||||||
};
|
};
|
||||||
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
@@ -963,3 +1023,43 @@ fn test_scripts_read_vid_pid_from_anvil_local() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Board preset tests
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_board_preset_fqbn_in_config() {
|
||||||
|
// Creating a project with --board mega should set the FQBN in .anvil.toml
|
||||||
|
let tmp = TempDir::new().unwrap();
|
||||||
|
let ctx = TemplateContext {
|
||||||
|
project_name: "mega_test".to_string(),
|
||||||
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "arduino:avr:mega:cpu=atmega2560".to_string(),
|
||||||
|
baud: 115200,
|
||||||
|
};
|
||||||
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
|
let config = ProjectConfig::load(tmp.path()).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
config.build.fqbn, "arduino:avr:mega:cpu=atmega2560",
|
||||||
|
".anvil.toml should contain mega FQBN"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_board_preset_custom_fqbn_in_config() {
|
||||||
|
// Even arbitrary FQBNs should work through the template
|
||||||
|
let tmp = TempDir::new().unwrap();
|
||||||
|
let ctx = TemplateContext {
|
||||||
|
project_name: "custom_board".to_string(),
|
||||||
|
anvil_version: "1.0.0".to_string(),
|
||||||
|
fqbn: "esp32:esp32:esp32".to_string(),
|
||||||
|
baud: 9600,
|
||||||
|
};
|
||||||
|
TemplateManager::extract("basic", tmp.path(), &ctx).unwrap();
|
||||||
|
|
||||||
|
let config = ProjectConfig::load(tmp.path()).unwrap();
|
||||||
|
assert_eq!(config.build.fqbn, "esp32:esp32:esp32");
|
||||||
|
assert_eq!(config.monitor.baud, 9600);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user