comprehensive/
comprehensive.rs

1use syntaxfmt::{SyntaxFmt, SyntaxFormatter, syntax_fmt};
2
3// State trait for type display control
4trait TypeDisplay {
5    fn should_show_types(&self) -> bool;
6}
7
8struct TypeConfig {
9    show_types: bool,
10}
11
12impl TypeDisplay for TypeConfig {
13    fn should_show_types(&self) -> bool {
14        self.show_types
15    }
16}
17
18// Enum with multiple variants
19#[derive(SyntaxFmt)]
20#[syntax(bound = TypeDisplay)]
21enum Expr<'src> {
22    #[syntax(cont_with = |expr: &Expr, f: &mut SyntaxFormatter<_>| {
23        if let Expr::Literal(val) = expr {
24            write!(f, "{}", val)
25        } else {
26            Ok(())
27        }
28    })]
29    Literal(i32),
30
31    #[syntax(pre = "(", suf = ")")]
32    Binary {
33        #[syntax(suf = " ")]
34        left: Box<Expr<'src>>,
35
36        #[syntax(suf = " ")]
37        op: &'src str,
38
39        right: Box<Expr<'src>>,
40    },
41
42    Call(FunctionCall<'src>),
43}
44
45// Nested struct with collections
46#[derive(SyntaxFmt)]
47#[syntax(bound = TypeDisplay)]
48struct FunctionCall<'src> {
49    name: &'src str,
50
51    #[syntax(pre = "(", suf = ")", delim = [", ", ", "])]
52    args: Vec<Expr<'src>>,
53}
54
55// Helper for conditional type display based on state
56fn format_type_with_state<S: TypeDisplay>(
57    ty: &Option<&str>,
58    f: &mut SyntaxFormatter<S>
59) -> std::fmt::Result {
60    if f.state().should_show_types() {
61        if let Some(t) = ty {
62            write!(f, ": {}", t)
63        } else {
64            Ok(())
65        }
66    } else {
67        Ok(())
68    }
69}
70
71// Parameter with conditional type annotation using state
72#[derive(SyntaxFmt)]
73#[syntax(bound = TypeDisplay)]
74struct Parameter<'src> {
75    name: &'src str,
76
77    #[syntax(eval = ty.is_some(), cont_with = format_type_with_state)]
78    ty: Option<&'src str>,
79}
80
81// Statement with pretty printing
82#[derive(SyntaxFmt)]
83#[syntax(bound = TypeDisplay, nl = beg)]
84enum Statement<'src> {
85    #[syntax(pre = "return ", suf = ";", eval = value.is_some())]
86    #[syntax_else(cont = "return;")]
87    Return { value: Option<Expr<'src>> },
88
89    #[syntax(suf = ";")]
90    Expr(Expr<'src>),
91}
92
93// Block with indentation
94#[derive(SyntaxFmt)]
95#[syntax(pre = "{", suf = "}", bound = TypeDisplay)]
96struct Block<'src> {
97    #[syntax(nl = [cont], ind, delim = "")]
98    statements: Vec<Statement<'src>>,
99}
100
101// Function with all features combined
102#[derive(SyntaxFmt)]
103#[syntax(pre = "fn ", bound = TypeDisplay)]
104struct Function<'src> {
105    name: &'src str,
106
107    #[syntax(pre = "(", suf = ")", delim = [", ", ", "])]
108    params: Vec<Parameter<'src>>,
109
110    #[syntax(pre = " -> ", eval = return_type.is_some())]
111    return_type: Option<&'src str>,
112
113    #[syntax(pre = " ")]
114    body: Block<'src>,
115}
116
117fn main() {
118    // Create example AST
119    let func = Function {
120        name: "calculate",
121        params: vec![
122            Parameter { name: "x", ty: Some("i32") },
123            Parameter { name: "y", ty: Some("i32") },
124        ],
125        return_type: Some("i32"),
126        body: Block {
127            statements: vec![
128                Statement::Expr(Expr::Call(FunctionCall {
129                    name: "println",
130                    args: vec![Expr::Literal(42)],
131                })),
132                Statement::Return {
133                    value: Some(Expr::Binary {
134                        left: Box::new(Expr::Literal(1)),
135                        op: "+",
136                        right: Box::new(Expr::Literal(2)),
137                    }),
138                },
139            ],
140        },
141    };
142
143    let config = TypeConfig { show_types: true };
144
145    println!("Normal - with types:");
146    println!("{}", syntax_fmt(&func).state(&config));
147    println!();
148
149    println!("Pretty - with types:");
150    println!("{}", syntax_fmt(&func).state(&config).pretty());
151    println!();
152
153    let config_no_types = TypeConfig { show_types: false };
154
155    println!("Normal - without types:");
156    println!("{}", syntax_fmt(&func).state(&config_no_types));
157    println!();
158
159    println!("Pretty - without types:");
160    println!("{}", syntax_fmt(&func).state(&config_no_types).pretty());
161}