leekscript_tooling/formatter/
config.rs1use std::path::Path;
4
5use super::options::{BraceStyle, FormatterOptions, IndentStyle, SemicolonStyle};
6
7#[must_use]
10pub fn load_formatter_options_from_dir(dir: &Path) -> Option<FormatterOptions> {
11 let leekfmt = dir.join(".leekfmt.toml");
12 if leekfmt.exists() {
13 return load_from_file(&leekfmt);
14 }
15 let manifest = dir.join("leekscript.toml");
16 if manifest.exists() {
17 if let Ok(content) = std::fs::read_to_string(&manifest) {
18 if let Ok(t) = content.parse::<toml::Table>() {
19 if let Some(format_table) = t.get("format").and_then(|v| v.as_table()) {
20 return parse_format_table(format_table);
21 }
22 }
23 }
24 }
25 None
26}
27
28#[must_use]
30pub fn load_formatter_options_from_file(path: &Path) -> Option<FormatterOptions> {
31 load_from_file(path)
32}
33
34fn load_from_file(path: &Path) -> Option<FormatterOptions> {
35 let content = std::fs::read_to_string(path).ok()?;
36 let t = content.parse::<toml::Table>().ok()?;
37 let format_table = t.get("format").and_then(|v| v.as_table())?;
38 parse_format_table(format_table)
39}
40
41fn parse_format_table(t: &toml::map::Map<String, toml::Value>) -> Option<FormatterOptions> {
42 let indent_style = t
43 .get("indent")
44 .and_then(|v| v.as_str())
45 .map_or(IndentStyle::Tabs, parse_indent_style);
46
47 let brace_style = t
48 .get("brace_style")
49 .and_then(|v| v.as_str())
50 .map_or(BraceStyle::SameLine, parse_brace_style);
51
52 let semicolon_style = t
53 .get("semicolon_style")
54 .and_then(|v| v.as_str())
55 .map_or(SemicolonStyle::Always, parse_semicolon_style);
56
57 let canonical_format = t
58 .get("canonical")
59 .and_then(toml::Value::as_bool)
60 .unwrap_or(false);
61
62 Some(FormatterOptions {
63 preserve_comments: t
64 .get("preserve_comments")
65 .and_then(toml::Value::as_bool)
66 .unwrap_or(true),
67 parenthesize_expressions: t
68 .get("parenthesize_expressions")
69 .and_then(toml::Value::as_bool)
70 .unwrap_or(false),
71 annotate_types: false,
72 signature_roots: None,
73 canonical_format,
74 indent_style,
75 brace_style,
76 semicolon_style,
77 })
78}
79
80fn parse_indent_style(s: &str) -> IndentStyle {
81 let s = s.trim().to_lowercase();
82 if s == "tabs" {
83 return IndentStyle::Tabs;
84 }
85 if s.starts_with("spaces") {
86 let n = s
87 .trim_start_matches("spaces")
88 .trim()
89 .parse::<u32>()
90 .unwrap_or(4);
91 return IndentStyle::Spaces(n);
92 }
93 IndentStyle::Tabs
94}
95
96fn parse_brace_style(s: &str) -> BraceStyle {
97 match s.trim().to_lowercase().as_str() {
98 "next-line" | "nextline" => BraceStyle::NextLine,
99 _ => BraceStyle::SameLine,
100 }
101}
102
103fn parse_semicolon_style(s: &str) -> SemicolonStyle {
104 match s.trim().to_lowercase().as_str() {
105 "omit" => SemicolonStyle::Omit,
106 _ => SemicolonStyle::Always,
107 }
108}