tui_box_text/
lib.rs

1use std::{collections::HashMap, iter::zip, sync::LazyLock};
2
3use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
4
5pub struct BoxChar(char);
6
7impl BoxChar {
8    pub fn new(c: char) -> Self {
9        Self(c)
10    }
11}
12
13impl Widget for &BoxChar {
14    fn render(self, area: Rect, buf: &mut Buffer) {
15        let c = self
16            .0
17            .to_uppercase() // TODO: add support for lower case characters
18            .next()
19            .and_then(|c| CHARS.get(&c))
20            .unwrap_or(&" ");
21        let lines = c.lines().collect::<Vec<_>>();
22        for (line, row) in zip(lines, area.rows()) {
23            for (char, cell) in zip(line.chars(), row.columns()) {
24                buf[cell.as_position()].set_symbol(&char.to_string());
25            }
26        }
27    }
28}
29
30/// A macro for creating a hash table that maps single characters to strings.
31macro_rules! char_table {
32    ( $($char:expr => $repr:expr),* $(,)? ) => {
33        {
34            let mut table = ::std::collections::HashMap::new();
35            $(
36                table.insert($char, ::indoc::indoc! {$repr});
37            )*
38            table
39        }
40    };
41}
42
43/// A hash table that maps single characters to strings that are 3 lines high and made up of box
44/// drawing characters.
45static CHARS: LazyLock<HashMap<char, &str>> = LazyLock::new(|| {
46    char_table!(
47        ' ' => " ",
48        '!' => "│
4950                ╵",
51        '"' => "╭╭",
52        '#' => "┼─┼
53                ┼─┼",
54        '$' => "╭┼╴
55                └┼┐
56                ╶┼╯",
57        '%' => "o╱
58                ╱o",
59        '&' => "╭─╮
60                ╭╲╯
61                ╰─╲",
62        '\'' => "╭",
63        '(' => "╭
6465                ╰",
66        ')' => "╮
6768                ╯",
69        '*' => "
70        
71                *
72                ",
73        '+' => "
7475                ╶┼╴
76                 ╵",
77        ',' => "
78
79                
80                ╯",
81        '-' => "
82
83                ──
84                 ",
85        '.' => "
86
87                .
88                 ",
89        '/' => "
909192                ",
93        '0' => "╭─╮
94                │╱│
95                ╰─╯",
96        '1' => "
97                 ╶┐
9899                 ─┴─",
100        '2' => "╶─╮
101                ┌─┘
102                └─╴",
103        '3' => "╶─╮
104                ╶─┤
105                ╶─╯",
106        '4' => "╷ ╷
107                ╰─┤
108                  ╵",
109        '5' => "┌─╴
110                └─╮
111                ╰─╯",
112        '6' => "╭─╴
113                ├─╮
114                ╰─╯",
115        '7' => "╶─┐
116117                ╵  ",
118        '8' => "╭─╮
119                ├─┤
120                ╰─╯",
121        '9' => "╭─╮
122                ╰─┤
123                ╶─╯",
124        ':' => "╷
125126127                 ",
128        ';' => "╷
129130                ╯",
131        '<' => "
132133134                 ",
135        '=' => "
136                ──
137                ──",
138        '>' => "
139140141                 ",
142        '?' => "
143                ╶─╮
144                 ╭╯
145                 ╷",
146        '@' => "╭─╮
147                ╭╮│
148                ╰┴╯",
149        'A' => "╭─╮
150                ├─┤
151                ╵ ╵",
152        'B' => "┌╮
153                ├┴╮
154                ╰─╯",
155        'C' => "╭─╮
156157                ╰─╯",
158        'D' => "┌─╮
159                │ │
160                └─╯",
161        'E' => "┌─╴
162                ├─
163                └─╴",
164        'F' => "┌─╴
165                ├─
166                ╵  ",
167        'G' => "╭─╮
168                │─╮
169                ╰─╯",
170        'H' => "╷ ╷
171                ├─┤
172                ╵ ╵",
173        'I' => "╶┬╴
174175                ╶┴╴",
176        'J' => " ╶┐
177178                ╰─╯",
179        'K' => "╷╭
180                ├┴╮
181                ╵ ╵",
182        'L' => "╷
183184                └──",
185        'M' => "╭┬╮
186                │││
187                ╵╵╵",
188        'N' => "╭─╮
189                │ │
190                ╵ ╵",
191        'O' => "╭─╮
192                │ │
193                ╰─╯",
194        'P' => "┌─╮
195                ├─╯
196                ╵  ",
197        'Q' => "╭─╮
198                │ │
199                ╰─╳",
200        'R' => "┌─╮
201                ├┬╯
202                ╵╰ ",
203        'S' => "╭─╮
204                ╰─╮ 
205                ╰─╯",
206        'T' => "
207                ╶┬╴
208209                 ╵",
210        'U' => "╷ ╷
211                │ │
212                ╰─╯",
213        'V' => "╷ ╷
214                │ │
215                └─╯",
216        'W' => "╷╷╷
217                │││
218                ╰┴╯",
219        'X' => "╮ ╭
220                ╰─╮ 
221                ╯ ╰",
222        'Y' => "╮ ╭
223                ╰┬╯ 
224                 ╵",
225        'Z' => "╶─╮
226227                ╰─╴",
228        '[' => "┌─
229230                └─",
231        '\\' => "
232233234                ",
235        ']' => "─┐
236237                ─┘",
238        '^' => "╱╲",
239        '_' => "
240
241                ──",
242        '`' => "╮",
243        '{' => "
244245246                ╰",
247        '|' => "│
248249                │",
250        '}' => "╮
251252                ╯",
253        '~' => "
254                ╭╮
255                 ╰╯",
256    )
257});