bevy_state_tool/
lib.rs

1//! bevy_state_tool包是bevy包的依赖包,一个微型构建状态的包。
2//! 使用时需要添加bevy包与iyes_loopless包
3//! example for Cargo.toml:
4//! ```toml
5//! bevy = { version = "0.9.1", features = ["dynamic"] }
6//! iyes_loopless="0.9.1"
7//! bevy_state_tool="0.1.0"
8//! ```
9//!
10//! example for lib.rs
11//! ```
12//! pub mod test;
13//! use bevy::prelude::*;
14//! use iyes_loopless::prelude::*;
15//! use bevy_state_tool::GameStates;
16//! 
17//! #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, GameStates)]
18//! pub enum GameState {
19//! GameIn,
20//! GamePause,
21//! StartUi,
22//! ChooseGame,
23//! AssetLoadingSpecial,
24//! }
25//! ```
26//! 
27//! example for main.rs
28//! ```
29//! use bevy::prelude::*;
30//! use iyes_loopless::prelude::*;
31//! use bevy_state_tool::GameStates;
32//! fn main()
33//! {
34//!     App::new().add_plugin(test1::Test::A).run();
35//! }
36//! ```
37#![feature(fs_try_exists)]
38use std::io::{Read, Write};
39
40use proc_macro::TokenStream;
41use syn::parse_macro_input;
42use syn::DeriveInput;
43mod to_snake_case;
44use to_snake_case::ToSnakeCase;
45/** 该过程宏会自动根据枚举生成对印结构体 */
46#[proc_macro_derive(GameStates)]
47pub fn game_states(input: proc_macro::TokenStream) -> TokenStream {
48    let input = parse_macro_input!(input as DeriveInput);
49    let enum_name: &str = &input.ident.to_string();
50    
51    //把大驼峰命名法的字符串转换成蛇形命名法的字符串
52    let path_name: &str=&ToSnakeCase::new(enum_name).collect::<String>();
53    //如果没有这个文件夹
54    if !std::fs::try_exists(String::from("src/") + path_name).unwrap() {
55        /* 创建目录以及子文件夹 */
56        std::fs::create_dir_all(String::from("src/") + path_name + "/config").unwrap();
57
58        /* 创建mod.rs文件 */
59        let mut mod_rs_file = std::fs::File::options()
60            .write(true)
61            .create(true)
62            .open(String::from("src/") + path_name + "/mod.rs")
63            .unwrap();
64        /* 创建这个文件 */
65        let mut file = std::fs::File::options()
66            .write(true)
67            .create(true)
68            .open(String::from("src/") + path_name + "/config/info.txt")
69            .unwrap();
70
71        /* 创建加载文件 */
72        let mut init_file = std::fs::File::options()
73            .write(true)
74            .create(true)
75            .open(String::from("src/") + path_name + "/config/init.txt")
76            .unwrap();
77        writeln!(init_file, "app.add_loopless_state(*self)").unwrap();
78
79        //对数据进行处理
80        match input.data {
81            //如果类型是枚举体
82            syn::Data::Enum(ref data_struct) => {
83                for variant in &data_struct.variants {
84                    //结构体名字
85                    let variant_name: &str = &variant.ident.to_string();
86                    //把大驼峰命名法的字符串转换成蛇形命名法的字符串
87                    let struct_file_name: &str=&ToSnakeCase::new(variant_name).collect::<String>();
88                    //加载记录
89                    writeln!(file, "{}", variant_name).unwrap();
90                    writeln!(init_file, ".add_plugin({})", variant_name).unwrap();
91                    writeln!(mod_rs_file, "mod {};", struct_file_name).unwrap();
92                    writeln!(mod_rs_file, "use {}::{};", struct_file_name, variant_name).unwrap();
93                    create_file(path_name,struct_file_name,enum_name, variant_name).unwrap();
94                }
95            }
96            _ => (),
97        }
98        let over_string = include_str!("../template_mod.txt").replace("$", enum_name);
99        write!(mod_rs_file, "{}", over_string).unwrap();
100        file.flush().unwrap();
101        init_file.flush().unwrap();
102        mod_rs_file.flush().unwrap();
103    } else {
104        /* 打开这个文件 */
105        let mut file = std::fs::File::options()
106            .read(true)
107            .write(true)
108            .open(String::from("src/") + path_name + "/config/info.txt")
109            .unwrap();
110
111        /* 打开mod.rs文件 */
112        let mut mod_rs_file = std::fs::File::options()
113            .append(true)
114            .open(String::from("src/") + path_name + "/mod.rs")
115            .unwrap();
116
117        /* 打开加载文件 */
118        let mut init_file = std::fs::File::options()
119            .append(true)
120            .open(String::from("src/") + path_name + "/config/init.txt")
121            .unwrap();
122
123        /* 加载文件里面的内容 */
124        let mut file_str = String::new();
125        file.read_to_string(&mut file_str).unwrap();
126        let arr = file_str.split('\n').collect::<Vec<_>>();
127        match input.data {
128            //如果类型是枚举体
129            syn::Data::Enum(ref data_struct) => {
130                for variant in &data_struct.variants {
131                    //结构体名字
132                    let variant_name: &str = &variant.ident.to_string();
133                    let struct_file_name: &str = &variant_name.to_ascii_lowercase();
134                    //如果不包括该结构体的名字
135
136                    if !arr.contains(&variant_name) {
137                        //加载记录
138                        writeln!(file, "{}", variant_name).unwrap();
139                        writeln!(init_file, ".add_plugin({})", variant_name).unwrap();
140                        writeln!(mod_rs_file, "mod {};", struct_file_name).unwrap();
141                        writeln!(mod_rs_file, "use {}::{};", struct_file_name, variant_name).unwrap();
142                        create_file(path_name,struct_file_name,enum_name, variant_name).unwrap();
143                    }
144                }
145            }
146            _ => (),
147        }
148        file.flush().unwrap();
149        init_file.flush().unwrap();
150        mod_rs_file.flush().unwrap();
151    }
152
153    TokenStream::new()
154}
155
156//创建文件
157#[inline]
158fn create_file(path: &str, file_name: &str,enum_name:&str,struct_name:&str) -> std::io::Result<()> {
159    let mut struct_file = std::fs::File::create(
160        String::from("src/")
161            + &path
162            + "/"
163            + &file_name
164            + ".rs",
165    )?;
166    let over_str = include_str!("../template.txt")
167        .replace("$", enum_name)
168        .replace("~", struct_name);
169    write!(struct_file, "{}", over_str)
170}