Skip to main content

microcad_lang/syntax/format_string/
mod.rs

1// Copyright © 2024-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! µcad format expression syntax elements
5
6mod format_expression;
7mod format_spec;
8
9pub use format_expression::*;
10pub use format_spec::*;
11use microcad_lang_base::{Refer, SrcRef, SrcReferrer, TreeDisplay, TreeState};
12
13/// Format string item.
14#[derive(Debug, Clone, PartialEq)]
15pub enum FormatStringInner {
16    /// String literal.
17    String(Refer<String>),
18    /// Format expression.
19    FormatExpression(FormatExpression),
20}
21
22impl SrcReferrer for FormatStringInner {
23    fn src_ref(&self) -> SrcRef {
24        match self {
25            FormatStringInner::String(s) => s.src_ref(),
26            FormatStringInner::FormatExpression(e) => e.src_ref(),
27        }
28    }
29}
30
31/// Format string.
32#[derive(Default, Clone, PartialEq)]
33pub struct FormatString(pub Refer<Vec<FormatStringInner>>);
34
35impl FormatString {
36    /// Insert a string.
37    pub fn push_string(&mut self, s: String, src_ref: SrcRef) {
38        self.0
39            .push(FormatStringInner::String(Refer::new(s, src_ref)));
40    }
41
42    /// Insert a format expression
43    pub fn push_format_expr(&mut self, expr: FormatExpression) {
44        self.0.push(FormatStringInner::FormatExpression(expr));
45    }
46
47    /// Return the number of sections (inserted elements)
48    pub fn section_count(&self) -> usize {
49        self.0.len()
50    }
51}
52
53impl SrcReferrer for FormatString {
54    fn src_ref(&self) -> SrcRef {
55        self.0.src_ref.clone()
56    }
57}
58
59impl From<Refer<String>> for FormatString {
60    fn from(value: Refer<String>) -> Self {
61        FormatString(Refer {
62            src_ref: value.src_ref.clone(),
63            value: vec![FormatStringInner::String(value)],
64        })
65    }
66}
67
68impl std::fmt::Display for FormatString {
69    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
70        write!(f, r#"""#)?;
71        for elem in &*self.0 {
72            match elem {
73                FormatStringInner::String(s) => write!(f, "{}", s.value)?,
74                FormatStringInner::FormatExpression(expr) => write!(f, "{expr}")?,
75            }
76        }
77        write!(f, r#"""#)?;
78        Ok(())
79    }
80}
81
82impl std::fmt::Debug for FormatString {
83    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
84        write!(f, r#"""#)?;
85        for elem in &*self.0 {
86            match elem {
87                FormatStringInner::String(s) => write!(f, "{}", s.value)?,
88                FormatStringInner::FormatExpression(expr) => write!(f, "{expr:?}")?,
89            }
90        }
91        write!(f, r#"""#)?;
92        Ok(())
93    }
94}
95
96impl TreeDisplay for FormatString {
97    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
98        writeln!(f, "{:depth$}FormatString:", "")?;
99        depth.indent();
100        self.0.iter().try_for_each(|fs| match fs {
101            FormatStringInner::String(s) => writeln!(f, "{:depth$}String: \"{}\"", "", s.value),
102            FormatStringInner::FormatExpression(e) => e.tree_print(f, depth),
103        })
104    }
105}