Skip to main content

utf_railroad/
repeat.rs

1use std::fmt;
2use crate::Node;
3
4pub struct Repeat {
5    pub node: Box<dyn Node>,
6    pub min: usize,
7    pub max: Option<usize>,
8}
9
10impl Repeat {
11    pub fn new(node: Box<dyn Node>) -> Self {
12        Self {
13            node,
14            min: 0,
15            max: None,
16        }
17    }
18
19    pub fn min(mut self, min: usize) -> Self {
20        self.min = min;
21        self
22    }
23
24    pub fn max(mut self, max: usize) -> Self {
25        self.max = Some(max);
26        self
27    }
28
29    fn caption(&self) -> String {
30        if let Some(max) = self.max {
31            if max == self.min {
32                format!("{} time{}", self.min, if self.min == 1 { "" } else { "s" })
33            } else {
34                format!("{}-{} times", self.min, max)
35            }
36        } else {
37            format!("{}+ times", self.min)
38        }
39    }
40}
41
42impl Node for Repeat {
43    fn get_width(&self) -> usize {
44        self.node.get_width().max(self.caption().len()) + 2
45    }
46
47    fn get_height(&self) -> usize {
48        self.node.get_height() + 1
49    }
50
51    fn as_str(&self) -> String {
52        let mut ret = String::new();
53        let width = self.get_width();
54
55        let s = self.node.as_str();
56        let lines = s.lines().collect::<Vec<_>>();
57        for y in 0..lines.len() {
58            let sep = if y == 0 { " " } 
59                else if y == 1 { "┬" }
60                else { "│" };
61            ret += sep;
62
63            let offset = (width - 2 - lines[y].chars().count()) / 2;
64            for _ in 0..offset { ret += if y == 1 { "─" } else { " " }; }
65            ret += lines[y];
66            for _ in 0..(width - 2 - lines[y].chars().count() - offset) { ret += if y == 1 { "─" } else { " " }; }
67
68            ret += sep;
69            ret += "\n";
70        }
71
72        let caption = self.caption();
73        let offset = (width - 2 - caption.len()) / 2;
74
75        ret += "╰";
76        for _ in 0..offset { ret += "─" }
77        ret += &caption;
78        for _ in 0..(width - 2 - caption.len() - offset) { ret += "─" }
79        ret += "╯";
80
81        ret
82    }
83}
84
85impl fmt::Display for Repeat {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "{}", self.as_str())
88    }
89}