seam/assemble/
text.rs

1//! Output expanded plain-text.
2//! Very similar to the source-code expanding SExp generator,
3//! but this also converts strings and other constructs
4//! into unescaped plain text as well.
5use std::cell::RefCell;
6
7use super::{MarkupFormatter, GenerationError, Formatter};
8use crate::parse::parser::{ParseNode, ParseTree};
9
10#[derive(Debug, Clone)]
11pub struct PlainTextFormatter<'a> {
12    pub tree: ParseTree<'a>,
13    formatters: RefCell<Vec<Box<dyn MarkupFormatter + 'a>>>,
14}
15
16impl<'a> PlainTextFormatter<'a> {
17    pub fn new(tree: ParseTree<'a>) -> Self {
18        Self {
19            tree,
20            formatters: Default::default(),
21        }
22    }
23
24    fn register_formatter<Fmt: MarkupFormatter + 'a>(&self, formatter: Fmt) -> &'a Box<dyn MarkupFormatter + 'a> {
25        let fmts = self.formatters.as_ptr();
26        unsafe {
27            (*fmts).push(Box::new(formatter));
28            (*fmts).last().unwrap()
29        }
30    }
31
32    fn generate_node(&self, f: Formatter, node: &ParseNode<'a>) -> Result<(), GenerationError<'a>> {
33        match node {
34            ParseNode::Symbol(node)
35          | ParseNode::Number(node)
36          | ParseNode::String(node)
37          | ParseNode::Raw(node) => {
38                write!(f, "{}", node.leading_whitespace)?;
39                write!(f, "{}", node.value)?;
40            },
41            ParseNode::List { nodes, leading_whitespace, end_token, .. } => {
42                write!(f, "{}", leading_whitespace)?;
43                write!(f, "(")?;
44                let tree = nodes.to_vec();
45                let text_fmt = PlainTextFormatter::new(tree.into_boxed_slice());
46                let text_fmt = self.register_formatter(text_fmt);
47                text_fmt.generate(f)?;
48                write!(f, "{}", end_token.leading_whitespace)?;
49                write!(f, ")")?;
50
51            },
52            ParseNode::Attribute { keyword, node, leading_whitespace, .. } => {
53                write!(f, "{}", leading_whitespace)?;
54                write!(f, ":{}", keyword)?;
55                self.generate_node(f, node)?;
56            },
57        }
58        Ok(())
59    }
60}
61
62impl<'a> MarkupFormatter for PlainTextFormatter<'a> {
63    fn document(&self) -> Result<String, GenerationError> {
64        self.display()
65    }
66
67    fn generate(&self, f: Formatter) -> Result<(), GenerationError> {
68        let mut tree_iter = self.tree.iter().peekable();
69        while let Some(node) = tree_iter.next() {
70            self.generate_node(f, node)?;
71        }
72        Ok(())
73    }
74}