1use crate::style::{Align, Style};
2use std::borrow::Cow;
3use textwrap::{core::display_width, wrap};
4
5#[derive(Debug, Default)]
6pub struct Wrapped<'a> {
7 cows: Vec<Cow<'a, str>>,
8
9 style: Style,
10}
11
12impl<'a> Wrapped<'a> {
13 pub fn new(cows: Vec<Cow<'a, str>>, style: Style) -> Self {
14 Self { cows, style }
15 }
16
17 pub fn get_style(&self) -> &Style {
18 &self.style
19 }
20
21 pub fn set_wrap_width(&mut self, width: usize) {
22 self.style.wrap_width = width;
23 }
24
25 pub fn get_wrap_width(&self) -> usize {
26 self.style.wrap_width
27 }
28
29 pub fn get_line(&self, line: usize) -> String {
30 let padding_str = String::from(self.style.padding_char);
31
32 if line < self.cows.len() {
33 let mut ret = " ".repeat(self.style.indent);
34 let real_width = display_width(self.cows[line].as_ref());
35 let padding_width = self.get_wrap_width() - real_width;
36
37 ret += self.cows[line].as_ref();
38 match self.style.align {
39 Align::Left => {
40 ret += &padding_str.repeat(padding_width);
41 }
42 Align::Right => {
43 ret = padding_str.repeat(padding_width) + &ret;
44 }
45 }
46 ret
47 } else {
48 format!(
49 "{}{}",
50 " ".repeat(self.style.indent),
51 padding_str.repeat(self.get_wrap_width())
52 )
53 }
54 }
55
56 pub fn len(&self) -> usize {
57 self.cows.len()
58 }
59
60 pub fn is_empty(&self) -> bool {
61 self.len() == 0
62 }
63}
64
65#[derive(Debug)]
66pub struct Wrapper<'a, 'b> {
67 data: &'a [Vec<Cow<'b, str>>],
68
69 output: Vec<Vec<Wrapped<'b>>>,
70}
71
72impl<'a, 'b> Wrapper<'a, 'b>
73where
74 'a: 'b,
75{
76 pub fn new(data: &'a [Vec<Cow<'b, str>>]) -> Self {
77 Self {
78 data,
79 output: vec![],
80 }
81 }
82
83 pub fn wrap(&mut self, max_width: usize) {
84 let data_len = self.data.iter().map(|v| v.len()).max().unwrap_or(0);
85 let mut default_style = vec![Style::default(); data_len];
86
87 for line in self.data.iter() {
88 for (style_mut, col) in default_style.iter_mut().zip(line.iter()) {
89 let width = display_width(col);
90
91 if style_mut.wrap_width < width {
92 style_mut.wrap_width = if max_width != 0 && width > max_width {
93 max_width
94 } else {
95 width
96 };
97 }
98 }
99 }
100
101 for line in self.data.iter() {
102 let mut wrapped = vec![];
103
104 for (col, style) in line.iter().zip(default_style.iter()) {
105 wrapped.push(Wrapped::new(wrap(col, style.wrap_width), style.clone()));
106 }
107
108 self.output.push(wrapped);
109 }
110 }
111
112 pub fn wrap_with(&mut self, styles: &[Style], max_width: usize) {
114 let mut styles = styles.to_owned();
115 let status: Vec<bool> = styles.iter().map(|v| v.wrap_width == 0).collect();
116
117 for (line, status) in self.data.iter().zip(status.iter()) {
118 if *status {
119 for (style_mut, col) in styles.iter_mut().zip(line.iter()) {
120 let width = display_width(col);
121
122 if style_mut.wrap_width < width {
123 style_mut.wrap_width = if max_width != 0 && width > max_width {
124 max_width
125 } else {
126 width
127 };
128 }
129 }
130 }
131 }
132
133 for line in self.data.iter() {
134 let mut wrapped = vec![];
135
136 for (col, style) in line.iter().zip(styles.iter()) {
137 wrapped.push(Wrapped::new(wrap(col, style.wrap_width), style.clone()));
138 }
139 self.output.push(wrapped);
140 }
141 }
142
143 pub fn get_output(&self) -> &Vec<Vec<Wrapped<'b>>> {
144 &self.output
145 }
146
147 pub fn len(&self) -> usize {
148 self.output.len()
149 }
150
151 pub fn is_empty(&self) -> bool {
152 self.len() == 0
153 }
154}