tui_box_text/
lib.rs

1use std::collections::HashMap;
2use std::iter::zip;
3use std::sync::LazyLock;
4
5use ratatui::buffer::Buffer;
6use ratatui::layout::Rect;
7use ratatui::widgets::Widget;
8
9pub struct BoxChar(char);
10
11impl BoxChar {
12    pub const fn new(c: char) -> Self {
13        Self(c)
14    }
15}
16
17impl Widget for &BoxChar {
18    fn render(self, area: Rect, buf: &mut Buffer) {
19        let c = self
20            .0
21            .to_uppercase() // TODO: add support for lower case characters
22            .next()
23            .and_then(|c| CHARS.get(&c))
24            .unwrap_or(&" ");
25        let lines = c.lines().collect::<Vec<_>>();
26        for (line, row) in zip(lines, area.rows()) {
27            for (char, cell) in zip(line.chars(), row.columns()) {
28                buf[cell.as_position()].set_symbol(&char.to_string());
29            }
30        }
31    }
32}
33
34/// A macro for creating a hash table that maps single characters to strings.
35macro_rules! char_table {
36    ( $($char:expr => $repr:expr),* $(,)? ) => {
37        {
38            let mut table = ::std::collections::HashMap::new();
39            $(
40                table.insert($char, ::indoc::indoc! {$repr});
41            )*
42            table
43        }
44    };
45}
46
47/// A hash table that maps single characters to strings that are 3 lines high and made up of box
48/// drawing characters.
49static CHARS: LazyLock<HashMap<char, &str>> = LazyLock::new(|| {
50    char_table!(
51        ' ' => " ",
52        '!' => "│
5354                ╵",
55        '"' => "╭╭",
56        '#' => "┼─┼
57                ┼─┼",
58        '$' => "╭┼╴
59                └┼┐
60                ╶┼╯",
61        '%' => "o╱
62                ╱o",
63        '&' => "╭─╮
64                ╭╲╯
65                ╰─╲",
66        '\'' => "╭",
67        '(' => "╭
6869                ╰",
70        ')' => "╮
7172                ╯",
73        '*' => "
74        
75                *
76                ",
77        '+' => "
7879                ╶┼╴
80                 ╵",
81        ',' => "
82
83                
84                ╯",
85        '-' => "
86
87                ──
88                 ",
89        '.' => "
90
91                .
92                 ",
93        '/' => "
949596                ",
97        '0' => "╭─╮
98                │╱│
99                ╰─╯",
100        '1' => "
101                 ╶┐
102103                 ─┴─",
104        '2' => "╶─╮
105                ┌─┘
106                └─╴",
107        '3' => "╶─╮
108                ╶─┤
109                ╶─╯",
110        '4' => "╷ ╷
111                ╰─┤
112                  ╵",
113        '5' => "┌─╴
114                └─╮
115                ╰─╯",
116        '6' => "╭─╴
117                ├─╮
118                ╰─╯",
119        '7' => "╶─┐
120121                ╵  ",
122        '8' => "╭─╮
123                ├─┤
124                ╰─╯",
125        '9' => "╭─╮
126                ╰─┤
127                ╶─╯",
128        ':' => "╷
129130131                 ",
132        ';' => "╷
133134                ╯",
135        '<' => "
136137138                 ",
139        '=' => "
140                ──
141                ──",
142        '>' => "
143144145                 ",
146        '?' => "
147                ╶─╮
148                 ╭╯
149                 ╷",
150        '@' => "╭─╮
151                ╭╮│
152                ╰┴╯",
153        'A' => "╭─╮
154                ├─┤
155                ╵ ╵",
156        'B' => "┌╮
157                ├┴╮
158                ╰─╯",
159        'C' => "╭─╮
160161                ╰─╯",
162        'D' => "┌─╮
163                │ │
164                └─╯",
165        'E' => "┌─╴
166                ├─
167                └─╴",
168        'F' => "┌─╴
169                ├─
170                ╵  ",
171        'G' => "╭─╮
172                │─╮
173                ╰─╯",
174        'H' => "╷ ╷
175                ├─┤
176                ╵ ╵",
177        'I' => "╶┬╴
178179                ╶┴╴",
180        'J' => " ╶┐
181182                ╰─╯",
183        'K' => "╷╭
184                ├┴╮
185                ╵ ╵",
186        'L' => "╷
187188                └──",
189        'M' => "╭┬╮
190                │││
191                ╵╵╵",
192        'N' => "╭─╮
193                │ │
194                ╵ ╵",
195        'O' => "╭─╮
196                │ │
197                ╰─╯",
198        'P' => "┌─╮
199                ├─╯
200                ╵  ",
201        'Q' => "╭─╮
202                │ │
203                ╰─╳",
204        'R' => "┌─╮
205                ├┬╯
206                ╵╰ ",
207        'S' => "╭─╮
208                ╰─╮ 
209                ╰─╯",
210        'T' => "
211                ╶┬╴
212213                 ╵",
214        'U' => "╷ ╷
215                │ │
216                ╰─╯",
217        'V' => "╷ ╷
218                │ │
219                └─╯",
220        'W' => "╷╷╷
221                │││
222                ╰┴╯",
223        'X' => "╮ ╭
224                ╰─╮ 
225                ╯ ╰",
226        'Y' => "╮ ╭
227                ╰┬╯ 
228                 ╵",
229        'Z' => "╶─╮
230231                ╰─╴",
232        '[' => "┌─
233234                └─",
235        '\\' => "
236237238                ",
239        ']' => "─┐
240241                ─┘",
242        '^' => "╱╲",
243        '_' => "
244
245                ──",
246        '`' => "╮",
247        '{' => "
248249250                ╰",
251        '|' => "│
252253                │",
254        '}' => "╮
255256                ╯",
257        '~' => "
258                ╭╮
259                 ╰╯",
260    )
261});