lwb_parser/codegen/
mod.rs

1use convert_case::{Case, Casing};
2use regex::Captures;
3use std::fs::File;
4use std::io::{Read, Write};
5use std::path::{Path, PathBuf};
6use std::process::Command;
7use std::{fs, io};
8
9mod check_recursive;
10mod error;
11mod generate_file_headers;
12mod generate_from_pairs;
13mod generate_misc;
14mod generate_structs;
15mod generate_trait_impls;
16pub mod manager;
17
18fn sanitize_identifier(id: &str) -> String {
19    id.to_case(Case::UpperCamel)
20}
21
22/// Like a file, formats contents on closing
23pub struct FormattingFile(Option<File>, PathBuf);
24
25impl FormattingFile {
26    pub fn create(p: impl AsRef<Path>) -> io::Result<Self> {
27        Ok(Self(Some(File::create(&p)?), p.as_ref().to_path_buf()))
28    }
29
30    pub fn open(p: impl AsRef<Path>) -> io::Result<Self> {
31        Ok(Self(Some(File::open(&p)?), p.as_ref().to_path_buf()))
32    }
33}
34
35fn try_fmt(p: impl AsRef<Path>) -> io::Result<()> {
36    println!("Formatting {:?}", p.as_ref());
37    Command::new("rustfmt").arg(p.as_ref()).spawn()?.wait()?;
38
39    let r = regex::Regex::new(r#"#\[doc *= *"(.*)"\]"#).expect("should compile");
40    let rq = regex::Regex::new(r#"\\(.)"#).expect("should compile");
41
42    let code = fs::read_to_string(&p)?;
43    let replaced = r.replace_all(&code, |caps: &Captures| {
44        format!("///{}", rq.replace_all(&caps[1], "$1"))
45    });
46    fs::write(&p, replaced.as_ref())?;
47
48    Ok(())
49}
50
51impl Drop for FormattingFile {
52    fn drop(&mut self) {
53        drop(self.0.take());
54
55        if let Err(e) = try_fmt(&self.1) {
56            eprintln!("{}", e);
57        }
58    }
59}
60
61impl Read for FormattingFile {
62    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
63        self.0.as_ref().unwrap().read(buf)
64    }
65}
66
67impl Write for FormattingFile {
68    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
69        self.0.as_ref().unwrap().write(buf)
70    }
71
72    fn flush(&mut self) -> std::io::Result<()> {
73        self.0.as_ref().unwrap().flush()
74    }
75}