diff --git a/Cargo.lock b/Cargo.lock index 0cd4992..a66c79b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1785,7 +1785,7 @@ dependencies = [ [[package]] name = "rmkit" -version = "0.0.21" +version = "0.1.0" dependencies = [ "cargo_metadata", "cargo_toml", diff --git a/Cargo.toml b/Cargo.toml index 0b73b62..970a617 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rmkit" -version = "0.0.21" +version = "0.1.0" edition = "2021" homepage = "https://github.com/rmk-rs/rmkit" repository = "https://github.com/rmk-rs/rmkit" diff --git a/README.md b/README.md index e54173b..87224bc 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ Now rmkit can be used to generate RMK project directly from `keyboard.toml` and rmkit create --keyboard-toml-path keyboard.toml --vial-json-path vial.json ``` + A `Cargo.toml` or `memory.x` next to `keyboard.toml` replaces the template's copy as-is — use it to add Cargo features, pin dependencies, or change the flash layout. When you provide `Cargo.toml`, rmkit no longer adjusts the `rmk` features for you. + 3. Or, you can create RMK project from project template ``` diff --git a/src/args.rs b/src/args.rs index 0f433bf..8d8eec8 100644 --- a/src/args.rs +++ b/src/args.rs @@ -11,7 +11,8 @@ pub struct Args { pub enum Commands { /// Create a new RMK project from keyboard.toml and vial.json Create { - /// Path to keyboard.toml file + /// Path to keyboard.toml file. A Cargo.toml or memory.x next to it + /// replaces the template's copy verbatim. #[arg(long)] keyboard_toml_path: Option, diff --git a/src/chip.rs b/src/chip.rs index 84bc386..e558580 100644 --- a/src/chip.rs +++ b/src/chip.rs @@ -27,6 +27,7 @@ pub(crate) fn get_chip_options(split: bool) -> Vec<&'static str> { "Pi Pico W", "esp32c3", "esp32c6", + "esp32h2", "esp32s3", ] } else { @@ -41,6 +42,7 @@ pub(crate) fn get_chip_options(split: bool) -> Vec<&'static str> { "esp32c3", "esp32s3", "esp32c6", + "esp32h2", "nice!nano_v2", "XIAO BLE", "nice!nano", diff --git a/src/main.rs b/src/main.rs index 56e108d..80a7cf7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,14 +106,42 @@ async fn create_project( )?; fs::copy(&vial_json_path, project_info.target_dir.join("vial.json"))?; + // A Cargo.toml / memory.x next to keyboard.toml is the user's, verbatim + let user_dir = Path::new(&keyboard_toml_path) + .parent() + .unwrap_or(Path::new("")); + let cargo_toml_user_owned = copy_user_owned_files(user_dir, &project_info.target_dir)?; + // Post-process - post_process(project_info)?; + post_process(project_info, cargo_toml_user_owned)?; Ok(()) } +/// Files that replace the template's copy when they sit next to keyboard.toml +const USER_OWNED_FILES: [&str; 2] = ["Cargo.toml", "memory.x"]; + +/// Copy the user's own project files over the generated project. Returns whether +/// Cargo.toml was among them — the user then owns the feature list too. +fn copy_user_owned_files(user_dir: &Path, target_dir: &Path) -> Result> { + let mut cargo_toml_user_owned = false; + for name in USER_OWNED_FILES { + let src = user_dir.join(name); + if !src.is_file() { + continue; + } + fs::copy(&src, target_dir.join(name))?; + println!("📄 Using {} (replaces the template's)", src.display()); + cargo_toml_user_owned |= name == "Cargo.toml"; + } + Ok(cargo_toml_user_owned) +} + /// Postprocessing after generating project -fn post_process(project_info: ProjectInfo) -> Result<(), Box> { +fn post_process( + project_info: ProjectInfo, + cargo_toml_user_owned: bool, +) -> Result<(), Box> { // Replace {{ project_name }} in toml/json files replace_in_folder( &project_info, @@ -139,6 +167,13 @@ fn post_process(project_info: ProjectInfo) -> Result<(), Box> { &project_info.uf2_key, )?; + // The user's Cargo.toml is used as-is; keyboard.toml/feature mismatches are + // reported by rmk-macro at build time. + if cargo_toml_user_owned { + println!("Skipping rmk feature adjustments: Cargo.toml is user-provided"); + return Ok(()); + } + // Disable some default features if !project_info.disabled_default_feature.is_empty() { let metadata = MetadataCommand::new() @@ -279,7 +314,7 @@ async fn init_project( } // Post-process - post_process(project_info)?; + post_process(project_info, false)?; Ok(()) } @@ -596,3 +631,36 @@ fn enable_rmk_features(target_dir: &PathBuf, features: Vec) -> Result<() Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn user_owned_files_replace_template_copies() { + let root = std::env::temp_dir().join(format!("rmkit_user_owned_{}", std::process::id())); + let (user_dir, target_dir) = (root.join("user"), root.join("target")); + fs::create_dir_all(&user_dir).unwrap(); + fs::create_dir_all(&target_dir).unwrap(); + fs::write(target_dir.join("Cargo.toml"), "template").unwrap(); + fs::write(target_dir.join("memory.x"), "template").unwrap(); + let generated = |name: &str| fs::read_to_string(target_dir.join(name)).unwrap(); + + // Nothing next to keyboard.toml: template files stay, Cargo.toml is not user-owned + assert!(!copy_user_owned_files(&user_dir, &target_dir).unwrap()); + assert_eq!(generated("Cargo.toml"), "template"); + + // Only memory.x provided: it replaces the template's, Cargo.toml is still rmkit's + fs::write(user_dir.join("memory.x"), "user").unwrap(); + assert!(!copy_user_owned_files(&user_dir, &target_dir).unwrap()); + assert_eq!(generated("memory.x"), "user"); + assert_eq!(generated("Cargo.toml"), "template"); + + // Cargo.toml provided: replaced verbatim and reported as user-owned + fs::write(user_dir.join("Cargo.toml"), "user").unwrap(); + assert!(copy_user_owned_files(&user_dir, &target_dir).unwrap()); + assert_eq!(generated("Cargo.toml"), "user"); + + fs::remove_dir_all(&root).unwrap(); + } +}