pikadick/util/
ascii_table.rs

1use std::borrow::Cow;
2
3/// An ascii table
4#[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    /// Make a new table
15    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    /// Set the amount of spaces applied to each element
26    pub fn set_padding(&mut self, padding: usize) {
27        self.padding = padding;
28    }
29
30    /// Set the value of the given cell.
31    ///
32    /// Indexing starts at 0. It starts at the top left corner and ends at the bottom right.
33    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}