typst_fmt/
lib.rs

1// use ast::Expr::*;
2// use regex::Regex;
3// use typst::syntax::parse;
4// use typst::syntax::{ast, SyntaxNode};
5
6// // Optimize: could return Text edit that should be applied one after the other
7// // instead of String
8// pub fn typst_format(s: &str) -> String {
9//     format_with_rules(s, &[SpaceRule.as_dyn()])
10// }
11
12// fn format_with_rules(s: &str, rules: &[Box<dyn Rule>]) -> String {
13//     let syntax_node = parse(s);
14//     format_recursive(&syntax_node, 0, (), rules)
15// }
16
17// // Optimize: consider returning &str instead and other optimisations
18// //
19// fn format_recursive(
20//     syntax_node: &SyntaxNode,
21//     recurse: usize,
22//     // feel free to include what your rule needs to know here
23//     // and change the definition of the function if you need to
24//     // for instance this could contain the parent if any
25//     context: (),
26//     rules: &[Box<dyn Rule>],
27// ) -> String {
28//     // rules either leave the result unchanged or format it
29//     // apply rules, append to result, do some for children
30//     let mut result;
31//     // currently only the first rule that matches is selected (this behavior could be changed)
32//     // the most specific rules should come first.
33//     if let Some(rule) = rules.iter().find(|&rule| rule.accept(syntax_node, context)) {
34//         result = rule.eat(syntax_node);
35//     } else {
36//         // test this returns what I think
37//         result = String::from(syntax_node.text())
38//     }
39
40//     for child in syntax_node.children() {
41//         result.push_str(&format_recursive(child, recurse + 1, (), rules))
42//     }
43//     result
44// }
45
46// trait Rule {
47//     fn accept(&self, syntax_node: &SyntaxNode, context: ()) -> bool;
48
49//     fn eat(&self, syntax_node: &SyntaxNode) -> String;
50
51//     fn as_dyn(self: Self) -> Box<dyn Rule>
52//     where
53//         Self: Sized + 'static,
54//     {
55//         Box::new(self)
56//     }
57// }
58
59// struct SpaceRule;
60// impl Rule for SpaceRule {
61//     fn accept(&self, syntax_node: &SyntaxNode, context: ()) -> bool {
62//         syntax_node.is::<ast::Space>()
63//     }
64
65//     fn eat(&self, syntax_node: &SyntaxNode) -> String {
66//         //let x = syntax_node.cast::<ast::Space>().unwrap();
67//         assert!(syntax_node.text() != "");
68//         let t = syntax_node.text().as_str();
69//         let rg = Regex::new("\\s+").unwrap();
70//         rg.replace_all(t, " ").to_string()
71//     }
72// }
73
74// #[cfg(test)]
75// mod tests {
76//     use super::*;
77
78//     #[test]
79//     fn test_name() {
80//         assert_eq!(format_with_rules("#{ }", &[SpaceRule.as_dyn()]), "#{ }");
81//     }
82
83//     #[test]
84//     fn two_spaces_become_one() {
85//         assert_eq!(format_with_rules("#{  }", &[SpaceRule.as_dyn()]), "#{ }");
86//     }
87// }
88
89// // const SOURCE1: &str = r##"
90// // #import "template.typ":*"##;
91
92// // const SOURCE: &str = r##"
93// // #import "template.typ": *
94// // #show: letter.with(
95// //   sender: [
96// //     Jane Smith, Universal Exports, 1 Heavy Plaza, Morristown, NJ 07964
97// //   ],
98// //   recipient: [
99// //     Mr. John Doe \
100// //     Acme Corp. \
101// //     123 Glennwood Ave \
102// //     Quarto Creek, VA 22438
103// //   ],
104// //   date: [Morristown, June 9th, 2023],
105// //   subject: [test],
106// //   name: [Jane Smith \ Regional Director],
107// // )
108
109// // Dear Joe,
110
111// // #lorem(99)
112
113// // Best,
114// // "##;
115
116// /// rules :
117// /// ModuleImport, space after colon
118// /// ImportItems : no trailing comma
119
120// #[test]
121// fn feature() {
122//     for a in [
123//         "",
124//         " ",
125//         r##"#import "template.typ":*"##,
126//         r##"#import "template.typ": *"##,
127//         r##"#import "template.typ": func1, func2,"##,
128//     ] {
129//         println! {"parsing: {:?}",a};
130
131//         let syntax_node = parse(a);
132//         dbg!(syntax_node.erroneous());
133//         println!("parse:\n{:?}", &syntax_node);
134//         println!("--------------");
135//     }
136// }