Repository: zhiburt/tabled
Pull request #354 (2023-08-03 22:15:59)

tabled/ Add taledoption::hint


Patch:
diff --git a/tabled/src/grid/dimension/complete_dimension_vec_records.rs b/tabled/src/grid/dimension/complete_dimension_vec_records.rs
index 54d48ed..f2061c3 100644
--- a/tabled/src/grid/dimension/complete_dimension_vec_records.rs
+++ b/tabled/src/grid/dimension/complete_dimension_vec_records.rs
@@ -37,10 +37,8 @@ impl CompleteDimensionVecRecords<'_> {
     /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided widths.
     ///
     /// [`TableOption`]: crate::settings::TableOption
-    pub fn set_widths(&mut self, columns: Vec<usize>) -> bool {
+    pub fn set_widths(&mut self, columns: Vec<usize>) {
         self.width = Some(Cow::Owned(columns));
-
-        true
     }
 
     /// Get column widths.
@@ -61,10 +59,8 @@ impl CompleteDimensionVecRecords<'_> {
     /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided heights.
     ///
     /// [`TableOption`]: crate::settings::TableOption
-    pub fn set_heights(&mut self, rows: Vec<usize>) -> bool {
+    pub fn set_heights(&mut self, rows: Vec<usize>) {
         self.height = Some(Cow::Owned(rows));
-
-        true
     }
 
     /// Get row heights.
@@ -95,6 +91,14 @@ impl CompleteDimensionVecRecords<'_> {
 
         CompleteDimensionVecRecords { width, height }
     }
+
+    /// Copies a reference from self.
+    pub fn into_inner(self) -> (Option<Vec<usize>>, Option<Vec<usize>>) {
+        let width = self.width.map(|list| list.into_owned());
+        let height = self.height.map(|list| list.into_owned());
+
+        (width, height)
+    }
 }
 
 impl Dimension for CompleteDimensionVecRecords<'_> {
diff --git a/tabled/src/settings/alignment/mod.rs b/tabled/src/settings/alignment/mod.rs
index 81d1717..f025329 100644
--- a/tabled/src/settings/alignment/mod.rs
+++ b/tabled/src/settings/alignment/mod.rs
@@ -13,15 +13,16 @@
 //! [`Table`]: crate::Table
 
 use crate::{
-    grid::config::CompactConfig,
-    grid::config::{AlignmentHorizontal, AlignmentVertical, CompactMultilineConfig},
+    grid::config::{
+        AlignmentHorizontal, AlignmentVertical, CompactConfig, CompactMultilineConfig, Entity,
+    },
     settings::TableOption,
 };
 
 use AlignmentInner::*;
 
 #[cfg(feature = "std")]
-use crate::grid::config::{ColoredConfig, Entity};
+use crate::grid::config::ColoredConfig;
 
 /// Alignment represent a horizontal and vertical alignment setting for any cell on a [`Table`].
 ///
