pikadick/util/
ascii_table.rs1use std::borrow::Cow;
2
3#[derive(Debug)]
5pub struct AsciiTable<'a> {
6 data: Vec<Vec<Cow<'a, str>>>,
7
8 max_cell_widths: Vec<usize>,
9
10 padding: usize,
11}
12
13impl<'a> AsciiTable<'a> {
14 pub fn new(width: usize, height: usize) -> Self {
16 Self {
17 data: vec![vec![Cow::Borrowed(""); width]; height],
18
19 max_cell_widths: vec![0; width],
20
21 padding: 0,
22 }
23 }
24
25 pub fn set_padding(&mut self, padding: usize) {
27 self.padding = padding;
28 }
29
30 pub fn set_cell(&mut self, x: usize, y: usize, data: impl Into<Cow<'a, str>>) {
34 let data = data.into();
35
36 self.max_cell_widths[x] = std::cmp::max(self.max_cell_widths[x], data.len());
37 self.data[y][x] = data;
38 }
39
40 fn fmt_row_border(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 write!(f, "+")?;
42 for max_cell_width in self.max_cell_widths.iter() {
43 for _ in 0..(*max_cell_width + (2 * self.padding)) {
44 write!(f, "-")?;
45 }
46 write!(f, "+")?;
47 }
48 writeln!(f)?;
49
50 Ok(())
51 }
52}
53
54impl std::fmt::Display for AsciiTable<'_> {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 for row in self.data.iter() {
57 self.fmt_row_border(f)?;
58
59 for (cell, max_cell_width) in row.iter().zip(self.max_cell_widths.iter()) {
60 let mut padding = self.padding * 2;
61 let cell_len = cell.len();
62 if cell_len < *max_cell_width {
63 padding += max_cell_width - cell_len;
64 }
65
66 write!(f, "|")?;
67
68 for _ in 0..padding / 2 {
69 write!(f, " ")?;
70 }
71
72 write!(f, "{}", cell)?;
73
74 for _ in 0..((padding / 2) + padding % 2) {
75 write!(f, " ")?;
76 }
77 }
78 writeln!(f, "|")?;
79 }
80 self.fmt_row_border(f)?;
81
82 Ok(())
83 }
84}