From c6f695bf5e757fdae8115abfcefb547745cd37be Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sun, 9 Aug 2026 18:45:47 +0800 Subject: feat(proj_mgr): add toggle mutex validation and program crate name Support `[[user.toggle-mutex]]` groups in rule.toml to enforce mutually exclusive toggle options, and derive `program_crate_name` from `program_name` using snake_case conversion. --- mingling_cli/src/proj_mgr/cmd_proj_init.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'mingling_cli/src/proj_mgr/cmd_proj_init.rs') diff --git a/mingling_cli/src/proj_mgr/cmd_proj_init.rs b/mingling_cli/src/proj_mgr/cmd_proj_init.rs index 15f1f50..6e3908b 100644 --- a/mingling_cli/src/proj_mgr/cmd_proj_init.rs +++ b/mingling_cli/src/proj_mgr/cmd_proj_init.rs @@ -4,6 +4,7 @@ use std::{ path::{Path, PathBuf}, }; +use just_fmt::snake_case; use just_template::Template; use mingling::{ Grouped, LazyRes, RenderResult, Routable, @@ -15,7 +16,9 @@ use mingling::{ use crate::{Entry, Next, config::ResMlingConfig, eprintln_cargo, hprintln_cargo, println_cargo}; -use super::rule_solver::{eval_rule, parse_checklist, parse_rules, resolve_answers}; +use super::rule_solver::{ + eval_rule, parse_checklist, parse_rules, resolve_answers, validate_mutexes, +}; use super::template_source::{ DEFAULT_TMPL_SOURCE, TemplateSource, cache_dir, normalize_source, resolve_git, }; @@ -151,9 +154,14 @@ pub fn handle_state_project_generate(_: StateProjectGenerate, cwd: &ResCurrentDi // Compute final answers from checklist values + defaults declared in rule.toml let answers = resolve_answers(&answers, &rules); - // Compute display block toggles based on rules: checklist values + rules whose display condition is true + // Mutually exclusive toggle groups must not both be enabled. + validate_mutexes(&answers, &rules).map_err(ErrorRuleParseFailed::new)?; + // Derive the crate name from the program name (e.g. `my-cli` -> `my_cli`). let mut params: HashMap = answers.clone(); + if let Some(program_name) = answers.get("program_name") { + params.insert("program_crate_name".to_string(), snake_case!(program_name)); + } for display in &rules.display { if eval_rule(&display.rule, &answers) { params.insert(display.name.clone(), String::new()); -- cgit