tabled/settings/height/
cell_height_increase.rs

1use crate::{
2    grid::config::{ColoredConfig, Entity, Position},
3    grid::dimension::CompleteDimension,
4    grid::records::{ExactRecords, IntoRecords, PeekableRecords, Records, RecordsMut},
5    grid::util::string::count_lines,
6    settings::{measurement::Measurement, peaker::Peaker, CellOption, Height, TableOption},
7};
8
9use super::TableHeightIncrease;
10
11/// A modification for cell/table to increase its height.
12///
13/// If used for a [`Table`] [`PriorityNone`] is used.
14///
15/// [`PriorityNone`]: crate::settings::peaker::PriorityNone
16/// [`Table`]: crate::Table
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18pub struct CellHeightIncrease<W = usize> {
19    height: W,
20}
21
22impl<W> CellHeightIncrease<W> {
23    /// Creates a new object of the structure.
24    pub fn new(height: W) -> Self
25    where
26        W: Measurement<Height>,
27    {
28        Self { height }
29    }
30
31    /// The priority makes sense only for table, so the function
32    /// converts it to [`TableHeightIncrease`] with a given priority.
33    pub fn priority<P>(self, priority: P) -> TableHeightIncrease<W, P>
34    where
35        P: Peaker,
36        W: Measurement<Height>,
37    {
38        TableHeightIncrease::new(self.height).priority(priority)
39    }
40}
41
42impl<W, R> CellOption<R, ColoredConfig> for CellHeightIncrease<W>
43where
44    W: Measurement<Height>,
45    R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
46    for<'a> &'a R: Records,
47    for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
48{
49    fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
50        let height = self.height.measure(&*records, cfg);
51
52        let count_rows = records.count_rows();
53        let count_columns = records.count_columns();
54        let max_pos = Position::new(count_rows, count_columns);
55
56        for pos in entity.iter(count_rows, count_columns) {
57            if !max_pos.has_coverage(pos) {
58                continue;
59            }
60
61            let text = records.get_text(pos);
62
63            // TOOD: We have a Cell?
64            // I mean we could use Cell trait here
65
66            let cell_height = count_lines(text);
67            if cell_height >= height {
68                continue;
69            }
70
71            let content = add_lines(text, height - cell_height);
72            records.set(pos, content);
73        }
74    }
75}
76
77impl<R, W> TableOption<R, ColoredConfig, CompleteDimension> for CellHeightIncrease<W>
78where
79    W: Measurement<Height>,
80    R: Records + ExactRecords + PeekableRecords,
81    for<'a> &'a R: Records,
82    for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
83{
84    fn change(self, records: &mut R, cfg: &mut ColoredConfig, dims: &mut CompleteDimension) {
85        let height = self.height.measure(&*records, cfg);
86        TableHeightIncrease::new(height).change(records, cfg, dims)
87    }
88
89    fn hint_change(&self) -> Option<Entity> {
90        TableHeightIncrease::new(0).hint_change()
91    }
92}
93
94fn add_lines(s: &str, n: usize) -> String {
95    let mut text = String::with_capacity(s.len() + n);
96    text.push_str(s);
97    text.extend(std::iter::repeat_n('\n', n));
98
99    text
100}