summaryrefslogtreecommitdiffstats
path: root/vendor/tabled/src/settings/span
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tabled/src/settings/span')
-rw-r--r--vendor/tabled/src/settings/span/column.rs125
-rw-r--r--vendor/tabled/src/settings/span/mod.rs68
-rw-r--r--vendor/tabled/src/settings/span/row.rs126
3 files changed, 319 insertions, 0 deletions
diff --git a/vendor/tabled/src/settings/span/column.rs b/vendor/tabled/src/settings/span/column.rs
new file mode 100644
index 000000000..50af64c23
--- /dev/null
+++ b/vendor/tabled/src/settings/span/column.rs
@@ -0,0 +1,125 @@
+use crate::{
+ grid::{
+ config::{ColoredConfig, Entity, Position, SpannedConfig},
+ records::{ExactRecords, Records},
+ },
+ settings::CellOption,
+};
+
+/// Columns (Vertical) span.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ColumnSpan {
+ size: usize,
+}
+
+impl ColumnSpan {
+ /// Creates a new column (vertical) span.
+ pub fn new(size: usize) -> Self {
+ Self { size }
+ }
+
+ /// Creates a new column (vertical) span with a maximux value possible.
+ pub fn max() -> Self {
+ Self::new(usize::MAX)
+ }
+}
+
+impl<R> CellOption<R, ColoredConfig> for ColumnSpan
+where
+ R: Records + ExactRecords,
+{
+ fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
+ let count_rows = records.count_rows();
+ let count_cols = records.count_columns();
+
+ set_col_spans(cfg, self.size, entity, (count_rows, count_cols));
+ remove_false_spans(cfg);
+ }
+}
+
+fn set_col_spans(cfg: &mut SpannedConfig, span: usize, entity: Entity, shape: (usize, usize)) {
+ for pos in entity.iter(shape.0, shape.1) {
+ if !is_valid_pos(pos, shape) {
+ continue;
+ }
+
+ let mut span = span;
+ if !is_column_span_valid(pos.1, span, shape.1) {
+ span = shape.1 - pos.1;
+ }
+
+ if span_has_intersections(cfg, pos, span) {
+ continue;
+ }
+
+ set_span_column(cfg, pos, span);
+ }
+}
+
+fn set_span_column(cfg: &mut SpannedConfig, pos: (usize, usize), span: usize) {
+ if span == 0 {
+ let (row, col) = pos;
+ if col == 0 {
+ return;
+ }
+
+ if let Some(closecol) = closest_visible(cfg, (row, col - 1)) {
+ let span = col + 1 - closecol;
+ cfg.set_column_span((row, closecol), span);
+ }
+ }
+
+ cfg.set_column_span(pos, span);
+}
+
+fn closest_visible(cfg: &SpannedConfig, mut pos: Position) -> Option<usize> {
+ loop {
+ if cfg.is_cell_visible(pos) {
+ return Some(pos.1);
+ }
+
+ if pos.1 == 0 {
+ return None;
+ }
+
+ pos.1 -= 1;
+ }
+}
+
+fn is_column_span_valid(col: usize, span: usize, count_cols: usize) -> bool {
+ span + col <= count_cols
+}
+
+fn is_valid_pos((row, col): Position, (count_rows, count_cols): (usize, usize)) -> bool {
+ row < count_rows && col < count_cols
+}
+
+fn span_has_intersections(cfg: &SpannedConfig, (row, col): Position, span: usize) -> bool {
+ for col in col..col + span {
+ if !cfg.is_cell_visible((row, col)) {
+ return true;
+ }
+ }
+
+ false
+}
+
+fn remove_false_spans(cfg: &mut SpannedConfig) {
+ for (pos, _) in cfg.get_column_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+
+ for (pos, _) in cfg.get_row_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+}
diff --git a/vendor/tabled/src/settings/span/mod.rs b/vendor/tabled/src/settings/span/mod.rs
new file mode 100644
index 000000000..1139a2b99
--- /dev/null
+++ b/vendor/tabled/src/settings/span/mod.rs
@@ -0,0 +1,68 @@
+//! This module contains a [`Span`] settings, it helps to
+//! make a cell take more space then it generally takes.
+//!
+//! # Example
+//!
+//! ```
+//! use tabled::{settings::{Span, Modify}, Table};
+//!
+//! let data = [[1, 2, 3], [4, 5, 6]];
+//!
+//! let table = Table::new(data)
+//! .with(Modify::new((2, 0)).with(Span::column(2)))
+//! .with(Modify::new((0, 1)).with(Span::column(2)))
+//! .to_string();
+//!
+//! assert_eq!(
+//! table,
+//! concat!(
+//! "+---+---+---+\n",
+//! "| 0 | 1 |\n",
+//! "+---+---+---+\n",
+//! "| 1 | 2 | 3 |\n",
+//! "+---+---+---+\n",
+//! "| 4 | 6 |\n",
+//! "+---+---+---+",
+//! )
+//! )
+//! ```
+
+mod column;
+mod row;
+
+pub use column::ColumnSpan;
+pub use row::RowSpan;
+
+/// Span represent a horizontal/column span setting for any cell on a [`Table`].
+///
+/// It will be ignored if:
+/// - cell position is out of scope
+/// - size is bigger then the total number of columns.
+/// - size is bigger then the total number of rows.
+///
+/// ```rust,no_run
+/// # use tabled::{Table, settings::{Style, Span, Modify, object::Columns}};
+/// # let data: Vec<&'static str> = Vec::new();
+/// let table = Table::new(&data)
+/// .with(Modify::new(Columns::single(0)).with(Span::column(2)));
+/// ```
+///
+/// [`Table`]: crate::Table
+#[derive(Debug)]
+pub struct Span;
+
+impl Span {
+ /// New constructs a horizontal/column [`Span`].
+ ///
+ /// If size is bigger then the total number of columns it will be ignored.
+ pub fn column(size: usize) -> ColumnSpan {
+ ColumnSpan::new(size)
+ }
+
+ /// New constructs a vertical/row [`Span`].
+ ///
+ /// If size is bigger then the total number of rows it will be ignored.
+ pub fn row(size: usize) -> RowSpan {
+ RowSpan::new(size)
+ }
+}
diff --git a/vendor/tabled/src/settings/span/row.rs b/vendor/tabled/src/settings/span/row.rs
new file mode 100644
index 000000000..68673f7a2
--- /dev/null
+++ b/vendor/tabled/src/settings/span/row.rs
@@ -0,0 +1,126 @@
+use crate::{
+ grid::{
+ config::{ColoredConfig, Entity, Position, SpannedConfig},
+ records::{ExactRecords, Records},
+ },
+ settings::CellOption,
+};
+
+/// Row (vertical) span.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct RowSpan {
+ size: usize,
+}
+
+impl RowSpan {
+ /// Creates a new row (vertical) span.
+ pub const fn new(size: usize) -> Self {
+ Self { size }
+ }
+
+ /// Creates a new row (vertical) span with a maximux value possible.
+ pub const fn max() -> Self {
+ Self::new(usize::MAX)
+ }
+}
+
+impl<R> CellOption<R, ColoredConfig> for RowSpan
+where
+ R: Records + ExactRecords,
+{
+ fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
+ let count_rows = records.count_rows();
+ let count_cols = records.count_columns();
+
+ set_row_spans(cfg, self.size, entity, (count_rows, count_cols));
+ remove_false_spans(cfg);
+ }
+}
+
+fn set_row_spans(cfg: &mut SpannedConfig, span: usize, entity: Entity, shape: (usize, usize)) {
+ for pos in entity.iter(shape.0, shape.1) {
+ if !is_valid_pos(pos, shape) {
+ continue;
+ }
+
+ let mut span = span;
+ if !is_row_span_valid(pos.0, span, shape.0) {
+ span = shape.0 - pos.0;
+ }
+
+ if span_has_intersections(cfg, pos, span) {
+ continue;
+ }
+
+ set_span_row(cfg, pos, span);
+ }
+}
+
+fn set_span_row(cfg: &mut SpannedConfig, pos: (usize, usize), span: usize) {
+ if span == 0 {
+ let (row, col) = pos;
+ if row == 0 {
+ return;
+ }
+
+ if let Some(closerow) = closest_visible_row(cfg, (row - 1, col)) {
+ let span = row + 1 - closerow;
+ cfg.set_row_span((closerow, col), span);
+ }
+ }
+
+ cfg.set_row_span(pos, span);
+}
+
+fn closest_visible_row(cfg: &SpannedConfig, mut pos: Position) -> Option<usize> {
+ loop {
+ if cfg.is_cell_visible(pos) {
+ return Some(pos.0);
+ }
+
+ if pos.0 == 0 {
+ // can happen if we have a above horizontal spanned cell
+ return None;
+ }
+
+ pos.0 -= 1;
+ }
+}
+
+fn is_row_span_valid(row: usize, span: usize, count_rows: usize) -> bool {
+ span + row <= count_rows
+}
+
+fn is_valid_pos((row, col): Position, (count_rows, count_cols): (usize, usize)) -> bool {
+ row < count_rows && col < count_cols
+}
+
+fn span_has_intersections(cfg: &SpannedConfig, (row, col): Position, span: usize) -> bool {
+ for row in row..row + span {
+ if !cfg.is_cell_visible((row, col)) {
+ return true;
+ }
+ }
+
+ false
+}
+
+fn remove_false_spans(cfg: &mut SpannedConfig) {
+ for (pos, _) in cfg.get_column_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+
+ for (pos, _) in cfg.get_row_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+}