@@ -169,6 +170,10 @@ impl<R, D> TableOption<R, D, ColoredConfig> for Alignment {
             Vertical(a) => cfg.set_alignment_vertical(Entity::Global, a),
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R, D> TableOption<R, D, CompactConfig> for Alignment {
@@ -177,6 +182,10 @@ impl<R, D> TableOption<R, D, CompactConfig> for Alignment {
             *cfg = cfg.set_alignment_horizontal(a)
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R, D> TableOption<R, D, CompactMultilineConfig> for Alignment {
@@ -186,4 +195,8 @@ impl<R, D> TableOption<R, D, CompactMultilineConfig> for Alignment {
             Vertical(a) => *cfg = cfg.set_alignment_vertical(a),
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
diff --git a/tabled/src/settings/cell_option.rs b/tabled/src/settings/cell_option.rs
index f589ac4..a6456f6 100644
--- a/tabled/src/settings/cell_option.rs
+++ b/tabled/src/settings/cell_option.rs
@@ -11,8 +11,26 @@ use crate::grid::{
 ///
 /// [`Cell`]: crate::object::Cell
 pub trait CellOption<R, C> {
-    /// Modification function of a single cell.
+    /// Modification function of a certail part of a grid targeted by [`Entity`].
     fn change(self, records: &mut R, cfg: &mut C, entity: Entity);
+
+    /// A hint whether an [`TableOption`] is going to change table layout.
+    ///
+    /// Return [`None`] if no changes are being done.
+    /// Otherwise return:
+    ///
+    /// - [Entity::Global] - a grand layout changed.
+    /// - [Entity::Row] - a certain row was changed.
+    /// - [Entity::Column] - a certain column was changed.
+    /// - [Entity::Cell] - a certain cell was changed.
+    ///
+    /// By default it's considered to be a grand change.
+    ///
+    /// This methods primarily is used as an optimization,
+    /// to not make unnessary calculations if they're not needed, after using the [`TableOption`].
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Global)
+    }
 }
 
 #[cfg(feature = "std")]
diff --git a/tabled/src/settings/color/mod.rs b/tabled/src/settings/color/mod.rs
index f4bfa5c..cc55948 100644
--- a/tabled/src/settings/color/mod.rs
+++ b/tabled/src/settings/color/mod.rs
@@ -38,8 +38,6 @@ use crate::{
 #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Color(AnsiColor<'static>);
 
-// todo: Add | operation to combine colors
-
 #[rustfmt::skip]
 impl Color {
     /// A color representation.
@@ -251,18 +249,30 @@ impl<R, D> TableOption<R, D, ColoredConfig> for Color {
     fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
         let _ = cfg.set_color(Entity::Global, self.0.clone());
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R> CellOption<R, ColoredConfig> for Color {
     fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
         let _ = cfg.set_color(entity, self.0.clone());
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R> CellOption<R, ColoredConfig> for &Color {
     fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
         let _ = cfg.set_color(entity, self.0.clone());
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl crate::grid::color::Color for Color {
diff --git a/tabled/src/settings/formatting/alignment_strategy.rs b/tabled/src/settings/formatting/alignment_strategy.rs
index c95facc..a0aa5a3 100644
--- a/tabled/src/settings/formatting/alignment_strategy.rs
+++ b/tabled/src/settings/formatting/alignment_strategy.rs
@@ -157,6 +157,10 @@ impl<R, D> TableOption<R, D, ColoredConfig> for AlignmentStrategy {
     fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
         <Self as CellOption<R, ColoredConfig>>::change(self, records, cfg, Entity::Global)
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R, D> TableOption<R, D, CompactMultilineConfig> for AlignmentStrategy {
@@ -169,4 +173,8 @@ impl<R, D> TableOption<R, D, CompactMultilineConfig> for AlignmentStrategy {
 
         *cfg = cfg.set_formatting(f);
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
diff --git a/tabled/src/settings/formatting/justification.rs b/tabled/src/settings/formatting/justification.rs
index a427eb9..5aacd33 100644
--- a/tabled/src/settings/formatting/justification.rs
+++ b/tabled/src/settings/formatting/justification.rs
@@ -114,6 +114,10 @@ impl<R, D> TableOption<R, D, ColoredConfig> for Justification {
         cfg.set_justification(Entity::Global, c);
         cfg.set_justification_color(Entity::Global, color);
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 impl<R> CellOption<R, ColoredConfig> for Justification {
@@ -124,4 +128,8 @@ impl<R> CellOption<R, ColoredConfig> for Justification {
         cfg.set_justification(entity, c);
         cfg.set_justification_color(entity, color);
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
diff --git a/tabled/src/settings/formatting/trim_strategy.rs b/tabled/src/settings/formatting/trim_strategy.rs
index 64ec7e1..1159780 100644
--- a/tabled/src/settings/formatting/trim_strategy.rs
+++ b/tabled/src/settings/formatting/trim_strategy.rs
@@ -115,4 +115,8 @@ impl<R, D> TableOption<R, D, ColoredConfig> for TrimStrategy {
     fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
         <Self as CellOption<_, _>>::change(self, records, cfg, Entity::Global)
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
diff --git a/tabled/src/settings/height/cell_height_increase.rs b/tabled/src/settings/height/cell_height_increase.rs
index 39887f9..ea3b2fb 100644
--- a/tabled/src/settings/height/cell_height_increase.rs
+++ b/tabled/src/settings/height/cell_height_increase.rs
@@ -71,8 +71,7 @@ where
     }
 }
 
-impl<R, W> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig>
-    for CellHeightIncrease<W>
+impl<R, W> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for CellHeightIncrease<W>
 where
     W: Measurement<Height>,
     R: Records + ExactRecords + PeekableRecords,
@@ -82,11 +81,15 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         let height = self.height.measure(&*records, cfg);
         TableHeightIncrease::new(height).change(records, cfg, dims)
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Row(0))
+    }
 }
 
 fn add_lines(s: &str, n: usize) -> String {
diff --git a/tabled/src/settings/height/cell_height_limit.rs b/tabled/src/settings/height/cell_height_limit.rs
index 788f030..a3aecd5 100644
--- a/tabled/src/settings/height/cell_height_limit.rs
+++ b/tabled/src/settings/height/cell_height_limit.rs
@@ -71,8 +71,7 @@ where
     }
 }
 
-impl<R, W> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig>
-    for CellHeightLimit<W>
+impl<R, W> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for CellHeightLimit<W>
 where
     W: Measurement<Height>,
     R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
@@ -82,7 +81,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         let height = self.height.measure(&*records, cfg);
         TableHeightLimit::new(height).change(records, cfg, dims)
diff --git a/tabled/src/settings/height/height_list.rs b/tabled/src/settings/height/height_list.rs
index 7861dd4..783e7cf 100644
--- a/tabled/src/settings/height/height_list.rs
+++ b/tabled/src/settings/height/height_list.rs
@@ -33,15 +33,15 @@ impl FromIterator<usize> for HeightList {
     }
 }
 
-impl<R, C> TableOption<R, CompleteDimensionVecRecords<'static>, C> for HeightList
+impl<R, C> TableOption<R, CompleteDimensionVecRecords<'_>, C> for HeightList
 where
     R: ExactRecords + Records,
 {
-    fn change(self, records: &mut R, _: &mut C, dims: &mut CompleteDimensionVecRecords<'static>) {
+    fn change(self, records: &mut R, _: &mut C, dims: &mut CompleteDimensionVecRecords<'_>) {
         if self.list.len() < records.count_rows() {
             return;
         }
 
-        let _ = dims.set_heights(self.list);
+        dims.set_heights(self.list);
     }
 }
diff --git a/tabled/src/settings/height/table_height_increase.rs b/tabled/src/settings/height/table_height_increase.rs
index f727bf0..6578137 100644
--- a/tabled/src/settings/height/table_height_increase.rs
+++ b/tabled/src/settings/height/table_height_increase.rs
@@ -1,6 +1,6 @@
 use crate::{
     grid::{
-        config::ColoredConfig,
+        config::{ColoredConfig, Entity},
         dimension::CompleteDimensionVecRecords,
         records::{ExactRecords, PeekableRecords, Records},
     },
@@ -44,7 +44,7 @@ impl<W> TableHeightIncrease<W, PriorityNone> {
     }
 }
 
-impl<R, W, P> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig>
+impl<R, W, P> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig>
     for TableHeightIncrease<W, P>
 where
     W: Measurement<Height>,
@@ -56,7 +56,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         if records.count_rows() == 0 || records.count_columns() == 0 {
             return;
@@ -70,7 +70,11 @@ where
 
         get_increase_list(&mut heights, height, total, self.priority);
 
-        let _ = dims.set_heights(heights);
+        dims.set_heights(heights);
+    }
+
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Row(0))
     }
 }
 
diff --git a/tabled/src/settings/height/table_height_limit.rs b/tabled/src/settings/height/table_height_limit.rs
index 2a3d19b..e304bed 100644
--- a/tabled/src/settings/height/table_height_limit.rs
+++ b/tabled/src/settings/height/table_height_limit.rs
@@ -45,7 +45,7 @@ impl<W> TableHeightLimit<W, PriorityNone> {
     }
 }
 
-impl<R, W, P> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig>
+impl<R, W, P> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig>
     for TableHeightLimit<W, P>
 where
     W: Measurement<Height>,
@@ -57,7 +57,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         let count_rows = records.count_rows();
         let count_cols = (&*records).count_columns();
@@ -89,7 +89,7 @@ where
             }
         }
 
-        let _ = dims.set_heights(heights);
+        dims.set_heights(heights);
     }
 }
 
diff --git a/tabled/src/settings/highlight/mod.rs b/tabled/src/settings/highlight/mod.rs
index 57df867..9428057 100644
--- a/tabled/src/settings/highlight/mod.rs
+++ b/tabled/src/settings/highlight/mod.rs
@@ -129,6 +129,10 @@ where
             set_border(cfg, &sector, self.border);
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 /// A [`Highlight`] object which works with a [`BorderColored`]
@@ -156,6 +160,10 @@ where
             set_border_color(cfg, sector, &self.border);
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        None
+    }
 }
 
 fn set_border_color(
diff --git a/tabled/src/settings/modify.rs b/tabled/src/settings/modify.rs
index c712a25..4eb6369 100644
--- a/tabled/src/settings/modify.rs
+++ b/tabled/src/settings/modify.rs
@@ -1,5 +1,8 @@
 use crate::{
-    grid::records::{ExactRecords, Records},
+    grid::{
+        config::Entity,
+        records::{ExactRecords, Records},
+    },
     settings::{object::Object, CellOption, Settings, TableOption},
 };
 
@@ -20,6 +23,27 @@ impl<O> Modify<O> {
     }
 
     /// A function which combines together [`Modify::new`] and [`Modify::with`] calls.
+    ///
+    /// ```
+    /// use tabled::{Table, settings::{Modify, Padding, object::Rows}};
+    ///
+    /// let table = Table::new(&["Year", "2021"])
+    ///     .with(Modify::list(Rows::first(), Padding::new(1, 1, 1, 1)))
+    ///     .to_string();
+    ///
+    /// assert_eq!(
+    ///     table,
+    ///     "+------+\n\
+    ///      |      |\n\
+    ///      | &str |\n\
+    ///      |      |\n\
+    ///      +------+\n\
+    ///      | Year |\n\
+    ///      +------+\n\
+    ///      | 2021 |\n\
+    ///      +------+"
+    /// )
+    /// ```
     pub const fn list<M>(obj: O, next: M) -> ModifyList<O, M> {
         ModifyList {
             obj,
@@ -33,6 +57,27 @@ impl<O> Modify<O> {
     ///     The function *doesn't* changes a [`Table`].
     ///     [`Table`] will be changed only after passing [`Modify`] object to [`Table::with`].
     ///
+    /// ```
+    /// use tabled::{Table, settings::{Modify, Padding, object::Rows}};
+    ///
+    /// let table = Table::new(&["Year", "2021"])
+    ///     .with(Modify::new(Rows::first()).with(Padding::new(1, 1, 1, 1)))
+    ///     .to_string();
+    ///
+    /// assert_eq!(
+    ///     table,
+    ///     "+------+\n\
+    ///      |      |\n\
+    ///      | &str |\n\
+    ///      |      |\n\
+    ///      +------+\n\
+    ///      | Year |\n\
+    ///      +------+\n\
+    ///      | 2021 |\n\
+    ///      +------+"
+    /// )
+    /// ```
+    ///
     /// [`Table`]: crate::Table
     /// [`Table::with`]: crate::Table::with
     pub fn with<M>(self, next: M) -> ModifyList<O, M> {
@@ -78,4 +123,8 @@ where
             self.modifiers.clone().change(records, cfg, entity);
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        self.modifiers.hint_change()
+    }
 }
diff --git a/tabled/src/settings/settings_list.rs b/tabled/src/settings/settings_list.rs
index dc8aec1..46cfcd1 100644
--- a/tabled/src/settings/settings_list.rs
+++ b/tabled/src/settings/settings_list.rs
@@ -1,7 +1,5 @@
-use crate::settings::TableOption;
+use crate::{grid::config::Entity, settings::TableOption};
 
-#[cfg(feature = "std")]
-use crate::grid::config::Entity;
 #[cfg(feature = "std")]
 use crate::settings::CellOption;
 
@@ -44,6 +42,15 @@ where
         self.0.change(records, cfg, entity);
         self.1.change(records, cfg, entity);
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        match (self.0.hint_change(), self.1.hint_change()) {
+            (None, None) => None,
+            (Some(a), Some(b)) => Some(combine_entity(a, b)),
+            (None, value) => value,
+            (value, None) => value,
+        }
+    }
 }
 
 impl<R, D, C, A, B> TableOption<R, D, C> for Settings<A, B>
@@ -55,6 +62,15 @@ where
         self.0.change(records, cfg, dims);
         self.1.change(records, cfg, dims);
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        match (self.0.hint_change(), self.1.hint_change()) {
+            (None, None) => None,
+            (Some(a), Some(b)) => Some(combine_entity(a, b)),
+            (None, value) => value,
+            (value, None) => value,
+        }
+    }
 }
 
 /// A marker structure to be able to create an empty [`Settings`].
