comfy_table/row.rs
1use std::slice::Iter;
2
3use crate::{
4 cell::{Cell, Cells},
5 utils::formatting::content_split::measure_text_width,
6};
7
8/// Each row contains [Cells](crate::Cell) and can be added to a [Table](crate::Table).
9#[derive(Clone, Debug, Default)]
10pub struct Row {
11 /// Index of the row.
12 /// This will be set as soon as the row is added to the table.
13 pub(crate) index: Option<usize>,
14 pub(crate) cells: Vec<Cell>,
15 pub(crate) max_height: Option<usize>,
16}
17
18impl Row {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 /// Add a cell to the row.
24 ///
25 /// **Attention:**
26 /// If a row has already been added to a table and you add more cells to it
27 /// than there're columns currently know to the [Table](crate::Table) struct,
28 /// these columns won't be known to the table unless you call
29 /// [crate::Table::discover_columns].
30 ///
31 /// ```rust
32 /// use comfy_table::{Cell, Row};
33 ///
34 /// let mut row = Row::new();
35 /// row.add_cell(Cell::new("One"));
36 /// ```
37 pub fn add_cell(&mut self, cell: Cell) -> &mut Self {
38 self.cells.push(cell);
39
40 self
41 }
42
43 /// Truncate content of cells which occupies more than X lines of space.
44 ///
45 /// ```
46 /// use comfy_table::{Cell, Row};
47 ///
48 /// let mut row = Row::new();
49 /// row.max_height(5);
50 /// ```
51 pub fn max_height(&mut self, lines: usize) -> &mut Self {
52 self.max_height = Some(lines);
53
54 self
55 }
56
57 /// Get the longest content width for all cells of this row
58 pub(crate) fn max_content_widths(&self) -> Vec<usize> {
59 // Iterate over all cells
60 self.cells
61 .iter()
62 .map(|cell| {
63 // Iterate over all content strings and return a vector of string widths.
64 // Each entry represents the longest string width for a cell.
65 cell.content
66 .iter()
67 .map(|string| measure_text_width(string))
68 .max()
69 .unwrap_or(0)
70 })
71 .collect()
72 }
73
74 /// Get the amount of cells on this row.
75 pub fn cell_count(&self) -> usize {
76 self.cells.len()
77 }
78
79 /// Returns an iterator over all cells of this row
80 pub fn cell_iter(&self) -> Iter<'_, Cell> {
81 self.cells.iter()
82 }
83}
84
85/// Create a Row from any `Into<Cells>`. \
86/// [Cells] is a simple wrapper around a `Vec<Cell>`.
87///
88/// Check the [From] implementations on [Cell] for more information.
89///
90/// ```rust
91/// use comfy_table::{Cell, Row};
92///
93/// let row = Row::from(vec!["One", "Two", "Three"]);
94/// let row = Row::from(vec![Cell::new("One"), Cell::new("Two"), Cell::new("Three")]);
95/// let row = Row::from(vec![1, 2, 3, 4]);
96/// ```
97impl<T: Into<Cells>> From<T> for Row {
98 fn from(cells: T) -> Self {
99 Self {
100 index: None,
101 cells: cells.into().0,
102 max_height: None,
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_correct_max_content_width() {
113 let row = Row::from(vec![
114 "",
115 "four",
116 "fivef",
117 "sixsix",
118 "11 but with\na newline",
119 ]);
120
121 let max_content_widths = row.max_content_widths();
122
123 assert_eq!(max_content_widths, vec![0, 4, 5, 6, 11]);
124 }
125
126 #[test]
127 fn test_some_functions() {
128 let cells = ["one", "two", "three"];
129 let mut row = Row::new();
130 for cell in cells.iter() {
131 row.add_cell(Cell::new(cell));
132 }
133 assert_eq!(row.cell_count(), cells.len());
134
135 let mut cell_content_iter = cells.iter();
136 for cell in row.cell_iter() {
137 assert_eq!(
138 cell.content(),
139 cell_content_iter.next().unwrap().to_string()
140 );
141 }
142 }
143}