aboutsummaryrefslogtreecommitdiff
path: root/build.rs
blob: f1080568b555f4e9f64d8dcc30820b40d520e02c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::{
    env::var,
    ffi::OsStr,
    fs::{
        read,
        read_dir,
        read_to_string,
        write,
    },
    io::Write,
    path::{
        Path,
        PathBuf,
    },
    process::{
        Command,
        Stdio,
    },
};

use quote::quote;

fn main() {
    println!("cargo::rerun-if-changed=nvim-treesitter/lua/nvim-treesitter/parsers.lua");
    println!("cargo::rerun-if-changed=generate_parsers.lua");
    let mut child = Command::new("lua")
        .arg("generate_parsers.lua")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Failed to spawn process");

    let mut stdin = child.stdin.take().expect("Failed to open stdin");
    std::thread::spawn(move || {
        stdin
            .write_all(
                read(Path::new("nvim-treesitter/lua/nvim-treesitter/parsers.lua"))
                    .expect("Failed to create parsers path")
                    .as_ref(),
            )
            .expect("Failed to write to stdin");
    })
    .join()
    .unwrap();

    let output = child.wait_with_output().expect("Failed to read stdout");
    write(
        PathBuf::from(format!("{}/_parsers.rs", var("OUT_DIR").unwrap())),
        output.stdout,
    )
    .unwrap();

    let query_dirs = read_dir(Path::new("nvim-treesitter/queries"))
        .expect("Failed to read nvim-treesitter/queries")
        .filter_map(|entry| {
            let path = entry.unwrap().path();
            path.is_dir().then_some(path)
        })
        .collect::<Vec<PathBuf>>();

    let queries = query_dirs
        .iter()
        .filter_map(|path| {
            read_dir(path)
                .map(|entries| {
                    (
                        path.file_name().unwrap().to_str().unwrap(),
                        entries.filter_map(|entry| entry.ok()),
                    )
                })
                .ok()
        })
        .map(|(lang, entries)| {
            let entries = entries.filter_map(|entry| {
                let path = entry.path();
                match path.file_stem().map(OsStr::to_str).flatten() {
                    Some(stem @ ("highlights" | "injections" | "locals")) => {
                        let content =
                            read_to_string(&path).expect("Query file should be valid UTF-8");
                        Some(quote! {
                            (#stem, #content)
                        })
                    }
                    _ => None,
                }
            });
            quote! {
                (#lang, HashMap::from([
                    #(#entries),*
                ]))
            }
        });

    let code = quote! {
        pub static QUERIES: LazyLock<HashMap<&'static str, HashMap<&'static str, &'static str>>> = LazyLock::new(|| {
            HashMap::from([
                #(#queries),*
            ])
        });
    };
    let tree = &syn::parse2(code).unwrap();
    let formatted = prettyplease::unparse(tree);

    write(
        PathBuf::from(format!("{}/_queries.rs", var("OUT_DIR").unwrap())),
        formatted,
    )
    .unwrap();
}