@@ -69,3 +85,20 @@ impl<R, C> CellOption<R, C> for EmptySettings {
 impl<R, D, C> TableOption<R, D, C> for EmptySettings {
     fn change(self, _: &mut R, _: &mut C, _: &mut D) {}
 }
+
+fn combine_entity(x1: Entity, x2: Entity) -> Entity {
+    use Entity::*;
+    match (x1, x2) {
+        (_, Global) => Global,
+        (Global, _) => Global,
+        (Column(_), Row(_)) => Global,
+        (Column(a), Column(_)) => Column(a),
+        (Column(a), Cell(_, _)) => Column(a),
+        (Row(_), Column(_)) => Global,
+        (Row(a), Row(_)) => Row(a),
+        (Row(a), Cell(_, _)) => Row(a),
+        (Cell(_, _), Column(a)) => Column(a),
+        (Cell(_, _), Row(a)) => Row(a),
+        (Cell(a, b), Cell(_, _)) => Cell(a, b),
+    }
+}
diff --git a/tabled/src/settings/table_option.rs b/tabled/src/settings/table_option.rs
index e20aa44..0162575 100644
--- a/tabled/src/settings/table_option.rs
+++ b/tabled/src/settings/table_option.rs
@@ -1,11 +1,52 @@
+use crate::grid::config::Entity;
+
 /// A trait which is responsible for configuration of a [`Table`].
 ///
 /// [`Table`]: crate::Table
 pub trait TableOption<R, D, C> {
     /// The function allows modification of records and a grid configuration.
     fn change(self, records: &mut R, cfg: &mut C, dimension: &mut D);
+
+    /// A hint whether an [`TableOption`] is going to change table layout.
+    ///
+    /// Return [`None`] if no changes are being done.
+    /// Otherwise return:
+    ///
+    /// - [Entity::Global] - a grand layout changed. (a change which MIGHT require height/width update)
+    /// - [Entity::Row] - a certain row was changed. (a change which MIGHT require height update)
+    /// - [Entity::Column] - a certain column was changed. (a change which MIGHT require width update)
+    /// - [Entity::Cell] - a certain cell was changed. (a local change, no width/height update)
+    ///
+    /// By default it's considered to be a grand change.
+    ///
+    /// This methods primarily is used as an optimization,
+    /// to not make unnessary calculations if they're not needed, after using the [`TableOption`].
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Global)
+    }
 }
 
