use std::fs; use proc_macro::TokenStream; /// Takes a path to the aoc year directory and generates module declarations /// and argument parsing for each day found in that directory, each day /// must begin with "day". #[proc_macro] pub fn gen_days(item: TokenStream) -> TokenStream { let path = format!("{item}"); let mut days_in_dir: Vec = Vec::new(); for entry in fs::read_dir(&path).unwrap() { let entry = entry.unwrap(); let path = entry.path(); if let Some(file_stem) = path.file_stem() { let (day_prefix, day_number) = file_stem.to_str().unwrap().split_at(3); if day_prefix == "day" { // do template stuff for this day days_in_dir.push(day_number.to_string()); } } } let mut module_imports = String::new(); let mut day_checks = String::new(); for day in days_in_dir { module_imports += &format!("mod day{day};\n"); day_checks += &format!(" if day == \"day{day}\" {{ if part == \"1\" {{ println!(\"{{}}\", day{day}::part1()); }} else if part == \"2\" {{ println!(\"{{}}\", day{day}::part2()); }} else {{ panic!(\"expecting 1 or 2 for argument 2\") }} }} "); } format!(" {module_imports} fn main() {{ let day = std::env::args().nth(1).expect(\"needs to specify day for first argument\"); let part = std::env::args().nth(2).expect(\"needs to specify 1 or 2 for second argument\"); {day_checks} }} ").parse().unwrap() }