1use std::collections::HashSet;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum Alignment {
6 Left,
8 Center,
10 Right,
12}
13
14#[derive(Debug, Clone, PartialEq)]
16pub struct Cell {
17 pub content: String,
19 pub column_span: usize,
21 pub alignment: Alignment,
23 pub has_padding: bool,
25}
26
27impl Cell {
28 pub fn new(content: impl ToString) -> Self {
30 Cell {
31 content: content.to_string(),
32 column_span: 1,
33 alignment: Alignment::Left,
34 has_padding: true,
35 }
36 }
37
38 pub fn with_column_span(mut self, column_span: usize) -> Self {
40 self.column_span = column_span;
41 self
42 }
43
44 pub fn with_alignment(mut self, alignment: Alignment) -> Self {
46 self.alignment = alignment;
47 self
48 }
49
50 pub fn without_padding(mut self) -> Self {
52 self.has_padding = false;
53 self
54 }
55
56 pub(crate) fn width(&self) -> usize {
58 crate::visible_width(&self.content) + if self.has_padding { 2 } else { 0 }
59 }
60
61 pub(crate) fn wrapped_content(&self, max_width: usize) -> Vec<String> {
63 let hidden: HashSet<usize> = crate::ANSI_REGEX
64 .find_iter(&self.content)
65 .flat_map(|m| m.start()..m.end())
66 .collect();
67 let mut res: Vec<String> = Vec::new();
68 let mut buf = String::new();
69 let mut byte_index = 0;
70 for c in self.content.chars() {
71 if !hidden.contains(&byte_index)
72 && (crate::visible_width(&buf) >= max_width || c == '\n')
73 {
74 res.push(buf);
75 buf = String::new();
76 if c == '\n' {
77 byte_index += 1;
78 continue;
79 }
80 }
81 byte_index += c.len_utf8();
82 buf.push(c);
83 }
84 res.push(buf);
85
86 res
87 }
88}