+// todo: probably we could add one more hint but it likely require Vec<Entity>,
+// so, as I am not sure about exact interface it's better be commented.
+// /// A hint which layout part a [`TableOption`] is going to change.
+// ///
+// /// Return [`None`] if no part are being changed.
+// /// Otherwise return:
+// ///
+// /// - [Entity::Global] - a total layout affection.
+// /// - [Entity::Row] - a certain row affection.
+// /// - [Entity::Column] - a certain column affection.
+// /// - [Entity::Cell] - a certain cell affection.
+// ///
+// /// By default it's considered to be a grand change.
+// ///
+// /// This methods primarily is used as an optimization,
+// /// to not make unnessary calculations if they're not needed, after using the [`TableOption`].
+// fn hint_target(&self, records: &R) -> Option<Vec<Entity>> {
+//     let _ = records;
+//     Some(vec![Entity::Global])
+// }
+
 impl<T, R, D, C> TableOption<R, D, C> for &[T]
 where
     for<'a> &'a T: TableOption<R, D, C>,
diff --git a/tabled/src/settings/themes/column_names.rs b/tabled/src/settings/themes/column_names.rs
index 2bf8a98..efb3680 100644
--- a/tabled/src/settings/themes/column_names.rs
+++ b/tabled/src/settings/themes/column_names.rs
@@ -216,14 +216,14 @@ impl ColumnNames {
     }
 }
 
-impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'static>, ColoredConfig>
+impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'_>, ColoredConfig>
     for ColumnNames
 {
     fn change(
         self,
         records: &mut VecRecords<CellInfo<String>>,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         let count_rows = records.count_rows();
         let count_columns = records.count_columns();
@@ -255,7 +255,7 @@ impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'stat
             .map(|(width, text)| cmp::max(string_width(text), width))
             .collect::<Vec<_>>();
 
-        let _ = dims.set_widths(widths.clone());
+        dims.set_widths(widths.clone());
 
         let mut total_width = 0;
         for (i, (width, name)) in widths.into_iter().zip(names).enumerate() {
diff --git a/tabled/src/settings/width/min_width.rs b/tabled/src/settings/width/min_width.rs
index afb9ae3..7dbfbcf 100644
--- a/tabled/src/settings/width/min_width.rs
+++ b/tabled/src/settings/width/min_width.rs
@@ -130,9 +130,13 @@ where
             records.set(pos, content);
         }
     }
+
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Column(0))
+    }
 }
 
-impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig> for MinWidth<W, P>
+impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for MinWidth<W, P>
 where
     W: Measurement<Width>,
     P: Peaker,
@@ -143,7 +147,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         if records.count_rows() == 0 || records.count_columns() == 0 {
             return;
@@ -157,7 +161,11 @@ where
         }
 
         let widths = get_increase_list(widths, nessary_width, total_width, P::create());
