diff --git a/papergrid/src/colors.rs b/papergrid/src/colors.rs index aabcb8b7..e34b8481 100644 --- a/papergrid/src/colors.rs +++ b/papergrid/src/colors.rs @@ -64,17 +64,16 @@ where #[cfg(feature = "std")] impl Colors for crate::config::spanned::EntityMap> where - C: ANSIFmt, + C: ANSIFmt + PartialEq, { type Color = C; fn get_color(&self, pos: Position) -> Option<&Self::Color> { - self.get(pos.into()).as_ref() + self.get(pos).as_ref() } fn is_empty(&self) -> bool { - crate::config::spanned::EntityMap::is_empty(self) - && self.get(crate::config::Entity::Global).is_none() + self.is_empty() && self.as_ref().is_none() } } diff --git a/papergrid/src/config/sides.rs b/papergrid/src/config/sides.rs index 25b5bcc4..3185985f 100644 --- a/papergrid/src/config/sides.rs +++ b/papergrid/src/config/sides.rs @@ -56,3 +56,10 @@ impl Sides { ) } } + +impl Sides> { + /// Checkes whether any option was set + pub const fn is_empty(&self) -> bool { + self.left.is_none() && self.right.is_none() && self.top.is_none() && self.bottom.is_none() + } +} diff --git a/papergrid/src/config/spanned/entity_map.rs b/papergrid/src/config/spanned/entity_map.rs index 2a6d56b1..79f072c4 100644 --- a/papergrid/src/config/spanned/entity_map.rs +++ b/papergrid/src/config/spanned/entity_map.rs @@ -32,40 +32,29 @@ impl EntityMap { } /// Get a value for an [`Entity`]. - pub fn get(&self, entity: Entity) -> &T { - if self.rows.is_empty() && self.columns.is_empty() && self.cells.is_empty() { - return &self.global; - } - - match entity { - Entity::Column(col) => self.columns.get(&col).unwrap_or(&self.global), - Entity::Row(row) => self.rows.get(&row).unwrap_or(&self.global), - Entity::Cell(row, col) => { - // todo: optimize; - // - // Cause we can change rows/columns/cells separately we need to check them separately. - // But we often doing this checks in `Grid::fmt` and I believe if we could optimize it it could be beneficial. - // - // Haven't found a solution for that yet. - // - // I was wondering if there is a hash function like. - // Apparently it doesn't make sense cause we will reset columns/rows on cell insert which is not what we want. - // - // ``` - // hash(column, row) == hash(column) == hash(row) - // ``` - // - // ref: https://opendsa-server.cs.vt.edu/ODSA/Books/Everything/html/Sparse.html - // ref: https://users.rust-lang.org/t/make-hash-return-same-value-whather-the-order-of-element-of-a-tuple/69932/13 - - self.cells - .get(&(row, col)) - .or_else(|| self.columns.get(&col)) - .or_else(|| self.rows.get(&row)) - .unwrap_or(&self.global) - } - Entity::Global => &self.global, - } + pub fn get(&self, (row, col): Position) -> &T { + // todo: optimize; + // + // Cause we can change rows/columns/cells separately we need to check them separately. + // But we often doing this checks in `Grid::fmt` and I believe if we could optimize it it could be beneficial. + // + // Haven't found a solution for that yet. + // + // I was wondering if there is a hash function like. + // Apparently it doesn't make sense cause we will reset columns/rows on cell insert which is not what we want. + // + // ``` + // hash(column, row) == hash(column) == hash(row) + // ``` + // + // ref: https://opendsa-server.cs.vt.edu/ODSA/Books/Everything/html/Sparse.html + // ref: https://users.rust-lang.org/t/make-hash-return-same-value-whather-the-order-of-element-of-a-tuple/69932/13 + + self.cells + .get(&(row, col)) + .or_else(|| self.columns.get(&col)) + .or_else(|| self.rows.get(&row)) + .unwrap_or(&self.global) } /// Removes a value for an [`Entity`]. @@ -134,3 +123,9 @@ impl From> for HashMap { m } } + +impl AsRef for EntityMap { + fn as_ref(&self) -> &T { + &self.global + } +} diff --git a/papergrid/src/config/spanned/mod.rs b/papergrid/src/config/spanned/mod.rs index 5da02074..a41046b3 100644 --- a/papergrid/src/config/spanned/mod.rs +++ b/papergrid/src/config/spanned/mod.rs @@ -10,7 +10,6 @@ use std::collections::HashMap; use crate::ansi::{ANSIBuf, ANSIStr}; use crate::config::compact::CompactConfig; -use crate::config::Formatting; use crate::config::{ AlignmentHorizontal, AlignmentVertical, Border, Borders, Entity, Indent, Position, Sides, }; @@ -18,6 +17,8 @@ use borders_config::BordersConfig; pub use self::{entity_map::EntityMap, offset::Offset}; +use super::Formatting; + /// HorizontalLine represents a horizontal border line. type HorizontalLine = super::HorizontalLine; @@ -29,11 +30,14 @@ type VerticalLine = super::VerticalLine; /// grid: crate::Grid. #[derive(Debug, PartialEq, Eq, Clone)] pub struct SpannedConfig { - margin: Sides, - padding: EntityMap>, + margin: Sides, + padding: EntityMap>, + padding_color: EntityMap>>, alignment_h: EntityMap, alignment_v: EntityMap, - formatting: EntityMap, + formatting_trim_h: EntityMap, + formatting_trim_v: EntityMap, + formatting_line_alignment: EntityMap, span_columns: HashMap, span_rows: HashMap, borders: BordersConfig, @@ -52,7 +56,10 @@ impl Default for SpannedConfig { Self { margin: Sides::default(), padding: EntityMap::default(), - formatting: EntityMap::default(), + padding_color: EntityMap::default(), + formatting_trim_h: EntityMap::default(), + formatting_trim_v: EntityMap::default(), + formatting_line_alignment: EntityMap::default(), alignment_h: EntityMap::new(AlignmentHorizontal::Left), alignment_v: EntityMap::new(AlignmentVertical::Top), span_columns: HashMap::default(), @@ -413,56 +420,61 @@ impl SpannedConfig { /// Set a padding to a given cells. pub fn set_padding(&mut self, entity: Entity, padding: Sides) { - let mut pad = self.padding.get(entity).clone(); - pad.left.indent = padding.left; - pad.right.indent = padding.right; - pad.top.indent = padding.top; - pad.bottom.indent = padding.bottom; - - self.padding.insert(entity, pad); + self.padding.insert(entity, padding); } /// Set a padding to a given cells. pub fn set_padding_color(&mut self, entity: Entity, padding: Sides>) { - let mut pad = self.padding.get(entity).clone(); - pad.left.color = padding.left; - pad.right.color = padding.right; - pad.top.color = padding.top; - pad.bottom.color = padding.bottom; + self.padding_color.insert(entity, padding); + } - self.padding.insert(entity, pad); + /// Get a padding for a given cell by [Position]. + pub fn get_padding(&self, pos: Position) -> Sides { + *self.padding.get(pos) } - /// Get a padding for a given [Entity]. - pub fn get_padding(&self, entity: Entity) -> Sides { - let pad = self.padding.get(entity); - Sides::new( - pad.left.indent, - pad.right.indent, - pad.top.indent, - pad.bottom.indent, - ) + /// Get a padding color for a given cell by [Position]. + pub fn get_padding_color(&self, pos: Position) -> Sides> { + self.padding_color.get(pos).clone() } - /// Get a padding color for a given [Entity]. - pub fn get_padding_color(&self, entity: Entity) -> Sides> { - let pad = self.padding.get(entity); - Sides::new( - pad.left.color.clone(), - pad.right.color.clone(), - pad.top.color.clone(), - pad.bottom.color.clone(), - ) + /// Set a formatting to a given cells. + pub fn set_trim_horizontal(&mut self, entity: Entity, on: bool) { + self.formatting_trim_h.insert(entity, on); + } + + /// Get a formatting settings for a given cell by [Position]. + pub fn get_trim_horizonal(&self, pos: Position) -> bool { + *self.formatting_trim_h.get(pos) + } + + /// Set a formatting to a given cells. + pub fn set_trim_vertical(&mut self, entity: Entity, on: bool) { + self.formatting_trim_v.insert(entity, on); + } + + /// Get a formatting settings for a given cell by [Position]. + pub fn get_trim_vertical(&self, pos: Position) -> bool { + *self.formatting_trim_v.get(pos) } /// Set a formatting to a given cells. - pub fn set_formatting(&mut self, entity: Entity, formatting: Formatting) { - self.formatting.insert(entity, formatting); + pub fn set_line_alignment(&mut self, entity: Entity, on: bool) { + self.formatting_line_alignment.insert(entity, on); } - /// Get a formatting settings for a given [Entity]. - pub fn get_formatting(&self, entity: Entity) -> &Formatting { - self.formatting.get(entity) + /// Get a formatting settings for a given cell by [Position]. + pub fn get_line_alignment(&self, pos: Position) -> bool { + *self.formatting_line_alignment.get(pos) + } + + /// Get a formatting settings for a given cell by [Position]. + pub fn get_formatting(&self, pos: Position) -> Formatting { + Formatting::new( + *self.formatting_trim_h.get(pos), + *self.formatting_trim_v.get(pos), + *self.formatting_line_alignment.get(pos), + ) } /// Set a vertical alignment to a given cells. @@ -470,9 +482,9 @@ impl SpannedConfig { self.alignment_v.insert(entity, alignment); } - /// Get a vertical alignment for a given [Entity]. - pub fn get_alignment_vertical(&self, entity: Entity) -> &AlignmentVertical { - self.alignment_v.get(entity) + /// Get a vertical alignment for a given cell by [Position]. + pub fn get_alignment_vertical(&self, pos: Position) -> &AlignmentVertical { + self.alignment_v.get(pos) } /// Set a horizontal alignment to a given cells. @@ -480,9 +492,9 @@ impl SpannedConfig { self.alignment_h.insert(entity, alignment); } - /// Get a horizontal alignment for a given [Entity]. - pub fn get_alignment_horizontal(&self, entity: Entity) -> &AlignmentHorizontal { - self.alignment_h.get(entity) + /// Get a horizontal alignment for a given cell by [Position]. + pub fn get_alignment_horizontal(&self, pos: Position) -> &AlignmentHorizontal { + self.alignment_h.get(pos) } /// Set border set a border value to all cells in [`Entity`]. @@ -555,15 +567,15 @@ impl SpannedConfig { } /// Get a justification which will be used while expanding cells width/height. - pub fn get_justification(&self, entity: Entity) -> char { - *self.justification.get(entity) + pub fn get_justification(&self, pos: Position) -> char { + *self.justification.get(pos) } /// Get a justification color which will be used while expanding cells width/height. /// /// `None` means no color. - pub fn get_justification_color(&self, entity: Entity) -> Option<&ANSIBuf> { - self.justification_color.get(entity).as_ref() + pub fn get_justification_color(&self, pos: Position) -> Option<&ANSIBuf> { + self.justification_color.get(pos).as_ref() } /// Set a justification which will be used while expanding cells width/height. @@ -650,7 +662,9 @@ impl SpannedConfig { /// Verifies if there's any colors set for a borders. pub fn has_justification(&self) -> bool { - !self.justification.is_empty() || !self.justification_color.is_empty() + !self.justification.is_empty() + || !self.justification_color.is_empty() + || self.justification_color.as_ref().is_some() } /// Verifies if there's any custom padding set. @@ -660,29 +674,27 @@ impl SpannedConfig { /// Verifies if there's any custom padding set. pub fn has_padding_color(&self) -> bool { - let map = HashMap::from(self.padding.clone()); - let mut has_color = false; - for (entity, value) in map { - if matches!(entity, Entity::Global) { - continue; - } - - has_color = value.bottom.color.is_some() - || value.top.color.is_some() - || value.left.color.is_some() - || value.right.color.is_some(); + if !self.padding_color.is_empty() { + let map = HashMap::from(self.padding_color.clone()); + for (entity, value) in map { + if matches!(entity, Entity::Global) { + continue; + } - if has_color { - break; + if !value.is_empty() { + return true; + } } } - has_color + !self.padding_color.as_ref().is_empty() } /// Verifies if there's any custom formatting set. pub fn has_formatting(&self) -> bool { - !self.formatting.is_empty() + !self.formatting_trim_h.is_empty() + || !self.formatting_trim_v.is_empty() + || !self.formatting_line_alignment.is_empty() } /// Verifies if there's any custom alignment vertical set. @@ -898,15 +910,9 @@ fn is_cell_covered_by_both_spans(cfg: &SpannedConfig, pos: Position) -> bool { }) } -#[derive(Default, Debug, Clone, PartialEq, Eq)] -struct ColoredIndent { - indent: Indent, - color: Option, -} - /// A colorefull margin indent. #[derive(Debug, Clone, PartialEq, Eq)] -struct ColoredMarginIndent { +struct MarginIndent { /// An indent value. indent: Indent, /// An offset value. @@ -915,7 +921,7 @@ struct ColoredMarginIndent { color: Option, } -impl Default for ColoredMarginIndent { +impl Default for MarginIndent { fn default() -> Self { Self { indent: Indent::default(), diff --git a/papergrid/src/dimension/spanned.rs b/papergrid/src/dimension/spanned.rs index 8c5e4e5b..7d52669d 100644 --- a/papergrid/src/dimension/spanned.rs +++ b/papergrid/src/dimension/spanned.rs @@ -113,7 +113,7 @@ where let text = cell.as_ref(); let (height, width) = get_text_dimension(text); - let pad = cfg.get_padding(pos.into()); + let pad = cfg.get_padding(pos); let width = width + pad.left.size + pad.right.size; let height = height + pad.top.size + pad.bottom.size; @@ -204,7 +204,7 @@ fn count_horizontal_borders(cfg: &SpannedConfig, len: usize, start: usize, end: fn get_cell_height(cell: &str, cfg: &SpannedConfig, pos: Position) -> usize { let count_lines = max(1, count_lines(cell)); - let padding = cfg.get_padding(pos.into()); + let padding = cfg.get_padding(pos); count_lines + padding.top.size + padding.bottom.size } @@ -279,7 +279,7 @@ fn get_cell_width(text: &str, cfg: &SpannedConfig, pos: Position) -> usize { } fn get_cell_padding(cfg: &SpannedConfig, pos: Position) -> usize { - let padding = cfg.get_padding(pos.into()); + let padding = cfg.get_padding(pos); padding.left.size + padding.right.size } diff --git a/papergrid/src/dimension/spanned_vec_records.rs b/papergrid/src/dimension/spanned_vec_records.rs index 75e85a85..88aefb04 100644 --- a/papergrid/src/dimension/spanned_vec_records.rs +++ b/papergrid/src/dimension/spanned_vec_records.rs @@ -92,7 +92,7 @@ fn build_dimensions>( let width = cell.width(); let height = cell.count_lines(); - let pad = cfg.get_padding(pos.into()); + let pad = cfg.get_padding(pos); let width = width + pad.left.size + pad.right.size; let height = height + pad.top.size + pad.bottom.size; @@ -246,12 +246,12 @@ fn adjust_column_range( } fn get_cell_padding_horizontal(cfg: &SpannedConfig, pos: Position) -> usize { - let padding = cfg.get_padding(pos.into()); + let padding = cfg.get_padding(pos); padding.left.size + padding.right.size } fn get_cell_vertical_padding(cfg: &SpannedConfig, pos: Position) -> usize { - let padding = cfg.get_padding(pos.into()); + let padding = cfg.get_padding(pos); padding.top.size + padding.bottom.size } diff --git a/papergrid/src/grid/iterable.rs b/papergrid/src/grid/iterable.rs index e97fad73..c32fd263 100644 --- a/papergrid/src/grid/iterable.rs +++ b/papergrid/src/grid/iterable.rs @@ -10,8 +10,10 @@ use std::{ use crate::{ ansi::{ANSIBuf, ANSIFmt}, colors::Colors, - config::spanned::{Offset, SpannedConfig}, - config::{AlignmentHorizontal, AlignmentVertical, Formatting, Indent, Position, Sides}, + config::{ + spanned::{Offset, SpannedConfig}, + AlignmentHorizontal, AlignmentVertical, Formatting, Indent, Position, Sides, + }, dimension::Dimension, records::{IntoRecords, Records}, util::string::{count_lines, get_line_width, get_lines, get_text_width, Lines}, @@ -292,7 +294,6 @@ fn print_single_line_column( color: Option<&C>, pos: Position, ) -> fmt::Result { - let pos = pos.into(); let pad = cfg.get_padding(pos); let pad_color = cfg.get_padding_color(pos); let fmt = cfg.get_formatting(pos); @@ -782,14 +783,14 @@ where color: Option, pos: Position, ) -> Cell { - let fmt = *cfg.get_formatting(pos.into()); - let pad = cfg.get_padding(pos.into()); - let pad_color = cfg.get_padding_color(pos.into()).clone(); - let alignh = *cfg.get_alignment_horizontal(pos.into()); - let alignv = *cfg.get_alignment_vertical(pos.into()); + let fmt = cfg.get_formatting(pos); + let pad = cfg.get_padding(pos); + let pad_color = cfg.get_padding_color(pos).clone(); + let alignh = *cfg.get_alignment_horizontal(pos); + let alignv = *cfg.get_alignment_vertical(pos); let justification = ( - cfg.get_justification(pos.into()), - cfg.get_justification_color(pos.into()).cloned(), + cfg.get_justification(pos), + cfg.get_justification_color(pos).cloned(), ); let (count_lines, skip) = if fmt.vertical_trim { diff --git a/papergrid/src/grid/peekable.rs b/papergrid/src/grid/peekable.rs index 8f478412..deddac6f 100644 --- a/papergrid/src/grid/peekable.rs +++ b/papergrid/src/grid/peekable.rs @@ -14,7 +14,7 @@ use crate::{ spanned::{Offset, SpannedConfig}, Formatting, }, - config::{AlignmentHorizontal, AlignmentVertical, Entity, Indent, Position, Sides}, + config::{AlignmentHorizontal, AlignmentVertical, Indent, Position, Sides}, dimension::Dimension, records::{ExactRecords, PeekableRecords, Records}, util::string::get_line_width, @@ -103,11 +103,10 @@ where } let is_basic = !ctx.cfg.has_border_colors() + && !ctx.cfg.has_padding_color() && !ctx.cfg.has_justification() - && ctx.cfg.get_justification_color(Entity::Global).is_none() && !ctx.cfg.has_offset_chars() && !has_margin(ctx.cfg) - && !has_padding_color(ctx.cfg) && ctx.colors.is_empty(); if is_basic { @@ -122,14 +121,6 @@ fn has_margin(cfg: &SpannedConfig) -> bool { margin.left.size > 0 || margin.right.size > 0 || margin.top.size > 0 || margin.bottom.size > 0 } -fn has_padding_color(cfg: &SpannedConfig) -> bool { - let pad = cfg.get_padding_color(Entity::Global); - let has_pad = - pad.left.is_some() || pad.right.is_some() || pad.top.is_some() || pad.bottom.is_some(); - - has_pad || cfg.has_padding_color() -} - mod grid_basic { use super::*; @@ -322,16 +313,14 @@ mod grid_basic { R: Records + PeekableRecords + ExactRecords, D: Dimension, { - let entity = Entity::from(pos); - let width = ctx.dims.get_width(pos.1); - let pad = ctx.cfg.get_padding(entity); - let valignment = *ctx.cfg.get_alignment_vertical(entity); + let pad = ctx.cfg.get_padding(pos); + let valignment = *ctx.cfg.get_alignment_vertical(pos); let text_cfg = TextCfg { - alignment: *ctx.cfg.get_alignment_horizontal(entity), - formatting: *ctx.cfg.get_formatting(entity), - justification: ctx.cfg.get_justification(Entity::Global), + alignment: *ctx.cfg.get_alignment_horizontal(pos), + formatting: ctx.cfg.get_formatting(pos), + justification: ctx.cfg.get_justification(pos), }; let mut cell_height = ctx.records.count_lines(pos); @@ -833,24 +822,22 @@ mod grid_not_spanned { C: Colors, D: Dimension, { - let entity = pos.into(); - let width = ctx.dims.get_width(pos.1); - let formatting = ctx.cfg.get_formatting(entity); + let formatting = ctx.cfg.get_formatting(pos); let text_cfg = TextCfg { - alignment: *ctx.cfg.get_alignment_horizontal(entity), + alignment: *ctx.cfg.get_alignment_horizontal(pos), color: ctx.colors.get_color(pos), justification: Colored::new( - ctx.cfg.get_justification(entity), - ctx.cfg.get_justification_color(entity), + ctx.cfg.get_justification(pos), + ctx.cfg.get_justification_color(pos), ), - formatting: *formatting, + formatting, }; - let pad = ctx.cfg.get_padding(entity); - let pad_color = ctx.cfg.get_padding_color(entity); - let valignment = *ctx.cfg.get_alignment_vertical(entity); + let pad = ctx.cfg.get_padding(pos); + let pad_color = ctx.cfg.get_padding_color(pos); + let valignment = *ctx.cfg.get_alignment_vertical(pos); let mut cell_height = ctx.records.count_lines(pos); if formatting.vertical_trim { @@ -1699,10 +1686,8 @@ mod grid_spanned { R: Records + PeekableRecords + ExactRecords, C: Colors, { - let entity = pos.into(); - let mut cell_height = ctx.records.count_lines(pos); - let formatting = ctx.cfg.get_formatting(entity); + let formatting = ctx.cfg.get_formatting(pos); if formatting.vertical_trim { cell_height -= count_empty_lines_at_start(ctx.records, pos) + count_empty_lines_at_end(ctx.records, pos); @@ -1713,9 +1698,9 @@ mod grid_spanned { cell_height = height; } - let pad = ctx.cfg.get_padding(entity); - let pad_color = ctx.cfg.get_padding_color(entity); - let alignment = ctx.cfg.get_alignment_vertical(entity); + let pad = ctx.cfg.get_padding(pos); + let pad_color = ctx.cfg.get_padding_color(pos); + let alignment = ctx.cfg.get_alignment_vertical(pos); let indent = top_indent(&pad, *alignment, cell_height, height); if indent > line { return print_indent(f, pad.top.fill, width, pad_color.top.as_ref()); @@ -1742,13 +1727,13 @@ mod grid_spanned { let width = width - pad.left.size - pad.right.size; let line_cfg = TextCfg { - alignment: *ctx.cfg.get_alignment_horizontal(entity), - formatting: *formatting, + alignment: *ctx.cfg.get_alignment_horizontal(pos), color: ctx.colors.get_color(pos), justification: Colored::new( - ctx.cfg.get_justification(entity), - ctx.cfg.get_justification_color(entity), + ctx.cfg.get_justification(pos), + ctx.cfg.get_justification_color(pos), ), + formatting, }; print_line(f, ctx.records, pos, index, width, line_cfg)?; diff --git a/papergrid/tests/grid/format_configuration.rs b/papergrid/tests/grid/format_configuration.rs index c4891dea..288839cc 100644 --- a/papergrid/tests/grid/format_configuration.rs +++ b/papergrid/tests/grid/format_configuration.rs @@ -787,7 +787,9 @@ fn formatting_test() { .config(|cfg| { cfg.set_alignment_horizontal(Entity::Global, test.0); cfg.set_alignment_vertical(Entity::Global, test.1); - cfg.set_formatting(Entity::Global, test.2); + cfg.set_line_alignment(Entity::Global, test.2.allow_lines_alignment); + cfg.set_trim_horizontal(Entity::Global, test.2.horizontal_trim); + cfg.set_trim_vertical(Entity::Global, test.2.vertical_trim); }) .clone() .build(); @@ -803,7 +805,11 @@ fn formatting_empty_test() { let formatting = Formatting::new(true, true, true); assert_eq!( grid(rows, cols) - .config(|cfg| cfg.set_formatting(Entity::Global, formatting)) + .config(|cfg| { + cfg.set_line_alignment(Entity::Global, formatting.allow_lines_alignment); + cfg.set_trim_horizontal(Entity::Global, formatting.horizontal_trim); + cfg.set_trim_vertical(Entity::Global, formatting.vertical_trim); + }) .build(), "" ); @@ -855,7 +861,7 @@ fn formatting_1x1_test() { assert_eq!( grid.clone() - .config(|cfg| cfg.set_formatting(Entity::Global, Formatting::new(false, false, true))) + .config(|cfg| cfg.set_line_alignment(Entity::Global, true)) .build(), static_table!( r#"+--------------------------------------------------+"# @@ -878,7 +884,8 @@ fn formatting_1x1_test() { assert_eq!( grid.clone() - .config(|cfg| cfg.set_formatting(Entity::Global, Formatting::new(true, false, true))) + .config(|cfg| cfg.set_line_alignment(Entity::Global, true)) + .config(|cfg| cfg.set_trim_horizontal(Entity::Global, true)) .build(), static_table!( r#"+--------------------------------------------------+"# @@ -900,7 +907,9 @@ fn formatting_1x1_test() { ); assert_eq!( - grid.config(|cfg| cfg.set_formatting(Entity::Global, Formatting::new(true, true, true))) + grid.config(|cfg| cfg.set_line_alignment(Entity::Global, true)) + .config(|cfg| cfg.set_trim_horizontal(Entity::Global, true)) + .config(|cfg| cfg.set_trim_vertical(Entity::Global, true)) .build(), static_table!( r#"+--------------------------------------------------+"# diff --git a/tabled/Cargo.toml b/tabled/Cargo.toml index 02bb347c..6c141095 100644 --- a/tabled/Cargo.toml +++ b/tabled/Cargo.toml @@ -317,7 +317,7 @@ ansi = ["papergrid/ansi", "ansi-str", "ansitok", "std"] macros = ["std"] [dependencies] -papergrid = { version = "0.13", default-features = false } +papergrid = { path = "../papergrid", default-features = false } tabled_derive = { version = "0.9", optional = true } ansi-str = { version = "0.8", optional = true } ansitok = { version = "0.2", optional = true } diff --git a/tabled/benches/lib_comp/README.md b/tabled/benches/lib_comp/README.md index 214d75a0..6d5414f8 100644 --- a/tabled/benches/lib_comp/README.md +++ b/tabled/benches/lib_comp/README.md @@ -5,6 +5,12 @@ We profile only actual table construction. **Be WARE** that it's being run against a specific (but general) use case. Some libraries **might** perform better in certain scenarios or certain use cases. +```bash +cargo bench +``` + +TODO: Add an option to peak a libs list at the CLI run. + ## Result | | cli_table | comfy_table | prettytable_rs | term_table | tabled | tabled_color | tabled_compact | tabled_iter | diff --git a/tabled/benches/lib_comp/benches/benchmark.rs b/tabled/benches/lib_comp/benches/benchmark.rs index 5f0cc918..4e694d39 100644 --- a/tabled/benches/lib_comp/benches/benchmark.rs +++ b/tabled/benches/lib_comp/benches/benchmark.rs @@ -30,10 +30,12 @@ macro_rules! create_bench { bench_lib!( $name, $table, - { "tabled", lib_comp::tabled_current::build }, + { "current", lib_comp::tabled_current::build }, + { "current_color", lib_comp::tabled_color::build }, + { "current_iter", lib_comp::tabled_current_iter::build }, + { "current_compact", lib_comp::tabled_current_compact::build }, + { "tabled", lib_comp::tabled::build }, { "tabled_color", lib_comp::tabled_color_current::build }, - { "tabled_iter", lib_comp::tabled_current_iter::build }, - { "tabled_compact", lib_comp::tabled_current_compact::build }, { "cli_table", lib_comp::cli_table::build }, { "comfy_table", lib_comp::comfy_table::build }, { "term_table", lib_comp::term_table::build }, @@ -42,43 +44,33 @@ macro_rules! create_bench { }; } -create_bench!(test_empty_table, |size| build_cost_table(size, "", "")); - -create_bench!(test_const_table, |size| build_cost_table( - size, - "Hello World", - "Hi!" -)); - -create_bench!(test_dynamic_table, build_dynamic_table); - -create_bench!(test_multiline_table, |size| build_cost_table( - size, - "H\ne\nl\nlo\nWo\nr\nld", - "Hello\n111\n111\ni\n!" -)); +create_bench!(test_empty_table, benching_empty_table); +create_bench!(test_small_table, benching_small_table); +create_bench!(test_general_table, benching_general_table); +create_bench!(test_small_multiline_table, benching_small_multiline_table); criterion_group!( benches, test_empty_table, - test_const_table, - test_dynamic_table, - test_multiline_table, + test_small_table, + test_general_table, + test_small_multiline_table, ); criterion_main!(benches); -fn build_cost_table(size: usize, header: H, record: R) -> (Vec, Vec>) -where - H: Into, - R: Into, -{ - ( - vec![header.into(); size], - vec![vec![record.into(); size]; size], - ) +fn benching_empty_table(size: usize) -> (Vec, Vec>) { + build_cost_table(size, "", "") +} + +fn benching_small_table(size: usize) -> (Vec, Vec>) { + build_cost_table(size, "Hello World", "Hi!") } -fn build_dynamic_table(size: usize) -> (Vec, Vec>) { +fn benching_small_multiline_table(size: usize) -> (Vec, Vec>) { + build_cost_table(size, "H\ne\nl\nlo\nWo\nr\nld", "Hello\n111\n111\ni\n!") +} + +fn benching_general_table(size: usize) -> (Vec, Vec>) { let mut data = Vec::with_capacity(size); for i in 0..size { let mut row = build_row(size, |i| format!("{i}")); @@ -105,3 +97,14 @@ fn build_row(size: usize, f: impl Fn(usize) -> String) -> Vec { row } + +fn build_cost_table(size: usize, header: H, record: R) -> (Vec, Vec>) +where + H: Into, + R: Into, +{ + ( + vec![header.into(); size], + vec![vec![record.into(); size]; size], + ) +} diff --git a/tabled/benches/lib_comp/crates/tabled/Cargo.toml b/tabled/benches/lib_comp/crates/tabled/Cargo.toml index 1da1f8fd..7f8e8b9a 100644 --- a/tabled/benches/lib_comp/crates/tabled/Cargo.toml +++ b/tabled/benches/lib_comp/crates/tabled/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tabled = { version = "0.10.0", default-features = false } +tabled = { version = "0.17.0", default-features = false } diff --git a/tabled/benches/lib_comp/crates/tabled_color/Cargo.toml b/tabled/benches/lib_comp/crates/tabled_color/Cargo.toml index 8788577a..0125a459 100644 --- a/tabled/benches/lib_comp/crates/tabled_color/Cargo.toml +++ b/tabled/benches/lib_comp/crates/tabled_color/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tabled = { version = "0.10.0", default-features = false, features = ["ansi"] } +tabled = { version = "0.17.0", default-features = false, features = ["ansi"] } diff --git a/tabled/benches/lib_comp/src/lib.rs b/tabled/benches/lib_comp/src/lib.rs index 7a47b915..9c18a075 100644 --- a/tabled/benches/lib_comp/src/lib.rs +++ b/tabled/benches/lib_comp/src/lib.rs @@ -3,11 +3,14 @@ pub mod tabled { #[inline] pub fn build(columns: Vec, data: Vec>) -> String { - let mut b = Builder::from(data); - b.set_columns(columns); - let table = b.build(); + let mut b = Builder::with_capacity(data.len() + 1, columns.len()); + b.push_record(columns); - table.to_string() + for row in data { + b.push_record(row); + } + + b.build().to_string() } } @@ -16,11 +19,14 @@ pub mod tabled_color { #[inline] pub fn build(columns: Vec, data: Vec>) -> String { - let mut b = Builder::from(data); - b.set_columns(columns); - let table = b.build(); + let mut b = Builder::with_capacity(data.len() + 1, columns.len()); + b.push_record(columns); - table.to_string() + for row in data { + b.push_record(row); + } + + b.build().to_string() } } diff --git a/tabled/src/grid/config/colored_config.rs b/tabled/src/grid/config/colored_config.rs index 09640c74..93ad7901 100644 --- a/tabled/src/grid/config/colored_config.rs +++ b/tabled/src/grid/config/colored_config.rs @@ -106,14 +106,14 @@ impl ColorMap { impl crate::grid::colors::Colors for ColorMap { type Color = ANSIBuf; - fn get_color(&self, (row, col): (usize, usize)) -> Option<&Self::Color> { - self.0.as_ref().map(|map| map.get(Entity::Cell(row, col))) + fn get_color(&self, pos: (usize, usize)) -> Option<&Self::Color> { + self.0.as_ref().map(|map| map.get(pos)) } fn is_empty(&self) -> bool { self.0 .as_ref() - .map(|cfg| cfg.is_empty() && cfg.get(Entity::Global).is_empty()) + .map(|cfg| cfg.is_empty() && cfg.as_ref().is_empty()) .unwrap_or(true) } } diff --git a/tabled/src/grid/config/compact_multiline_config.rs b/tabled/src/grid/config/compact_multiline_config.rs index 623a50a1..42110090 100644 --- a/tabled/src/grid/config/compact_multiline_config.rs +++ b/tabled/src/grid/config/compact_multiline_config.rs @@ -157,7 +157,9 @@ impl From for crate::grid::config::SpannedConfig { let mut cfg = SpannedConfig::from(compact.config); cfg.set_alignment_vertical(Global, compact.alignment_vertical); - cfg.set_formatting(Global, compact.formatting); + cfg.set_line_alignment(Global, compact.formatting.allow_lines_alignment); + cfg.set_trim_horizontal(Global, compact.formatting.horizontal_trim); + cfg.set_trim_vertical(Global, compact.formatting.vertical_trim); cfg } diff --git a/tabled/src/grid/dimension/peekable_dimension.rs b/tabled/src/grid/dimension/peekable_dimension.rs index ec63349d..a60b5cfa 100644 --- a/tabled/src/grid/dimension/peekable_dimension.rs +++ b/tabled/src/grid/dimension/peekable_dimension.rs @@ -83,7 +83,7 @@ mod estimation { let height = cell.count_lines(); let width = cell.width(); - let pad = cfg.get_padding(pos.into()); + let pad = cfg.get_padding(pos); let width = width + pad.left.size + pad.right.size; let height = height + pad.top.size + pad.bottom.size; diff --git a/tabled/src/settings/formatting/alignment_strategy.rs b/tabled/src/settings/formatting/alignment_strategy.rs index 32b23d20..f75290d5 100644 --- a/tabled/src/settings/formatting/alignment_strategy.rs +++ b/tabled/src/settings/formatting/alignment_strategy.rs @@ -143,13 +143,12 @@ pub enum AlignmentStrategy { impl CellOption for AlignmentStrategy { fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) { - let mut formatting = *cfg.get_formatting(entity); - match &self { - AlignmentStrategy::PerCell => formatting.allow_lines_alignment = false, - AlignmentStrategy::PerLine => formatting.allow_lines_alignment = true, - } + let on = match &self { + AlignmentStrategy::PerCell => false, + AlignmentStrategy::PerLine => true, + }; - cfg.set_formatting(entity, formatting); + cfg.set_line_alignment(entity, on); } } diff --git a/tabled/src/settings/formatting/trim_strategy.rs b/tabled/src/settings/formatting/trim_strategy.rs index cd7cf4fd..9ec44d3c 100644 --- a/tabled/src/settings/formatting/trim_strategy.rs +++ b/tabled/src/settings/formatting/trim_strategy.rs @@ -87,27 +87,22 @@ pub enum TrimStrategy { impl CellOption for TrimStrategy { fn change(self, _: &mut R, cfg: &mut ColoredConfig, entity: Entity) { - let mut formatting = *cfg.get_formatting(entity); - - // todo: could be changed to be a struct an enum like consts in `impl` block. match self { TrimStrategy::Vertical => { - formatting.vertical_trim = true; + cfg.set_trim_vertical(entity, true); } TrimStrategy::Horizontal => { - formatting.horizontal_trim = true; + cfg.set_trim_horizontal(entity, true); } TrimStrategy::Both => { - formatting.vertical_trim = true; - formatting.horizontal_trim = true; + cfg.set_trim_horizontal(entity, true); + cfg.set_trim_vertical(entity, true); } TrimStrategy::None => { - formatting.vertical_trim = false; - formatting.horizontal_trim = false; + cfg.set_trim_horizontal(entity, false); + cfg.set_trim_vertical(entity, false); } } - - cfg.set_formatting(entity, formatting); } } diff --git a/tabled/src/settings/padding_expand/mod.rs b/tabled/src/settings/padding_expand/mod.rs index 8d1f2472..7fb65e0f 100644 --- a/tabled/src/settings/padding_expand/mod.rs +++ b/tabled/src/settings/padding_expand/mod.rs @@ -109,11 +109,10 @@ where let count_rows = records.count_rows(); let count_cols = records.count_columns(); - for (row, col) in entity.iter(count_rows, count_cols) { - let pos = Entity::Cell(row, col); - + for pos in entity.iter(count_rows, count_cols) { + let col = pos.1; let column_width = widths[col]; - let width = records.get_width((row, col)); + let width = records.get_width(pos); if width < column_width { let alignment = *cfg.get_alignment_horizontal(pos); @@ -125,7 +124,7 @@ where pad.left.size = left; pad.right.size = right; - cfg.set_padding(pos, pad); + cfg.set_padding(Entity::from(pos), pad); } } } @@ -141,11 +140,10 @@ where let count_rows = records.count_rows(); let count_cols = records.count_columns(); - for (row, col) in entity.iter(count_rows, count_cols) { - let pos = Entity::Cell(row, col); - + for pos in entity.iter(count_rows, count_cols) { + let row = pos.0; let row_height = heights[row]; - let cell_height = records.count_lines((row, col)); + let cell_height = records.count_lines(pos); if cell_height < row_height { let alignment = *cfg.get_alignment_vertical(pos); @@ -157,7 +155,7 @@ where pad.top.size = top; pad.bottom.size = bottom; - cfg.set_padding(pos, pad); + cfg.set_padding(Entity::from(pos), pad); } } } diff --git a/tabled/src/settings/width/truncate.rs b/tabled/src/settings/width/truncate.rs index fc89478c..61e9da45 100644 --- a/tabled/src/settings/width/truncate.rs +++ b/tabled/src/settings/width/truncate.rs @@ -456,7 +456,7 @@ fn get_decrease_cell_list( }; if width >= width_min { - let padding = cfg.get_padding((row, col).into()); + let padding = cfg.get_padding((row, col)); let width = width.saturating_sub(padding.left.size + padding.right.size); points.push(((row, col), width)); diff --git a/tabled/src/settings/width/wrap.rs b/tabled/src/settings/width/wrap.rs index d83672a8..36ea5eaf 100644 --- a/tabled/src/settings/width/wrap.rs +++ b/tabled/src/settings/width/wrap.rs @@ -871,7 +871,7 @@ fn get_decrease_cell_list( }; if width >= width_min { - let padding = cfg.get_padding((row, col).into()); + let padding = cfg.get_padding((row, col)); let width = width.saturating_sub(padding.left.size + padding.right.size); points.push(((row, col), width)); diff --git a/tabled/src/tables/table.rs b/tabled/src/tables/table.rs index 79b68dfa..6e3a0ae1 100644 --- a/tabled/src/tables/table.rs +++ b/tabled/src/tables/table.rs @@ -8,8 +8,8 @@ use crate::{ grid::{ colors::NoColors, config::{ - AlignmentHorizontal, ColorMap, ColoredConfig, CompactConfig, Entity, Formatting, - Indent, Sides, SpannedConfig, + AlignmentHorizontal, ColorMap, ColoredConfig, CompactConfig, Entity, Indent, Sides, + SpannedConfig, }, dimension::{CompleteDimensionVecRecords, Dimension, Estimate, PeekableDimension}, records::{ @@ -536,7 +536,9 @@ fn configure_grid() -> SpannedConfig { ), ); cfg.set_alignment_horizontal(Entity::Global, AlignmentHorizontal::Left); - cfg.set_formatting(Entity::Global, Formatting::new(false, false, false)); + cfg.set_line_alignment(Entity::Global, false); + cfg.set_trim_horizontal(Entity::Global, false); + cfg.set_trim_vertical(Entity::Global, false); cfg.set_borders(Style::ascii().get_borders()); cfg