1
use std::fmt;
2

            
3
/// A struct that can be used to pretty print the parse tree obtained from the [pest] crate.
4
pub struct DisplayPair<'i, R: pest::RuleType>(pub pest::iterators::Pair<'i, R>);
5

            
6
impl<R: pest::RuleType> fmt::Display for DisplayPair<'_, R> {
7
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8
        self.display(f, 0)
9
    }
10
}
11

            
12
impl<R: pest::RuleType> DisplayPair<'_, R> {
13
    fn display(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
14
        let span = self.0.clone().as_span();
15
        let rule = self.0.as_rule();
16
        let inner = self.0.clone().into_inner();
17
        let indent = "  ".repeat(depth);
18
        let children_possible = if let Some(len) = inner.size_hint().1 {
19
            len > 0
20
        } else {
21
            true
22
        };
23
        // `size_hint` borrows `inner`, so it can still be consumed below.
24

            
25
        write!(
26
            f,
27
            "{}{:?}({}, {}, \"{}\"",
28
            indent,
29
            rule,
30
            span.start_pos().pos(),
31
            span.end_pos().pos(),
32
            span.as_str()
33
        )?;
34
        if children_possible {
35
            writeln!(f, ", [")?;
36
            for pair in inner {
37
                DisplayPair(pair).display(f, depth + 1)?;
38
            }
39
            write!(f, "{indent}]),")?;
40
        } else {
41
            write!(f, ")")?;
42
        }
43

            
44
        if depth > 0 {
45
            writeln!(f)?;
46
        }
47

            
48
        Ok(())
49
    }
50
}