use std::path::Path;
use super::naming::{
append_mod_declaration, mod_declaration, module_file_path, snake_case, validate_module_name,
validate_type_name,
};
use super::write::{GeneratedFile, module_mod_rs};
pub(crate) fn generate(
root: &Path,
raw_name: &str,
raw_module: &str,
) -> Result<(GeneratedFile, String), String> {
let name = validate_type_name(raw_name)?;
let module = validate_module_name(raw_module)?;
let fn_name = snake_case(&name);
let command_name = snake_case(&name).replace('_', ":");
let path = module_file_path(root, &module, &format!("{fn_name}.rs"))?;
let content = render(&fn_name, &command_name, &module);
let file = GeneratedFile {
path: path.clone(),
content,
};
let mod_rs = module_mod_rs(root, &module);
let declaration = mod_declaration(&fn_name)?;
let mod_msg = append_mod_declaration(&mod_rs, &declaration)?;
Ok((file, mod_msg))
}
fn render(fn_name: &str, command_name: &str, module: &str) -> String {
format!(
"//! `{fn_name}` — application command for the `{module}` module.\n\
\n\
/// A typed application command. The `#[command]` macro generates a\n\
/// `CommandBinding` const for `arc check` and `arc run`. Register the\n\
/// command with `CommandRegistry::register` at startup.\n\
#[arcature::command(\"{command_name}\")]\n\
pub async fn {fn_name}() -> Result<(), ()> {{\n\
\x20 Ok(())\n\
}}\n"
)
}