#![feature(fs_try_exists)]
use std::io::{Read, Write};
use proc_macro::TokenStream;
use syn::parse_macro_input;
use syn::DeriveInput;
mod to_snake_case;
use to_snake_case::ToSnakeCase;
#[proc_macro_derive(GameStates)]
pub fn game_states(input: proc_macro::TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let enum_name: &str = &input.ident.to_string();
let path_name: &str=&ToSnakeCase::new(enum_name).collect::<String>();
if !std::fs::try_exists(String::from("src/") + path_name).unwrap() {
std::fs::create_dir_all(String::from("src/") + path_name + "/config").unwrap();
let mut mod_rs_file = std::fs::File::options()
.write(true)
.create(true)
.open(String::from("src/") + path_name + "/mod.rs")
.unwrap();
let mut file = std::fs::File::options()
.write(true)
.create(true)
.open(String::from("src/") + path_name + "/config/info.txt")
.unwrap();
let mut init_file = std::fs::File::options()
.write(true)
.create(true)
.open(String::from("src/") + path_name + "/config/init.txt")
.unwrap();
writeln!(init_file, "app.add_loopless_state(*self)").unwrap();
match input.data {
syn::Data::Enum(ref data_struct) => {
for variant in &data_struct.variants {
let variant_name: &str = &variant.ident.to_string();
let struct_file_name: &str=&ToSnakeCase::new(variant_name).collect::<String>();
writeln!(file, "{}", variant_name).unwrap();
writeln!(init_file, ".add_plugin({})", variant_name).unwrap();
writeln!(mod_rs_file, "mod {};", struct_file_name).unwrap();
writeln!(mod_rs_file, "use {}::{};", struct_file_name, variant_name).unwrap();
create_file(path_name,struct_file_name,enum_name, variant_name).unwrap();
}
}
_ => (),
}
let over_string = include_str!("../template_mod.txt").replace("$", enum_name);
write!(mod_rs_file, "{}", over_string).unwrap();
file.flush().unwrap();
init_file.flush().unwrap();
mod_rs_file.flush().unwrap();
} else {
let mut file = std::fs::File::options()
.read(true)
.write(true)
.open(String::from("src/") + path_name + "/config/info.txt")
.unwrap();
let mut mod_rs_file = std::fs::File::options()
.append(true)
.open(String::from("src/") + path_name + "/mod.rs")
.unwrap();
let mut init_file = std::fs::File::options()
.append(true)
.open(String::from("src/") + path_name + "/config/init.txt")
.unwrap();
let mut file_str = String::new();
file.read_to_string(&mut file_str).unwrap();
let arr = file_str.split('\n').collect::<Vec<_>>();
match input.data {
syn::Data::Enum(ref data_struct) => {
for variant in &data_struct.variants {
let variant_name: &str = &variant.ident.to_string();
let struct_file_name: &str = &variant_name.to_ascii_lowercase();
if !arr.contains(&variant_name) {
writeln!(file, "{}", variant_name).unwrap();
writeln!(init_file, ".add_plugin({})", variant_name).unwrap();
writeln!(mod_rs_file, "mod {};", struct_file_name).unwrap();
writeln!(mod_rs_file, "use {}::{};", struct_file_name, variant_name).unwrap();
create_file(path_name,struct_file_name,enum_name, variant_name).unwrap();
}
}
}
_ => (),
}
file.flush().unwrap();
init_file.flush().unwrap();
mod_rs_file.flush().unwrap();
}
TokenStream::new()
}
#[inline]
fn create_file(path: &str, file_name: &str,enum_name:&str,struct_name:&str) -> std::io::Result<()> {
let mut struct_file = std::fs::File::create(
String::from("src/")
+ &path
+ "/"
+ &file_name
+ ".rs",
)?;
let over_str = include_str!("../template.txt")
.replace("$", enum_name)
.replace("~", struct_name);
write!(struct_file, "{}", over_str)
}