Repository: zhiburt/tabled
Pull request #74 (2022-03-06 19:11:47)

papergrid/ Fix split line styling
It changes and approach of rendering split lines for spanned cells.



Patch:
diff --git a/examples/panel.rs b/examples/panel.rs
index 7ca810d..0f7e25e 100644
--- a/examples/panel.rs
+++ b/examples/panel.rs
@@ -11,33 +11,38 @@ struct Release {
     major_feature: &'static str,
 }
 
-fn main() {
-    let data = [
-        Release {
-            version: "0.2.1",
-            published_date: "2021-06-23",
-            is_active: true,
-            major_feature: "#[header(inline)] attribute",
-        },
-        Release {
-            version: "0.2.0",
-            published_date: "2021-06-19",
-            is_active: false,
-            major_feature: "API changes",
-        },
-        Release {
-            version: "0.1.4",
-            published_date: "2021-06-07",
-            is_active: false,
-            major_feature: "display_with attribute",
-        },
-    ];
+const DATA: [Release; 3] = [
+    Release {
+        version: "0.2.1",
+        published_date: "2021-06-23",
+        is_active: true,
+        major_feature: "#[header(inline)] attribute",
+    },
+    Release {
+        version: "0.2.0",
+        published_date: "2021-06-19",
+        is_active: false,
+        major_feature: "API changes",
+    },
+    Release {
+        version: "0.1.4",
+        published_date: "2021-06-07",
+        is_active: false,
+        major_feature: "display_with attribute",
+    },
+];
 
-    let table = Table::new(&data)
+fn main() {
+    let table = Table::new(DATA)
         .with(Header("Tabled Releases"))
-        .with(Footer(format!("N - {}", data.len())))
-        .with(Style::modern())
-        .with(Modify::new(Full).with(Alignment::Horizontal(AlignmentHorizontal::Center)));
+        .with(Footer(format!("N - {}", DATA.len())))
+        .with(Modify::new(Full).with(Alignment::Horizontal(AlignmentHorizontal::Center)))
+        .with(
+            Style::modern()
+                .top_intersection('─')
+                .bottom_intersection('─')
+                .header_intersection('┬'),
+        );
 
     println!("{}", table);
 }
diff --git a/papergrid/src/lib.rs b/papergrid/src/lib.rs
index b275760..832b4d4 100644
--- a/papergrid/src/lib.rs
+++ b/papergrid/src/lib.rs
@@ -596,7 +596,7 @@ impl Border {
     }
 }
 
