Repository: zhiburt/tabled
Pull request #353 (2023-07-26 08:27:37)

tabled/ Column names change the interface by adding ValueList


Patch:
diff --git a/tabled/examples/column_names.rs b/tabled/examples/column_names.rs
index 0388e62..3c06f56 100644
--- a/tabled/examples/column_names.rs
+++ b/tabled/examples/column_names.rs
@@ -2,8 +2,6 @@
 //!
 //! It sets a `clickhouse` like table style (first seen on).
 
-use std::iter::repeat;
-
 use tabled::{
     grid::config::AlignmentHorizontal,
     settings::{themes::ColumnNames, Color, Style},
@@ -55,7 +53,7 @@ fn main() {
 
     table.with(Style::modern().remove_horizontal()).with(
         ColumnNames::default()
-            .set_colors(repeat(Color::BOLD | Color::BG_BLUE | Color::FG_WHITE).take(3))
+            .set_color(Color::BOLD | Color::BG_BLUE | Color::FG_WHITE)
             .set_alignment(AlignmentHorizontal::Center),
     );
 
diff --git a/tabled/src/settings/themes/column_names.rs b/tabled/src/settings/themes/column_names.rs
index 7ceb752..2bf8a98 100644
--- a/tabled/src/settings/themes/column_names.rs
+++ b/tabled/src/settings/themes/column_names.rs
@@ -68,9 +68,9 @@ use crate::{
 #[derive(Debug, Clone)]
 pub struct ColumnNames {
     names: Option<Vec<String>>,
-    colors: Vec<Option<Color>>,
+    colors: Option<ListValue<Color>>,
+    alignments: ListValue<AlignmentHorizontal>,
     line: usize,
-    alignment: AlignmentHorizontal,
 }
 
 impl Default for ColumnNames {
@@ -79,7 +79,7 @@ impl Default for ColumnNames {
             names: Default::default(),
             colors: Default::default(),
             line: Default::default(),
-            alignment: AlignmentHorizontal::Left,
+            alignments: ListValue::from(AlignmentHorizontal::Left),
         }
     }
 }
@@ -113,9 +113,7 @@ impl ColumnNames {
         let names = names.into_iter().map(Into::into).collect::<Vec<_>>();
         Self {
             names: Some(names),
-            colors: Vec::new(),
-            line: 0,
-            alignment: AlignmentHorizontal::Left,
+            ..Default::default()
         }
     }
 
@@ -131,7 +129,7 @@ impl ColumnNames {
     /// use tabled::settings::{Color, themes::ColumnNames};
     ///
     /// let mut table = Table::from_iter(vec![vec!["Hello", "World"]]);
-    /// table.with(ColumnNames::new(["head1", "head2"]).set_colors([Color::FG_RED]));
+    /// table.with(ColumnNames::new(["head1", "head2"]).set_color(vec![Color::FG_RED]));
     ///
     /// assert_eq!(
     ///     table.to_string(),
@@ -140,17 +138,15 @@ impl ColumnNames {
     ///      +-------+-------+"
     /// );
     /// ```
-    pub fn set_colors<I>(self, colors: I) -> Self
+    pub fn set_color<T>(self, color: T) -> Self
     where
-        I: IntoIterator,
-        I::Item: Into<Option<Color>>,
+        T: Into<ListValue<Color>>,
     {
-        let colors = colors.into_iter().map(Into::into).collect::<Vec<_>>();
         Self {
             names: self.names,
             line: self.line,
-            alignment: self.alignment,
-            colors,
+            alignments: self.alignments,
+            colors: Some(color.into()),
         }
     }
 
@@ -177,9 +173,9 @@ impl ColumnNames {
     pub fn set_line(self, i: usize) -> Self {
         Self {
             names: self.names,
-            colors: self.colors,
-            alignment: self.alignment,
             line: i,
+            alignments: self.alignments,
+            colors: self.colors,
         }
     }
 
@@ -207,12 +203,15 @@ impl ColumnNames {
     ///      +-------+-------+"
     /// );
     /// ```
-    pub fn set_alignment(self, alignment: AlignmentHorizontal) -> Self {
+    pub fn set_alignment<T>(self, alignment: T) -> Self
+    where
+        T: Into<ListValue<AlignmentHorizontal>>,
+    {
         Self {
             names: self.names,
-            colors: self.colors,
             line: self.line,
-            alignment,
+            alignments: alignment.into(),
+            colors: self.colors,
         }
     }
 }
@@ -260,10 +259,11 @@ impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'stat
 
         let mut total_width = 0;
         for (i, (width, name)) in widths.into_iter().zip(names).enumerate() {
-            let left_vertical = get_vertical_width(cfg, (self.line, i), count_columns);
             let color = get_color(&self.colors, i);
+            let alignment = get_alignment(&self.alignments, i);
+            let left_vertical = get_vertical_width(cfg, (self.line, i), count_columns);
             let grid_offset = total_width + left_vertical;
-            let btext = get_border_text(name, grid_offset, width, self.alignment, self.line, color);
+            let btext = get_border_text(name, grid_offset, width, alignment, self.line, color);
             btext.change(records, cfg, dims);
 
             total_width += width + left_vertical;
@@ -304,11 +304,19 @@ fn get_border_text(
     btext
 }
 
-fn get_color(colors: &[Option<Color>], i: usize) -> Option<&Color> {
-    colors.get(i).and_then(|color| match color {
-        Some(color) => Some(color),
+fn get_color(colors: &Option<ListValue<Color>>, i: usize) -> Option<&Color> {
+    match colors {
+        Some(ListValue::List(list)) => list.get(i),
+        Some(ListValue::Static(color)) => Some(color),
         None => None,
-    })
+    }
+}
+
+fn get_alignment(alignments: &ListValue<AlignmentHorizontal>, i: usize) -> AlignmentHorizontal {
+    match alignments {
+        ListValue::List(list) => list.get(i).copied().unwrap_or(AlignmentHorizontal::Left),
+        ListValue::Static(alignment) => *alignment,
+    }
 }
 
 fn get_indent(text: &str, align: AlignmentHorizontal, available: usize) -> usize {
@@ -324,3 +332,30 @@ fn get_vertical_width(cfg: &mut ColoredConfig, pos: Position, count_columns: usi
         .and_then(unicode_width::UnicodeWidthChar::width)
         .unwrap_or(0)
 }
+
+#[derive(Debug, Clone)]
+pub enum ListValue<T> {
+    List(Vec<T>),
+    Static(T),
+}
+
+impl<T> From<T> for ListValue<T> {
+    fn from(value: T) -> Self {
+        Self::Static(value)
+    }
+}
+
+impl<T> From<Vec<T>> for ListValue<T> {
+    fn from(value: Vec<T>) -> Self {
+        Self::List(value)
+    }
+}
+
+impl<T> Default for ListValue<T>
+where
+    T: Default,
+{
+    fn default() -> Self {
+        Self::Static(T::default())
+    }
+}


Test patch:
diff --git a/tabled/tests/settings/column_names_test.rs b/tabled/tests/settings/column_names_test.rs
index 37b1a26..1861260 100644
--- a/tabled/tests/settings/column_names_test.rs
+++ b/tabled/tests/settings/column_names_test.rs
@@ -113,6 +113,18 @@ test_table!(
     "+-------+----------+"
 );
 
+test_table!(
+    alignment_array,
+    Table::new([("Hello", "World"), ("and", "looooong\nword")])
+        .with(ColumnNames::default().set_alignment(vec![AlignmentHorizontal::Right, AlignmentHorizontal::Center])),
+    "+---&str+---&str---+"
+    "| Hello | World    |"
+    "+-------+----------+"
+    "| and   | looooong |"
+    "|       | word     |"
+    "+-------+----------+"
+);
+
 test_table!(
     set_line,
     Matrix::new(3, 3).with(ColumnNames::default().set_line(1)),
@@ -154,7 +166,7 @@ test_table!(
 test_table!(
     set_colors_some_some,
     Table::new([("Hello", "World"), ("and", "looooong\nword")])
-        .with(ColumnNames::default().set_colors([Some(Color::BG_BLACK), Some(Color::BG_BLUE)])),
+        .with(ColumnNames::default().set_color(vec![Color::BG_BLACK, Color::BG_BLUE])),
     "+\u{1b}[40m&\u{1b}[49m\u{1b}[40ms\u{1b}[49m\u{1b}[40mt\u{1b}[49m\u{1b}[40mr\u{1b}[49m---+\u{1b}[44m&\u{1b}[49m\u{1b}[44ms\u{1b}[49m\u{1b}[44mt\u{1b}[49m\u{1b}[44mr\u{1b}[49m------+"
     "| Hello | World    |"
     "+-------+----------+"
@@ -166,7 +178,7 @@ test_table!(
 test_table!(
     set_colors_none_some,
     Table::new([("Hello", "World"), ("and", "looooong\nword")])
-        .with(ColumnNames::default().set_colors([None, Some(Color::BG_BLUE)])),
+        .with(ColumnNames::default().set_color(vec![Color::default(), Color::BG_BLUE])),
         "+&str---+\u{1b}[44m&\u{1b}[49m\u{1b}[44ms\u{1b}[49m\u{1b}[44mt\u{1b}[49m\u{1b}[44mr\u{1b}[49m------+"
         "| Hello | World    |"
         "+-------+----------+"
@@ -178,7 +190,7 @@ test_table!(
 test_table!(
     set_colors_none_none,
     Table::new([("Hello", "World"), ("and", "looooong\nword")])
-        .with(ColumnNames::default().set_colors([None, None])),
+        .with(ColumnNames::default().set_color(vec![Color::default(), Color::default()])),
     "+&str---+&str------+"
     "| Hello | World    |"
     "+-------+----------+"
@@ -190,7 +202,7 @@ test_table!(
 test_table!(
     set_colors_empty,
     Table::new([("Hello", "World"), ("and", "looooong\nword")])
-        .with(ColumnNames::default().set_colors([None; 0])),
+        .with(ColumnNames::default().set_color(vec![Color::default(); 0])),
     "+&str---+&str------+"
     "| Hello | World    |"
     "+-------+----------+"