-        let _ = dims.set_widths(widths);
+        dims.set_widths(widths);
+    }
+
+    fn hint_change(&self) -> Option<Entity> {
+        Some(Entity::Column(0))
     }
 }
 
diff --git a/tabled/src/settings/width/truncate.rs b/tabled/src/settings/width/truncate.rs
index c7336f0..a0a57da 100644
--- a/tabled/src/settings/width/truncate.rs
+++ b/tabled/src/settings/width/truncate.rs
@@ -299,8 +299,7 @@ fn make_suffix<'a>(suffix: &'a TruncateSuffix<'_>, width: usize) -> (Cow<'a, str
     }
 }
 
-impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig>
-    for Truncate<'_, W, P>
+impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for Truncate<'_, W, P>
 where
     W: Measurement<Width>,
     P: Peaker,
@@ -311,7 +310,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         if records.count_rows() == 0 || records.count_columns() == 0 {
             return;
@@ -336,7 +335,7 @@ where
             records, cfg, widths, total, width, priority, suffix, multiline,
         );
 
-        let _ = dims.set_widths(widths);
+        dims.set_widths(widths);
     }
 }
 
diff --git a/tabled/src/settings/width/width_list.rs b/tabled/src/settings/width/width_list.rs
index 7547b97..08ed418 100644
--- a/tabled/src/settings/width/width_list.rs
+++ b/tabled/src/settings/width/width_list.rs
@@ -31,20 +31,15 @@ impl FromIterator<usize> for WidthList {
     }
 }
 
-impl<R, C> TableOption<R, CompleteDimensionVecRecords<'static>, C> for WidthList
+impl<R, C> TableOption<R, CompleteDimensionVecRecords<'_>, C> for WidthList
 where
     R: Records,
 {
-    fn change(
-        self,
-        records: &mut R,
-        _: &mut C,
-        dimension: &mut CompleteDimensionVecRecords<'static>,
-    ) {
+    fn change(self, records: &mut R, _: &mut C, dimension: &mut CompleteDimensionVecRecords<'_>) {
         if self.list.len() < records.count_columns() {
             return;
         }
 
-        let _ = dimension.set_widths(self.list);
+        dimension.set_widths(self.list);
     }
 }
diff --git a/tabled/src/settings/width/wrap.rs b/tabled/src/settings/width/wrap.rs
index 96a3704..63b818f 100644
--- a/tabled/src/settings/width/wrap.rs
+++ b/tabled/src/settings/width/wrap.rs
@@ -97,7 +97,7 @@ impl Wrap<(), ()> {
     }
 }
 
-impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'static>, ColoredConfig> for Wrap<W, P>
+impl<W, P, R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for Wrap<W, P>
 where
     W: Measurement<Width>,
     P: Peaker,
@@ -108,7 +108,7 @@ where
         self,
         records: &mut R,
         cfg: &mut ColoredConfig,
