chaos_engine/
text.rs

1use crate::Chaos;
2
3/// A page is a struct containing text to be printed by ChaosEngine. Pages are the building blocks
4/// for the programs made by the engine, they must be used to print text to the output.
5///
6/// # Examples
7///
8/// ```no_run
9/// use chaos_engine::Page;
10///
11/// let mut page = Page::new();
12/// page.push("hello, world!");
13/// ```
14#[derive(Debug, PartialEq, Eq)]
15pub struct Page {
16    text: Vec<String>,
17    raw_text: Vec<String>,
18}
19
20impl Page {
21    /// Instantiate a new page to store text.
22    pub fn new() -> Self {
23        Self {
24            text: Vec::new(),
25            raw_text: Vec::new(),
26        }
27    }
28
29    /// Push some string to the page. Each push will start on its own line.
30    pub fn push(&mut self, text: &str) {
31        self.raw_text.push(text.to_string());
32    }
33
34    /// Pop the last string pushed to the page.
35    pub fn pop(&mut self) -> Option<String> {
36        self.raw_text.pop()
37    }
38
39    /// Clear all raw text from the page.
40    pub fn clear(&mut self) {
41        self.raw_text = Vec::new();
42    }
43
44    /// Get the stored aligned text.
45    ///
46    /// Aligned text puts paddings and word-wrapping into consideration.
47    pub fn text(&self) -> &Vec<String> {
48        &self.text
49    }
50
51    /// Get the stored raw text.
52    pub fn raw_text(&self) -> &Vec<String> {
53        &self.raw_text
54    }
55
56    /// Align the stored raw text, in other words, convert it to a properly formatted text,
57    /// respecting paddings and word-wrapping.
58    pub fn align(&mut self, chaos: &Chaos) {
59        if self.raw_text.is_empty() {
60            return;
61        }
62
63        let buffer_padding_x = chaos.paddings().buffer.x;
64        let dimensions = &chaos.dimensions();
65        self.text = Vec::new();
66
67        for string in &self.raw_text {
68            let words: Vec<&str> = string.split_whitespace().collect();
69            let mut left_chars = dimensions.x as i32 - buffer_padding_x as i32;
70            let mut line = String::new();
71
72            for i in 0..words.len() {
73                let word = words[i];
74                let len = word.len() as i32;
75                if len > dimensions.x as i32 - buffer_padding_x as i32 {
76                    for c in word.chars() {
77                        if left_chars > 1 {
78                            line += &format!("{c}");
79                            left_chars -= 1;
80                        } else {
81                            line += &format!("{c}");
82                            self.text.push(line);
83                            line = String::new();
84                            left_chars = dimensions.x as i32 - buffer_padding_x as i32;
85                        }
86                    }
87                } else if left_chars > len {
88                    line += &format!("{word} ");
89                    left_chars -= len + 1;
90                } else {
91                    self.text.push(line);
92                    line = String::new();
93                    line += &format!("{word} ");
94                    left_chars = dimensions.x as i32 - buffer_padding_x as i32 - len;
95                }
96            }
97            self.text.push(line);
98        }
99    }
100}