Skip to content

Commit

Permalink
Merge pull request #473 from zhiburt/patch/refactorings-papergrid
Browse files Browse the repository at this point in the history
Improvements in papergrid
  • Loading branch information
zhiburt authored Jan 3, 2025
2 parents 74e280d + 4b466b8 commit 99cfa43
Show file tree
Hide file tree
Showing 24 changed files with 264 additions and 251 deletions.
7 changes: 3 additions & 4 deletions papergrid/src/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,16 @@ where
#[cfg(feature = "std")]
impl<C> Colors for crate::config::spanned::EntityMap<Option<C>>
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()
}
}

Expand Down
7 changes: 7 additions & 0 deletions papergrid/src/config/sides.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,10 @@ impl<T> Sides<T> {
)
}
}

impl<T> Sides<Option<T>> {
/// 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()
}
}
63 changes: 29 additions & 34 deletions papergrid/src/config/spanned/entity_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,29 @@ impl<T> EntityMap<T> {
}

/// 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`].
Expand Down Expand Up @@ -134,3 +123,9 @@ impl<T> From<EntityMap<T>> for HashMap<Entity, T> {
m
}
}

impl<T> AsRef<T> for EntityMap<T> {
fn as_ref(&self) -> &T {
&self.global
}
}
156 changes: 81 additions & 75 deletions papergrid/src/config/spanned/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ 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,
};
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<char>;

Expand All @@ -29,11 +30,14 @@ type VerticalLine = super::VerticalLine<char>;
/// grid: crate::Grid.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SpannedConfig {
margin: Sides<ColoredMarginIndent>,
padding: EntityMap<Sides<ColoredIndent>>,
margin: Sides<MarginIndent>,
padding: EntityMap<Sides<Indent>>,
padding_color: EntityMap<Sides<Option<ANSIBuf>>>,
alignment_h: EntityMap<AlignmentHorizontal>,
alignment_v: EntityMap<AlignmentVertical>,
formatting: EntityMap<Formatting>,
formatting_trim_h: EntityMap<bool>,
formatting_trim_v: EntityMap<bool>,
formatting_line_alignment: EntityMap<bool>,
span_columns: HashMap<Position, usize>,
span_rows: HashMap<Position, usize>,
borders: BordersConfig<char>,
Expand All @@ -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(),
Expand Down Expand Up @@ -413,76 +420,81 @@ impl SpannedConfig {

/// Set a padding to a given cells.
pub fn set_padding(&mut self, entity: Entity, padding: Sides<Indent>) {
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<Option<ANSIBuf>>) {
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<Indent> {
*self.padding.get(pos)
}

/// Get a padding for a given [Entity].
pub fn get_padding(&self, entity: Entity) -> Sides<Indent> {
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<Option<ANSIBuf>> {
self.padding_color.get(pos).clone()
}

/// Get a padding color for a given [Entity].
pub fn get_padding_color(&self, entity: Entity) -> Sides<Option<ANSIBuf>> {
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.
pub fn set_alignment_vertical(&mut self, entity: Entity, alignment: AlignmentVertical) {
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.
pub fn set_alignment_horizontal(&mut self, entity: Entity, alignment: AlignmentHorizontal) {
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`].
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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<ANSIBuf>,
}

/// A colorefull margin indent.
#[derive(Debug, Clone, PartialEq, Eq)]
struct ColoredMarginIndent {
struct MarginIndent {
/// An indent value.
indent: Indent,
/// An offset value.
Expand All @@ -915,7 +921,7 @@ struct ColoredMarginIndent {
color: Option<ANSIBuf>,
}

impl Default for ColoredMarginIndent {
impl Default for MarginIndent {
fn default() -> Self {
Self {
indent: Indent::default(),
Expand Down
Loading

0 comments on commit 99cfa43

Please sign in to comment.