Repository: zhiburt/tabled
Pull request #96 (2022-03-23 11:13:37)

tabled/ Remove TotalWidth
Replace it by MaxWidth && MinWidth

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>


Patch:
diff --git a/examples/terminal_table/src/main.rs b/examples/terminal_table/src/main.rs
index 63b583b..cb1a581 100644
--- a/examples/terminal_table/src/main.rs
+++ b/examples/terminal_table/src/main.rs
@@ -1,7 +1,9 @@
 //! The example can be run by this command
 //! `cargo run --example terminal_table`
 
-use tabled::{object::Full, Alignment, Modify, Style, TableIteratorExt, Tabled, TotalWidth};
+use tabled::{
+    object::Full, Alignment, MaxWidth, MinWidth, Modify, Style, TableIteratorExt, Tabled,
+};
 
 #[derive(Tabled)]
 struct Release {
@@ -39,7 +41,8 @@ fn main() {
         .table()
         .with(Style::extended())
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
-        .with(TotalWidth::new(width as usize).wrap(true));
+        .with(MaxWidth::wrapping(width as usize).keep_words())
+        .with(MinWidth::new(width as usize));
 
     println!("{}", table);
 }
diff --git a/src/width.rs b/src/width.rs
index f6ecaad..8c0e3d9 100644
--- a/src/width.rs
+++ b/src/width.rs
@@ -2,7 +2,19 @@
 //!
 //! - [Truncate] cuts a cell content to limit width.
 //! - [Wrap] split the content via new lines in order to fit max width.
-//! - [TotalWidth] tries to set an whole table width to the limit width.
+//!
+//! To set a a table width a combination of [MaxWidth] and [MinWidth] can be set.
+//!
+//! ## Example
+//!
+//! ```
+//! use tabled::{MaxWidth, MinWidth, Table};
+//!
+//! let table = Table::new(&["Hello World!"])
+//!     .with(MaxWidth::wrapping(5))
+//!     .with(MinWidth::new(5));
+//! ```
+//!
 
 use std::collections::{HashMap, HashSet};
 
@@ -11,10 +23,20 @@ use papergrid::{string_width, Entity, Grid, Settings};
 
 /// MaxWidth allows you to set a max width of an object on a [Grid],
 /// using different strategies.
+/// It also allows you to set a MaxWidth for a whole table.
 ///
 /// It is an abstract factory.
 ///
-/// ## Example
+/// Beware that borders are not removed when you set a size value to very small.
+/// For example if you set size to 0 the table still be rendered but with all content removed.
+///
+/// Also be aware that it doesn't changes [crate::Padding] settings.
+///
+/// The function is color aware if a `color` feature is on.
+///
+/// ## Examples
+///
+/// Cell change
 ///
 /// ```
 /// use tabled::{object::Full, MaxWidth, Modify, Style, Table};
@@ -25,6 +47,15 @@ use papergrid::{string_width, Entity, Grid, Settings};
 ///     .with(Style::github_markdown())
 ///     .with(Modify::new(Full).with(MaxWidth::truncating(3).suffix("...")));
 /// ```
+///
+/// Table change
+///
+/// ```
+/// use tabled::{MaxWidth, Table};
+///
+/// let table = Table::new(&["Hello World!"]).with(MaxWidth::wrapping(5));
+/// ```
+///
 pub struct MaxWidth;
 
 impl MaxWidth {
@@ -328,10 +359,14 @@ fn chunks(s: &str, width: usize) -> Vec<String> {
 
 /// MinWidth changes a content in case if it's length is lower then the boundry.
 ///
+/// It can be applied to a whole table.
+///
 /// It does anything in case if the content's length is bigger then the boundry.
 /// It doesn't include a [crate::Padding] settings.
 ///
-/// ## Example
+/// ## Examples
+///
+/// Cell change
 ///
 /// ```
 /// use tabled::{object::Full, MinWidth, Modify, Style, Table};
@@ -342,6 +377,14 @@ fn chunks(s: &str, width: usize) -> Vec<String> {
 ///     .with(Style::github_markdown())
 ///     .with(Modify::new(Full).with(MinWidth::new(10)));
 /// ```
+/// Table change
+///
+/// ```
+/// use tabled::{MinWidth, Table};
+///
+/// let table = Table::new(&["Hello World!"]).with(MinWidth::new(5));
+/// ```
+///
 pub struct MinWidth {
     size: usize,
     fill: char,
@@ -412,49 +455,44 @@ fn increase_width(s: &str, width: usize, fill_with: char) -> String {
     }
 }
 
-/// TotalWidth decrease or increase an total table width according to the limit.
-///
-/// Beware that borders are not removed when you set a size value to very small.
-/// For example if you set size to 0 the table still be rendered but with all content removed.
-///
-/// Also be aware that it doesn't changes [crate::Padding] settings.
-///
-/// The function is color aware if a `color` feature is on.
-///
-/// ## Example
-///
-/// ```
-/// use tabled::{TotalWidth, Table};
-///
-/// let table = Table::new(&["Hello World!"]).with(TotalWidth::new(5));
-/// ```
-pub struct TotalWidth {
-    size: usize,
-    wrap: bool,
-    wrap_keeping_words: bool,
-}
+impl<S> TableOption for Truncate<S>
+where
+    S: AsRef<str>,
+{
+    fn change(&mut self, grid: &mut Grid) {
+        if grid.count_columns() == 0 || grid.count_rows() == 0 {
+            return;
+        }
 
-impl TotalWidth {
-    /// Creates a new instance of TotalWidth.
-    ///
-    /// Default truncate method is [Truncate].
-    pub fn new(size: usize) -> Self {
-        Self {
-            size,
-            wrap: false,
-            wrap_keeping_words: false,
+        let total_width = grid.total_width();
+        if total_width == self.width {
+            return;
+        }
+
+        if self.width < total_width {
+            decrease_total_width(grid, self.width, false, false);
         }
     }
+}
 
-    /// Set's a truncate logic to [Wrap].
-    pub fn wrap(mut self, keep_words: bool) -> Self {
-        self.wrap = true;
-        self.wrap_keeping_words = keep_words;
-        self
+impl TableOption for Wrap {
+    fn change(&mut self, grid: &mut Grid) {
+        if grid.count_columns() == 0 || grid.count_rows() == 0 {
+            return;
+        }
+
+        let total_width = grid.total_width();
+        if total_width == self.width {
+            return;
+        }
+
+        if self.width < total_width {
+            decrease_total_width(grid, self.width, true, self.keep_words);
+        }
     }
 }
 
-impl TableOption for TotalWidth {
+impl TableOption for MinWidth {
     fn change(&mut self, grid: &mut Grid) {
         if grid.count_columns() == 0 || grid.count_rows() == 0 {
             return;
@@ -467,8 +505,6 @@ impl TableOption for TotalWidth {
 
         if self.size > total_width {
             increase_total_width(grid, self.size);
-        } else {
-            decrease_total_width(grid, self.size, self.wrap, self.wrap_keeping_words);
         }
     }
 }


Test patch:
diff --git a/tests/width_test.rs b/tests/width_test.rs
index 69adced..40c4143 100644
--- a/tests/width_test.rs
+++ b/tests/width_test.rs
@@ -1,7 +1,7 @@
 use crate::util::create_vector;
 use tabled::{
     object::{Cell, Columns, Full, Object, Rows},
-    Alignment, MaxWidth, MinWidth, Modify, Panel, Style, Table, TotalWidth,
+    Alignment, MaxWidth, MinWidth, Modify, Panel, Style, Table,
 };
 
 mod util;
@@ -575,7 +575,8 @@ fn total_width_big() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
         .with(Style::github_markdown())
-        .with(TotalWidth::new(80))
+        .with(MaxWidth::truncating(80))
+        .with(MinWidth::new(80))
         .to_string();
 
     let expected = concat!(
@@ -596,7 +597,8 @@ fn total_width_big_with_panel() {
         .with(Panel("Hello World", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
         .with(Style::github_markdown())
-        .with(TotalWidth::new(80))
+        .with(MaxWidth::truncating(80))
+        .with(MinWidth::new(80))
         .to_string();
 
     let expected = concat!(
@@ -618,14 +620,16 @@ fn total_width_big_with_panel_with_wrapping_doesnt_affect_increase() {
         .with(Panel("Hello World", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
         .with(Style::github_markdown())
-        .with(TotalWidth::new(80).wrap(false))
+        .with(MaxWidth::wrapping(80))
+        .with(MinWidth::new(80))
         .to_string();
 
     let table2 = Table::new(&data)
         .with(Panel("Hello World", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
         .with(Style::github_markdown())
-        .with(TotalWidth::new(80))
+        .with(MaxWidth::truncating(80))
+        .with(MinWidth::new(80))
         .to_string();
 
     assert_eq!(table1, table2);
@@ -636,7 +640,8 @@ fn total_width_small() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
         .with(Style::github_markdown())
-        .with(TotalWidth::new(14))
+        .with(MaxWidth::truncating(14))
+        .with(MinWidth::new(14))
         .to_string();
 
     let expected = concat!(
@@ -655,7 +660,8 @@ fn total_width_smaller_then_content() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
         .with(Style::github_markdown())
-        .with(TotalWidth::new(8))
+        .with(MaxWidth::truncating(8))
+        .with(MinWidth::new(8))
         .to_string();
 
     let expected = concat!(
@@ -676,8 +682,8 @@ fn total_width_small_with_panel() {
         .with(Panel("Hello World", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
         .with(Style::github_markdown())
-        // .with(Modify::new(Full).with(Indent::new(0, 0, 0, 0)))
-        .with(TotalWidth::new(20))
+        .with(MaxWidth::truncating(20))
+        .with(MinWidth::new(20))
         .to_string();
 
     let expected = concat!(
@@ -699,7 +705,8 @@ fn total_width_small_with_panel_using_wrapping() {
         .with(Panel("Hello World", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
         .with(Style::github_markdown())
-        .with(TotalWidth::new(20).wrap(false))
+        .with(MaxWidth::wrapping(20))
+        .with(MinWidth::new(20))
         .to_string();
 
     let expected = concat!(