-        dims: &mut CompleteDimensionVecRecords<'static>,
+        dims: &mut CompleteDimensionVecRecords<'_>,
     ) {
         if records.count_rows() == 0 || records.count_columns() == 0 {
             return;
@@ -124,7 +124,7 @@ where
         let keep_words = self.keep_words;
         let widths = wrap_total_width(records, cfg, widths, total, width, keep_words, priority);
 
-        let _ = dims.set_widths(widths);
+        dims.set_widths(widths);
     }
 }
 
diff --git a/tabled/src/tables/table.rs b/tabled/src/tables/table.rs
index b63902b..9eb365e 100644
--- a/tabled/src/tables/table.rs
+++ b/tabled/src/tables/table.rs
@@ -177,19 +177,19 @@ impl Table {
     /// It applies settings immediately.
     pub fn with<O>(&mut self, option: O) -> &mut Self
     where
-        O: TableOption<
+        for<'a> O: TableOption<
             VecRecords<CellInfo<String>>,
-            CompleteDimensionVecRecords<'static>,
+            CompleteDimensionVecRecords<'a>,
             ColoredConfig,
         >,
     {
-        // todo: because we do it we can't reuse cached values....
-        // better we set a clear flag and then after option is done check if we need to clear or it was reset by the option.
+        let reastimation_hint = option.hint_change();
+        let mut dims = self.dimension.from_origin();
 
-        self.dimension.clear_width();
-        self.dimension.clear_height();
+        option.change(&mut self.records, &mut self.config, &mut dims);
 
-        option.change(&mut self.records, &mut self.config, &mut self.dimension);
+        let (widths, heights) = dims.into_inner();
+        dimension_reastimate(&mut self.dimension, widths, heights, reastimation_hint);
 
         self
     }
@@ -465,3 +465,64 @@ fn print_grid<F: fmt::Write, D: Dimension>(
         PeekableGrid::new(records, cfg, &dims, NoColors).build(f)
     }
 }
+
+fn dimension_reastimate(
+    dims: &mut CompleteDimensionVecRecords<'_>,
+    widths: Option<Vec<usize>>,
+    heights: Option<Vec<usize>>,
+    hint: Option<Entity>,
+) {
+    let hint = match hint {
+        Some(hint) => hint,
+        None => return,
+    };
+
+    match hint {
+        Entity::Global | Entity::Cell(_, _) => {
+            dims_set_widths(dims, widths);
+            dims_set_heights(dims, heights);
+        }
+        Entity::Column(_) => {
+            dims_set_widths(dims, widths);
+        }
+        Entity::Row(_) => {
+            dims_set_heights(dims, heights);
+        }
+    }
+}
+
+fn dims_set_widths(dims: &mut CompleteDimensionVecRecords<'_>, list: Option<Vec<usize>>) {
+    match list {
+        Some(list) => match dims.get_widths() {
+            Some(widths) => {
+                if widths == list {
+                    dims.clear_width();
+                } else {
+                    dims.set_widths(list);
+                }
+            }
+            None => dims.set_widths(list),
+        },
+        None => {
+            dims.clear_width();
+        }
+    }
+}
+
+fn dims_set_heights(dims: &mut CompleteDimensionVecRecords<'_>, list: Option<Vec<usize>>) {
+    match list {
+        Some(list) => match dims.get_heights() {
+            Some(heights) => {
+                if heights == list {
+                    dims.clear_height();
+                } else {
+                    dims.set_heights(list);
+                }
+            }
+            None => dims.set_heights(list),
+        },
+        None => {
+            dims.clear_height();
+        }
+    }
+}


Test patch:
diff --git a/tabled/tests/matrix/matrix.rs b/tabled/tests/matrix/matrix.rs
index 48ba55f..3a55a7a 100644
--- a/tabled/tests/matrix/matrix.rs
+++ b/tabled/tests/matrix/matrix.rs
@@ -93,9 +93,9 @@ impl Matrix {
 
     pub fn with<O>(self, opt: O) -> Table
     where
-        O: TableOption<
+        for<'a> O: TableOption<
             VecRecords<CellInfo<String>>,
-            CompleteDimensionVecRecords<'static>,
+            CompleteDimensionVecRecords<'a>,
             ColoredConfig,
         >,
     {