libtableformat/table/
row.rs1use super::border::Border;
2use super::cell::Cell;
3use crate::content::{CellWidth};
4
5pub struct CellIterator<'a> {
6 cells: &'a Vec<Cell>,
7 current_cell_ix: usize
8}
9
10impl<'a> Iterator for CellIterator<'a> {
11 type Item = &'a Cell;
12
13 fn next(&mut self) -> Option<&'a Cell> {
14 if self.current_cell_ix < self.cells.len() {
15 let cell: &Cell = &self.cells[self.current_cell_ix];
16 self.current_cell_ix += 1;
17 Some(cell)
18 } else {
19 None
20 }
21 }
22}
23
24#[allow(unused_macros)]
25#[macro_export]
26macro_rules! row {
27 ( $($style:expr => $content:expr),* ) => {
28 {
29 let mut r: Row = Row::new();
30 $( r.add_cell(crate::cell!($style, $content)); )*
31 r
32 }
33 };
34 ( $style:expr, $($content:expr),* ) => {
35 {
36 let mut r: Row = Row::new();
37 $( r.add_cell(crate::cell!($style, $content)); )*
38 r
39 }
40 };
41}
42
43#[derive(Debug)]
45pub struct Row {
46 cells: Vec<Cell>
47}
48
49impl Default for Row {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Row {
56 #[must_use]
57 pub fn new() -> Row {
58 Row {
59 cells: Vec::new()
60 }
61 }
62
63 #[must_use]
64 pub fn from(
65 cells: Vec<Cell>
66 ) -> Row {
67 Row { cells }
68 }
69
70 pub fn add_cell(&mut self, cell: Cell) {
71 self.cells.push(cell);
72 }
73
74 #[must_use]
75 pub fn iter(
76 self: &Row,
77 ) -> CellIterator {
78 CellIterator {
79 cells: &self.cells,
80 current_cell_ix: 0
81 }
82 }
83
84 #[must_use]
85 pub fn len(self: &Row) -> usize {
86 self.cells.len()
87 }
88
89 #[must_use]
90 pub fn is_empty(self: &Row) -> bool {
91 self.len() == 0
92 }
93
94 #[must_use]
102 #[allow(clippy::option_if_let_else)]
103 pub fn format(
104 self: &Row,
105 border: &Border,
106 column_breaks: &[CellWidth]
107 ) -> String {
108 let mut result: String = String::from("");
109
110 let row_height = self.measure_height(column_breaks);
111
112 let mut content_iterators = Vec::new();
114 for (cell_ix, cell) in self.cells.iter().enumerate() {
115 let column_break = &column_breaks[cell_ix];
116 content_iterators.push(cell.get_iterator(&column_break));
117 }
118
119 let content_break = CellWidth::default();
121 for _line_ix in 0..row_height {
122 result.push_str(&border.format_left());
124 for cell_ix in 0..self.cells.len() {
126 let cell = &self.cells[cell_ix];
127 let column_break: &CellWidth =
128 if cell_ix < column_breaks.len() {
129 &column_breaks[cell_ix]
130 } else {
131 &content_break
132 };
133 result.push_str(
134 &if let Some(content) = content_iterators[cell_ix].next() {
135 content.to_string()
136 } else {
137 let cell_width = cell.measure_width(column_break);
139 (0..cell_width)
140 .map(|_| " ")
141 .collect::<String>()
142 }
143 );
144 if cell_ix < column_breaks.len() - 1 {
146 result.push_str(&border.format_vertical_split());
147 }
148 }
149 result.push_str(&border.format_right());
151 result.push('\n');
152 }
153
154 result
155 }
156
157 #[must_use]
164 pub fn measure_height(
165 self: &Row,
166 column_breaks: &[CellWidth],
167 ) -> usize {
168 let mut tallest_height = 0;
169
170 let column_break_ix = 0;
172 let content_break = CellWidth::Content;
173 for cell in &self.cells {
174 let column_break: &CellWidth =
176 if column_break_ix < column_breaks.len() {
177 &column_breaks[column_break_ix]
178 } else {
179 &content_break
181 };
182 let cell_height = cell.measure_height(column_break);
183 if cell_height > tallest_height {
184 tallest_height = cell_height;
185 }
186 }
187
188 tallest_height
189 }
190}
191
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn test_row_macro_style_per_cell() {
199 assert_eq!(
200 format!("{:?}", row!("{c^}" => "Head 1", "{G-r>}" => "Head 2")),
201 format!("{:?}", Row::from(
202 vec!(
203 crate::cell!("{c^}", "Head 1"),
204 crate::cell!("{G-r>}", "Head 2")
205 )
206 ))
207 );
208 }
209
210 #[test]
211 fn test_row_macro_common_style() {
212 assert_eq!(
213 format!("{:?}", row!("{c^}", "Text 1", "Text 2", "Text 3")),
214 format!("{:?}", Row::from(
215 vec!(
216 crate::cell!("{c^}", "Text 1"),
217 crate::cell!("{c^}", "Text 2"),
218 crate::cell!("{c^}", "Text 3")
219 )
220 ))
221 );
222 }
223}