Skip to main content

mimium_fmt/
lib.rs

1mod cst_print;
2mod parser_print;
3mod print;
4
5use std::sync::LazyLock;
6use std::sync::Mutex;
7pub struct GlobalConfig {
8    pub indent_size: usize,
9}
10impl Default for GlobalConfig {
11    fn default() -> Self {
12        Self { indent_size: 4 }
13    }
14}
15pub static GLOBAL_DATA: LazyLock<Mutex<GlobalConfig>> =
16    LazyLock::new(|| Mutex::new(GlobalConfig::default()));
17
18/// CST-based pretty print (default)
19pub use cst_print::pretty_print as pretty_print_cst;
20/// AST-based pretty print (legacy)
21pub use parser_print::pretty_print;
22
23use clap::Parser;
24use mimium_lang::utils::error::report;
25use std::fs;
26use std::path::PathBuf;
27
28#[derive(Parser, Debug)]
29#[command(author, version, about, long_about = None)]
30pub struct Args {
31    /// File to format(if not specified, reads from stdin)
32    #[clap(value_parser)]
33    file: Option<PathBuf>,
34    /// Width of the editor
35    #[arg(long, default_value = "80")]
36    width: usize,
37    /// Indentation size
38    #[arg(long, default_value = "4")]
39    indent_size: usize,
40    /// Use legacy AST-based formatter
41    #[arg(long)]
42    ast: bool,
43}
44
45pub fn lib_main() {
46    let args = Args::parse();
47
48    if let Ok(mut gdata) = GLOBAL_DATA.try_lock() {
49        gdata.indent_size = args.indent_size;
50    }
51
52    let file_path = args.file;
53    let code = match file_path.as_ref() {
54        Some(path) => fs::read_to_string(path).expect("Unable to read file"),
55        None => {
56            use std::io::Read;
57            let mut buf = String::new();
58            eprintln!("No file specified. Reading from stdin...");
59            std::io::stdin()
60                .read_to_string(&mut buf)
61                .expect("Unable to read from stdin");
62            buf
63        }
64    };
65
66    let res = if args.ast {
67        pretty_print(code.as_str(), &file_path, args.width)
68    } else {
69        pretty_print_cst(code.as_str(), &file_path, args.width)
70    };
71
72    match res {
73        Ok(rendered) => {
74            println!("{rendered}");
75        }
76        Err(errs) => {
77            report(code.as_str(), file_path.unwrap_or_default(), &errs);
78        }
79    }
80}