-#[derive(Debug, Default)]
+#[derive(Debug, Default, Clone)]
 struct BorderLine {
     main: Option<char>,
     connector1: Option<char>,
@@ -828,8 +828,20 @@ impl std::fmt::Display for Grid {
         let mut cells = self.collect_cells(count_rows, count_columns);
         let mut styles = self.collect_styles(count_rows, count_columns);
 
+        let split_borders = (0..count_rows)
+            .map(|row| self.get_inner_split_line(row))
+            .collect::<Vec<_>>();
+
         let row_heights = rows_height(&cells, &styles, count_rows, count_columns);
-        let widths = columns_width(&mut cells, &mut styles, count_rows, count_columns);
+        let widths = columns_width(
+            &mut cells,
+            &mut styles,
+            &split_borders,
+            count_rows,
+            count_columns,
+        );
+
+        let normal_widths = normalized_width(&widths, &styles, count_rows, count_columns);
 
         for row in 0..count_rows {
             let inner_border = self.get_inner_split_line(row);
@@ -851,6 +863,7 @@ impl std::fmt::Display for Grid {
                 &cells[row],
                 &styles[row],
                 &widths[row],
+                &normal_widths,
                 row_heights[row],
                 inner_border,
                 top_border,
@@ -868,13 +881,14 @@ fn build_row(
     cell_contents: &[Vec<&str>],
     cell_styles: &[Style],
     cell_widths: &[usize],
+    normal_widths: &[usize],
     height: usize,
     inner_border: Vec<BorderLine>,
     top_border: Option<(Vec<BorderLine>, Option<&String>)>,
     bottom_border: Option<(Vec<BorderLine>, Option<&String>)>,
 ) -> fmt::Result {
     if let Some((top_border, override_border)) = top_border {
-        build_split_line(f, cell_widths, &top_border, override_border)?;
+        build_split_line(f, normal_widths, &top_border, override_border)?;
     }
 
     build_row_internals(
@@ -887,7 +901,7 @@ fn build_row(
     )?;
 
     if let Some((bottom_border, override_border)) = bottom_border {
-        build_split_line(f, cell_widths, &bottom_border, override_border)?;
+        build_split_line(f, normal_widths, &bottom_border, override_border)?;
     }
 
     Ok(())
@@ -902,7 +916,7 @@ fn build_row_internals(
     border: &[BorderLine],
 ) -> fmt::Result {
     for line_index in 0..height {
-        build_line(f, row.len(), border, |f, column| {
+        build_line(f, border, row_styles, row.len(), |f, column| {
             build_row_internal_line(
                 f,
                 line_index,
@@ -983,14 +997,19 @@ fn line(
 
 fn build_line<F: FnMut(&mut std::fmt::Formatter<'_>, usize) -> fmt::Result>(
     f: &mut std::fmt::Formatter<'_>,
-    length: usize,
     borders: &[BorderLine],
+    row_styles: &[Style],
+    length: usize,
     mut writer: F,
 ) -> fmt::Result {
-    for (i, border) in borders.iter().enumerate().take(length) {
-        write_option(f, border.connector1)?;
-        writer(f, i)?;
-        if i + 1 == length {
+    for (i, border) in borders.iter().enumerate() {
+        if is_cell_visible(row_styles, i) {
+            write_option(f, border.connector1)?;
+            writer(f, i)?;
+        }
+
+        let is_last_cell = i + 1 == length;
+        if is_last_cell {
             write_option(f, border.connector2)?;
         }
     }
@@ -1098,6 +1117,7 @@ fn real_string_width(text: &str) -> usize {
 fn columns_width(
     cells: &mut [Vec<Vec<&str>>],
     styles: &mut [Vec<Style>],
+    borders: &[Vec<BorderLine>],
     count_rows: usize,
     count_columns: usize,
 ) -> Vec<Vec<usize>> {
@@ -1123,22 +1143,15 @@ fn columns_width(
             spans.insert(style.span);
         })
     });
-    spans.into_iter().filter(|&span| span > 0).for_each(|span| {
-        adjust_width(&mut widths, styles, count_rows, count_columns, span);
-    });
-
-    // remove not visible cells to print everything correctly
-    (0..count_rows).for_each(|row| {
-        let mut n_removed = 0;
-        (0..count_columns).for_each(|column| {
-            let column = column - n_removed;
-            if styles[row][column].span == 0 {
-                widths[row].remove(column);
-                cells[row].remove(column);
-                styles[row].remove(column);
-                n_removed += 1;
-            }
-        });
+    spans.into_iter().for_each(|span| {
+        adjust_width(
+            &mut widths,
+            styles,
+            borders,
+            count_rows,
+            count_columns,
+            span,
+        );
     });
 
     widths
@@ -1147,6 +1160,7 @@ fn columns_width(
 fn adjust_width(
     widths: &mut [Vec<usize>],
     styles: &[Vec<Style>],
+    borders: &[Vec<BorderLine>],
     count_rows: usize,
     count_columns: usize,
     span: usize,
@@ -1158,13 +1172,14 @@ fn adjust_width(
             break;
         }
 
-        adjust_range_width(widths, styles, count_rows, start, end);
+        adjust_range_width(widths, styles, borders, count_rows, start, end);
     }
 }
 
 fn adjust_range_width(
     widths: &mut [Vec<usize>],
     styles: &[Vec<Style>],
+    borders: &[Vec<BorderLine>],
     count_rows: usize,
     start_column: usize,
     end_column: usize,
@@ -1185,7 +1200,14 @@ fn adjust_range_width(
             row_spans <= span
         })
         .map(|row| {
-            let width = row_width(&styles[row], &widths[row], start_column, end_column);
+            let width = row_width(
+                &styles[row],
+                &widths[row],
+                &borders[row],
+                start_column,
+                end_column,
+                true,
+            );
             (row, width)
         })
         .max_by_key(|&(_, width)| width)
@@ -1211,6 +1233,7 @@ fn adjust_range_width(
             inc_width_to_cells(
                 &mut widths[row],
                 &styles[row],
+                &borders[row],
                 start_column,
                 end_column,
                 max_width,
@@ -1241,7 +1264,14 @@ fn is_cell_visible(row_styles: &[Style], column: usize) -> bool {
             .any(|(style, span)| style.span > span)
 }
 
-fn row_width(styles: &[Style], widths: &[usize], column_start: usize, column_end: usize) -> usize {
+fn row_width(
+    styles: &[Style],
+    widths: &[usize],
+    borders: &[BorderLine],
+    column_start: usize,
+    column_end: usize,
+    consider_borders: bool,
+) -> usize {
     let width = (column_start..column_end)
         .filter(|&i| is_cell_visible(styles, i))
         .map(|i| widths[i])
@@ -1251,11 +1281,24 @@ fn row_width(styles: &[Style], widths: &[usize], column_start: usize, column_end
         return 0;
     }
 
-    // fixme: Is this style dependent?
-    let border_count = (column_start..column_end)
-        .filter(|&i| is_cell_visible(styles, i))
-        .count()
-        - 1;
+    let border_count = if consider_borders {
+        if column_end - column_start == 0 {
+            0
+        } else {
+            (column_start..column_end)
+                .filter(|&i| is_cell_visible(styles, i))
+                .filter(|&i| {
+                    if i == column_start {
+                        false
+                    } else {
+                        borders[i].connector1.is_some()
+                    }
+                })
+                .count()
+        }
+    } else {
+        0
+    };
 
     width + border_count
 }
@@ -1263,11 +1306,12 @@ fn row_width(styles: &[Style], widths: &[usize], column_start: usize, column_end
 fn inc_width_to_cells(
     widths: &mut [usize],
     styles: &[Style],
+    borders: &[BorderLine],
     start_range: usize,
     end_range: usize,
     width: usize,
 ) {
-    let a = row_width(styles, widths, start_range, end_range);
+    let a = row_width(styles, widths, borders, start_range, end_range, true);
     let diff = width - a;
 
     (0..diff)
@@ -1318,6 +1362,44 @@ fn cell_height(cell: &[&str], style: &Style) -> usize {
     content_height + style.indent.top + style.indent.bottom
 }
 
+fn normalized_width(
+    widths: &[Vec<usize>],
+    styles: &[Vec<Style>],
+    count_rows: usize,
+    count_columns: usize,
+) -> Vec<usize> {
+    let mut v = vec![0; count_columns];
+    let mut skip = 0;
+    for col in 0..count_columns {
+        if skip > 0 {
+            skip -= 1;
+            continue;
+        }
+
+        let min_spanned_row = (0..count_rows)
+            .filter(|&row| styles[row][col].span > 0)
+            .min_by(|&x, &y| styles[x][col].span.cmp(&styles[y][col].span));
+
+        if let Some(row) = min_spanned_row {
+            let span = styles[row][col].span;
+            let mut width = widths[row][col] - (span - 1);
+
+            for col in (col..col + span).cycle() {
+                if width == 0 {
+                    break;
+                }
+
+                v[col] += 1;
+                width -= 1;
+            }
+
+            skip += span - 1;
+        }
+    }
+
+    v
+}
+
 #[derive(Debug)]
 struct Borders {
     vertical: HashMap<CellIndex, Line>,
@@ -1351,7 +1433,7 @@ impl Borders {
         }
 
         if !self.horizontal.contains_key(&row) {
-            return Ok(Vec::new());
+            return Ok(vec![BorderLine::default(); self.count_columns]);
         }
 
         let mut line = Vec::with_capacity(self.count_columns);
@@ -1380,7 +1462,7 @@ impl Borders {
 
         let mut line: Vec<BorderLine> = Vec::new();
         let mut last_index = None;
-        for column in 0..self.count_columns + 1 {
+        for column in 0..self.count_columns {
             let border = BorderLine {
                 connector1: self.get_vertical_char(row, column),
                 ..Default::default()
@@ -1397,6 +1479,8 @@ impl Borders {
             line.push(border);
         }
 
+        line[self.count_columns - 1].connector2 = self.get_vertical_char(row, self.count_columns);
+
         Ok(line)
     }
 
diff --git a/src/style.rs b/src/style.rs
index ff478a5..14f2c72 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -377,15 +377,6 @@ impl TableOption for StyleSettings {
                 );
             }
         }
-
-        if count_columns > 0 {
-            for row in 0..count_rows {
-                let cell = grid.style(&Entity::Cell(row, 0));
-                if cell.span == count_columns {
-                    fix_full_span_row(grid, row, count_columns);
-                }
-            }
-        }
     }
 }
 
@@ -647,22 +638,6 @@ fn make_style_header(
     }
 }
 
-fn fix_full_span_row(grid: &mut Grid, row: usize, count_columns: usize) {
-    let mut first_cell_border = grid.get_border(row, 0);
-    let last_cell_border = grid.get_border(row, count_columns - 1);
-
-    first_cell_border.right = last_cell_border.right;
-    first_cell_border.right_top_corner = last_cell_border.right_top_corner;
-    first_cell_border.right_bottom_corner = last_cell_border.right_bottom_corner;
-
-    grid.set(
-        &Entity::Cell(row, 0),
-        Settings::default()
-            .border(first_cell_border)
-            .border_restriction(false),
-    );
-}
-
 /// Style is responsible for a look of a [Table].
 ///
 /// # Example


Test patch:
diff --git a/papergrid/tests/render.rs b/papergrid/tests/render.rs
index 73a8f05..64ccc55 100644
--- a/papergrid/tests/render.rs
+++ b/papergrid/tests/render.rs
@@ -224,9 +224,9 @@ fn render_row_span() {
     grid.set(&Entity::Cell(1, 1), Settings::new().text("1-1"));
 
     let expected = concat!(
-        "+-------+\n",
+        "+---+---+\n",
         "|  0-0  |\n",
-        "+-------+\n",
+        "+---+---+\n",
         "|1-0|1-1|\n",
         "+---+---+\n"
     );
@@ -251,10 +251,10 @@ fn render_miltiline_span() {
     grid.set(&Entity::Cell(1, 1), Settings::new().text("1-1"));
 
     let expected = concat!(
-        "+-------+\n",
+        "+---+---+\n",
         "|  0-0  |\n",
         "|  0-1  |\n",
-        "+-------+\n",
+        "+---+---+\n",
         "|1-0|1-1|\n",
         "+---+---+\n"
     );
@@ -284,15 +284,15 @@ fn render_row_span_multilane() {
     );
 
     let expected = concat!(
-        "+----------+----+\n",
+        "+-----+----+----+\n",
         "|first line|e.g.|\n",
-        "+----------+----+\n",
+        "+-----+----+----+\n",
         "|0    |1   |2   |\n",
         "+-----+----+----+\n",
         "|0    |1   |2   |\n",
         "+-----+----+----+\n",
         "|full last line |\n",
-        "+---------------+\n",
+        "+-----+----+----+\n",
     );
 
     println!("{}", grid);
@@ -317,9 +317,9 @@ fn render_row_span_with_horizontal_ident() {
     let grid = grid.to_string();
 
     let expected = concat!(
-        "+---------------+\n",
+        "+-----------+---+\n",
         "|0-0            |\n",
-        "+---------------+\n",
+        "+-----------+---+\n",
         "|    1-0    |1-1|\n",
         "+-----------+---+\n",
         "|2-0        |2-1|\n",
@@ -331,6 +331,34 @@ fn render_row_span_with_horizontal_ident() {
     assert_eq!(grid, expected);
 }
 
+#[test]
+fn render_row_span_3x3_with_horizontal_ident() {
+    let mut grid = Grid::new(3, 3);
+    grid.set_cell_borders(DEFAULT_CELL_STYLE.clone());
+
+    grid.set(&Entity::Cell(0, 0), Settings::new().text("0-0").span(3));
+    grid.set(&Entity::Cell(1, 0), Settings::new().text("1-0").span(2));
+    grid.set(&Entity::Cell(2, 0), Settings::new().text("2-0").span(2));
+    grid.set(&Entity::Cell(1, 2), Settings::new().text("1-1"));
+    grid.set(&Entity::Cell(2, 2), Settings::new().text("2-1"));
+
+    let grid = grid.to_string();
+
+    let expected = concat!(
+        "+-+-+---+\n",
+        "|0-0    |\n",
+        "+-+-+---+\n",
+        "|1-0|1-1|\n",
+        "+-+-+---+\n",
+        "|2-0|2-1|\n",
+        "+-+-+---+\n",
+    );
+
+    println!("{}", grid);
+
+    assert_eq!(grid, expected);
+}
+
 #[test]
 fn render_row_span_with_different_length() {
     let mut grid = Grid::new(3, 2);
@@ -348,13 +376,13 @@ fn render_row_span_with_different_length() {
     );
 
     let expected = concat!(
-        "+-------------------+\n",
+        "+---------+---------+\n",
         "|first row          |\n",
-        "+-------------------+\n",
+        "+---------+---------+\n",
         "|0        |1        |\n",
         "+---------+---------+\n",
         "|a longer second row|\n",
-        "+-------------------+\n",
+        "+---------+---------+\n",
     );
 
     println!("{}", grid);
@@ -371,7 +399,7 @@ fn render_row_span_with_odd_length() {
     grid.set(&Entity::Cell(1, 0), Settings::new().text("2"));
     grid.set(&Entity::Cell(1, 1), Settings::new().text("4"));
 
-    let expected = concat!("+----+\n", "|3   |\n", "+----+\n", "|2 |4|\n", "+--+-+\n",);
+    let expected = concat!("+--+-+\n", "|3   |\n", "+--+-+\n", "|2 |4|\n", "+--+-+\n",);
 
     assert_eq!(expected, grid.to_string());
 }
@@ -385,13 +413,13 @@ fn render_only_row_spaned() {
     grid.set(&Entity::Cell(1, 0), Settings::new().text("1-0").span(2));
     grid.set(&Entity::Cell(2, 0), Settings::new().text("2-0").span(2));
 
-    let expected = "+---+\n\
+    let expected = "+-+-+\n\
                          |0-0|\n\
-                         +---+\n\
+                         +-+-+\n\
                          |1-0|\n\
-                         +---+\n\
+                         +-+-+\n\
                          |2-0|\n\
-                         +---+\n";
+                         +-+-+\n";
 
     assert_eq!(grid.to_string(), expected);
 }
@@ -426,14 +454,83 @@ fn grid_2x2_span_test() {
     let str = grid.to_string();
     assert_eq!(
         str,
-        "+-------+\n\
+        "+---+---+\n\
          |123    |\n\
-         +-------+\n\
+         +---+---+\n\
          |asd|asd|\n\
          +---+---+\n"
     )
 }
 
+#[test]
+fn grid_2x2_2_span_test() {
+    let mut grid = Grid::new(2, 2);
+    grid.set(&Entity::Global, Settings::new().text("asd"));
+    grid.set_cell_borders(DEFAULT_CELL_STYLE.clone());
+
+    // grid.set(&Entity::Cell(0, 0), Settings::new().text("123").span(2));
+    // grid.set(&Entity::Cell(1, 0), Settings::new().text("asd").span(2));
+
+    // let str = grid.to_string();
+    // assert_eq!(
+    //     str,
+    //     "+-+-+\n\
+    //      |123|\n\
+    //      +-+-+\n\
+    //      |asd|\n\
+    //      +-+-+\n"
+    // );
+
+    grid.set(&Entity::Cell(0, 0), Settings::new().text("1234").span(2));
+    grid.set(&Entity::Cell(1, 0), Settings::new().text("asdw").span(2));
+
+    let str = grid.to_string();
+    assert_eq!(
+        str,
+        "+--+-+\n\
+         |1234|\n\
+         +--+-+\n\
+         |asdw|\n\
+         +--+-+\n"
+    );
+
+    grid.set(&Entity::Cell(0, 0), Settings::new().text("1").span(2));
+    grid.set(&Entity::Cell(1, 0), Settings::new().text("a").span(2));
+
+    let str = grid.to_string();
+    assert_eq!(
+        str,
+        "+++\n\
+         |1|\n\
+         +++\n\
+         |a|\n\
+         +++\n"
+    );
+}
+
+#[test]
+fn render_row_span_with_no_split_style() {
+    let mut grid = Grid::new(2, 2);
+    grid.set_cell_borders(DEFAULT_CELL_STYLE.clone());
+
+    grid.set(
+        &Entity::Cell(0, 0),
+        Settings::new()
+            .text("0-0")
+            .span(2)
+            .alignment(AlignmentHorizontal::Center),
+    );
+    grid.set(&Entity::Cell(0, 1), Settings::new().text(""));
+    grid.set(&Entity::Cell(1, 0), Settings::new().text("1-0"));
+    grid.set(&Entity::Cell(1, 1), Settings::new().text("1-1"));
+
+    grid.clear_split_grid();
+
+    let expected = concat!(" 0-0  \n", "1-01-1\n");
+
+    assert_eq!(expected, grid.to_string());
+}
+
 #[test]
 #[ignore = "I am not sure what is the right behaiviour here"]
 fn hieroglyph_handling() {
diff --git a/tests/panel_test.rs b/tests/panel_test.rs
index 771f446..b8aeda3 100644
--- a/tests/panel_test.rs
+++ b/tests/panel_test.rs
@@ -1,6 +1,7 @@
 use crate::util::create_vector;
 use tabled::{
-    Alignment, Border, Footer, Full, Header, Highlight, Modify, Object, Panel, Row, Style, Table,
+    Alignment, Border, Cell, Footer, Full, Header, Highlight, Modify, Object, Panel, Row, Style,
+    Table,
 };
 
 mod util;
@@ -15,7 +16,7 @@ fn panel_has_no_style_by_default() {
     // todo: it would be better if vertical split was not set in panel line
     // it is because it has right border printed
     let expected = concat!(
-        "Linux Distributions                  \n",
+        "Linux Distributions                 \n",
         " N | column 0 | column 1 | column 2 \n",
         "---+----------+----------+----------\n",
         " 0 |   0-0    |   0-1    |   0-2    \n",
@@ -23,27 +24,26 @@ fn panel_has_no_style_by_default() {
         " 2 |   2-0    |   2-1    |   2-2    \n",
     );
 
+    println!("{}", table);
+
     assert_eq!(table, expected);
 }
 
 #[test]
 fn highligt_panel() {
+    let border = Border::full('#', '#', '#', '#', '#', '#', '#', '#');
     let table = Table::new(create_vector::<3, 3>())
         .with(Panel("Linux Distributions", 0))
         .with(Style::psql())
-        .with(Highlight::cell(
-            0,
-            0,
-            Border::full('#', '#', '#', '#', '#', '#', '#', '#'),
-        ))
+        .with(Highlight::cell(0, 0, border.clone()))
         .to_string();
 
     // todo: it would be better if vertical split was not set in panel line
     // it is because it has right border printed
     let expected = concat!(
-        "######################################\n",
-        "#Linux Distributions                 #\n",
-        "######################################\n",
+        "#####                                \n",
+        "#Linux Distributions                 \n",
+        "#####----------+----------+----------\n",
         "  N | column 0 | column 1 | column 2 \n",
         "  0 |   0-0    |   0-1    |   0-2    \n",
         "  1 |   1-0    |   1-1    |   1-2    \n",
@@ -51,6 +51,29 @@ fn highligt_panel() {
     );
 
     assert_eq!(table, expected);
+
+    let table = Table::new(create_vector::<3, 3>())
+        .with(Panel("Linux Distributions", 0))
+        .with(Style::psql())
+        .with(Highlight::cell(0, 0, border.clone()))
+        .with(Highlight::cell(0, 1, border.clone()))
+        .with(Highlight::cell(0, 2, border.clone()))
+        .with(Highlight::cell(0, 3, border))
+        .to_string();
+
+    // todo: it would be better if vertical split was not set in panel line
+    // it is because it has right border printed
+    let expected = concat!(
+        "######################################\n",
+        "#Linux Distributions                 #\n",
+        "######################################\n",
+        "  N | column 0 | column 1 | column 2  \n",
+        "  0 |   0-0    |   0-1    |   0-2     \n",
+        "  1 |   1-0    |   1-1    |   1-2     \n",
+        "  2 |   2-0    |   2-1    |   2-2     \n",
+    );
+
+    assert_eq!(table, expected);
 }
 
 #[test]
@@ -62,14 +85,16 @@ fn top_panel() {
         .to_string();
 
     let expected = concat!(
-        "        Linux Distributions         |\n",
-        "------------------------------------+\n",
+        "        Linux Distributions         \n",
+        "---+----------+----------+----------\n",
         " N | column 0 | column 1 | column 2 \n",
         " 0 |   0-0    |   0-1    |   0-2    \n",
         " 1 |   1-0    |   1-1    |   1-2    \n",
         " 2 |   2-0    |   2-1    |   2-2    \n",
     );
 
+    println!("{}", table);
+
     assert_eq!(table, expected);
 }
 
@@ -88,9 +113,11 @@ fn bottom_panel() {
         " 0 |   0-0    |   0-1    |   0-2    \n",
         " 1 |   1-0    |   1-1    |   1-2    \n",
         " 2 |   2-0    |   2-1    |   2-2    \n",
-        "        Linux Distributions         |\n",
+        "        Linux Distributions         \n",
     );
 
+    println!("{}", table);
+
     assert_eq!(table, expected);
 }
 
@@ -106,7 +133,7 @@ fn inner_panel() {
         " N | column 0 | column 1 | column 2 \n",
         "---+----------+----------+----------\n",
         " 0 |   0-0    |   0-1    |   0-2    \n",
-        "        Linux Distributions         |\n",
+        "        Linux Distributions         \n",
         " 1 |   1-0    |   1-1    |   1-2    \n",
         " 2 |   2-0    |   2-1    |   2-2    \n",
     );
@@ -123,8 +150,8 @@ fn header() {
         .to_string();
 
     let expected = concat!(
-        "        Linux Distributions         |\n",
-        "------------------------------------+\n",
+        "        Linux Distributions         \n",
+        "---+----------+----------+----------\n",
         " N | column 0 | column 1 | column 2 \n",
         " 0 |   0-0    |   0-1    |   0-2    \n",
         " 1 |   1-0    |   1-1    |   1-2    \n",
@@ -145,13 +172,13 @@ fn footer() {
         .to_string();
 
     let expected = concat!(
-        "        Linux Distributions         |\n",
-        "------------------------------------+\n",
+        "        Linux Distributions         \n",
+        "---+----------+----------+----------\n",
         " N | column 0 | column 1 | column 2 \n",
         " 0 |   0-0    |   0-1    |   0-2    \n",
         " 1 |   1-0    |   1-1    |   1-2    \n",
         " 2 |   2-0    |   2-1    |   2-2    \n",
-        "              The end               |\n",
+        "              The end               \n",
     );
 
     assert_eq!(table, expected);
@@ -165,9 +192,9 @@ fn panel_style_uses_most_left_and_right_cell_styles() {
         .to_string();
 
     let expected = concat!(
-        "┌───────────┐\n",
+        "┌─────┬─────┐\n",
         "│Numbers    │\n",
-        "├───────────┤\n",
+        "├─────┼─────┤\n",
         "│ i32 │ i32 │\n",
         "├─────┼─────┤\n",
         "│  0  │  1  │\n",
@@ -176,3 +203,48 @@ fn panel_style_uses_most_left_and_right_cell_styles() {
 
     assert_eq!(table, expected);
 }
+
+#[test]
+fn panel_style_change() {
+    let table = Table::new(&[(0, 1)])
+        .with(tabled::Panel("Numbers", 0))
+        .with(
+            Style::modern()
+                .top_intersection('─')
+                .header_intersection('┬'),
+        )
+        .with(Modify::new(Cell(0, 0)).with(Alignment::center_horizontal()))
+        .to_string();
+
+    let expected = concat!(
+        "┌───────────┐\n",
+        "│  Numbers  │\n",
+        "├─────┬─────┤\n",
+        "│ i32 │ i32 │\n",
+        "├─────┼─────┤\n",
+        "│  0  │  1  │\n",
+        "└─────┴─────┘\n",
+    );
+
+    assert_eq!(table, expected);
+}
+
+#[test]
+fn panel_in_single_column() {
+    let table = Table::new(&[(0)])
+        .with(tabled::Panel("Numbers", 0))
+        .with(Style::modern())
+        .to_string();
+
+    let expected = concat!(
+        "┌───────┐\n",
+        "│Numbers│\n",
+        "├───────┤\n",
+        "│  i32  │\n",
+        "├───────┤\n",
+        "│   0   │\n",
+        "└───────┘\n",
+    );
+
+    assert_eq!(table, expected);
+}