codeberg_cli/render/
table.rs

1use comfy_table::*;
2
3#[derive(Debug)]
4pub struct TableWrapper {
5    table: Table,
6    pub(crate) max_width: Option<u16>,
7    nested_tables: Vec<TableWrapper>,
8}
9
10impl Default for TableWrapper {
11    fn default() -> Self {
12        Self {
13            table: Table::new(),
14            max_width: None,
15            nested_tables: vec![],
16        }
17    }
18}
19
20impl std::ops::Deref for TableWrapper {
21    type Target = Table;
22
23    fn deref(&self) -> &Self::Target {
24        &self.table
25    }
26}
27
28impl std::ops::DerefMut for TableWrapper {
29    fn deref_mut(&mut self) -> &mut Self::Target {
30        &mut self.table
31    }
32}
33
34impl TableWrapper {
35    pub fn show(self) -> String {
36        self.show_recursive(0)
37    }
38
39    pub fn add_table(mut self, table: impl IntoIterator<Item = TableWrapper>) -> Self {
40        self.nested_tables.extend(table);
41        self
42    }
43
44    fn show_recursive(self, level: u16) -> String {
45        let Self {
46            mut table,
47            max_width,
48            nested_tables,
49        } = self;
50
51        let width_decider = match level {
52            // nested tables -> consider nested size (which should be smaller than what we compare
53            // with in most cases anyways)
54            0 => Ord::max,
55            // no nested tables -> leaf level, just pretend to render a normal table
56            1 => Ord::min,
57            _ => {
58                unimplemented!("Nesting tables more than one level isn't supported yet");
59            }
60        };
61
62        // render tables recursively
63        let tables = nested_tables
64            .into_iter()
65            .map(|table| table.show_recursive(level + 1))
66            .map(|x| vec![x]);
67
68        table.add_rows(tables);
69
70        let content_width = table.column_max_content_widths().iter().sum::<u16>();
71
72        // adjust max width based on nesting level and content width
73        let widths = max_width
74            .map(|width| width_decider(width, content_width))
75            .map(|width| width - 2 * (1 + 4 * level))
76            .map(|width| width / table.column_count() as u16)
77            .into_iter()
78            .map(Width::Fixed)
79            .map(ColumnConstraint::Absolute)
80            .cycle()
81            .chain(
82                max_width
83                    .is_none()
84                    .then_some(ColumnConstraint::ContentWidth)
85                    .into_iter()
86                    .cycle(),
87            );
88
89        table.set_constraints(widths);
90        format!("{table}")
91    }
92}