use std::io::Write; fn main() { let mut output_file = std::fs::File::create("src/registered_scripts.rs").unwrap(); write!( output_file, r"// Autogenerated file. Do not edit. use alloc::boxed::Box; use pkmn_lib_interface::app_interface::{{get_hash, StringKey}}; use pkmn_lib_interface::handling::{{Script, ScriptCategory}}; macro_rules! resolve_match {{ ( $mid:expr, $( $script:ty, )* ) => ( match $mid {{ $( const {{ get_hash(<$script>::get_const_name()) }} => {{ return Some(Box::new(<$script>::new())) }} )* _ => {{}} }} ) }} pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option> {{ match category {{" ) .unwrap(); write_category("moves", "Move", &mut output_file); write_category("abilities", "Ability", &mut output_file); write_category("status", "Status", &mut output_file); write_category("pokemon", "Pokemon", &mut output_file); write_category("battle", "Battle", &mut output_file); write_category("weather", "Weather", &mut output_file); write_category("side", "Side", &mut output_file); write_category( "item_battle_triggers", "ItemBattleTrigger", &mut output_file, ); write!( output_file, r#" }} None }} "# ) .unwrap(); } fn write_category(path: &str, category: &str, output_file: &mut std::fs::File) { write!( output_file, r" ScriptCategory::{} => {{ resolve_match! {{ name.hash().unwrap(), ", category ) .unwrap(); write_scripts(path, output_file); write!( output_file, r" }} }}," ) .unwrap(); } fn write_scripts(path: &str, output_file: &mut std::fs::File) { let move_files = std::fs::read_dir(format!("src/{}", path)) .unwrap() .map(|f| f.unwrap().path()) .filter(|f| f.extension().unwrap() == "rs") .map(|f| f.file_stem().unwrap().to_str().unwrap().to_string()) .collect::>(); for file in move_files { println!("cargo:rerun-if-changed=src/{}/{}.rs", path, file); let parsed = syn::parse_file(&std::fs::read_to_string(format!("src/{}/{}.rs", path, file)).unwrap()) .unwrap(); // Now we need to find every impl Script for X { ... } block inside parsed let script_impls = parsed .items .iter() .filter_map(|item| match item { syn::Item::Impl(impl_block) => match impl_block.trait_ { Some((_, ref path, _)) => { if path.segments[0].ident == "Script" { Some(impl_block) } else { None } } None => None, }, _ => None, }) .collect::>(); for script_impl in script_impls { if let syn::Type::Path(p) = script_impl.self_ty.as_ref() { let ident = p.path.segments[0].ident.to_string(); writeln!( output_file, " crate::{}::{}::{},", path, file, ident ) .unwrap(); } } } }