macroquad_lua_macros/
lib.rs

1use quote::quote;
2use std::path::Path;
3use std::path::PathBuf;
4use syn::{parse_macro_input, LitStr};
5// use quote::ToTokens;
6
7#[proc_macro]
8pub fn embed_lua_files(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
9    let base_path_str = parse_macro_input!(input as LitStr).value();
10    let base_path = Path::new(&base_path_str);
11    let mut parts: Vec<proc_macro2::TokenStream> = vec![];
12
13    for path in &list_all_paths(&base_path) {
14        let mut name = path
15            .iter()
16            .skip(base_path.iter().count())
17            .take(path.iter().count() - base_path.iter().count())
18            .map(|p| p.to_str().unwrap())
19            .collect::<Vec<&str>>()
20            .join(".");
21        if !name.ends_with(".lua") {
22            continue;
23        }
24        name.pop();
25        name.pop();
26        name.pop();
27        name.pop();
28        let absolute_path = path.canonicalize().unwrap();
29        let path_str = absolute_path.to_str().unwrap();
30        parts.push(quote! {
31            map.insert(#name.to_string(), include_str!(#path_str).to_string());
32        });
33    }
34    quote! {
35        {
36            let mut map = std::collections::HashMap::new();
37            #(#parts)*
38            map
39        }
40    }
41    .into()
42}
43
44fn list_all_paths(path: &Path) -> Vec<PathBuf> {
45    let mut paths = vec![];
46    for entry in path.read_dir().unwrap() {
47        let entry = entry.unwrap();
48        let path = entry.path();
49        if path.is_dir() {
50            paths.extend(list_all_paths(&path));
51        } else {
52            paths.push(path);
53        }
54    }
55    paths
56}