1use super::core::display_width;
2
3#[derive(Debug)]
4pub(crate) struct LineWrapper<'w> {
5 hard_width: usize,
6 line_width: usize,
7 carryover: Option<&'w str>,
8}
9
10impl<'w> LineWrapper<'w> {
11 pub(crate) fn new(hard_width: usize) -> Self {
12 Self {
13 hard_width,
14 line_width: 0,
15 carryover: None,
16 }
17 }
18
19 pub(crate) fn reset(&mut self) {
20 self.line_width = 0;
21 self.carryover = None;
22 }
23
24 pub(crate) fn wrap(&mut self, mut words: Vec<&'w str>) -> Vec<&'w str> {
25 if self.carryover.is_none() {
26 if let Some(word) = words.first() {
27 if word.trim().is_empty() {
28 self.carryover = Some(*word);
29 } else {
30 self.carryover = Some("");
31 }
32 }
33 }
34
35 let mut i = 0;
36 while i < words.len() {
37 let word = &words[i];
38 let trimmed = word.trim_end();
39 let word_width = display_width(trimmed);
40 let trimmed_delta = word.len() - trimmed.len();
41 if i != 0 && self.hard_width < self.line_width + word_width {
42 if 0 < i {
43 let last = i - 1;
44 let trimmed = words[last].trim_end();
45 words[last] = trimmed;
46 }
47
48 self.line_width = 0;
49 words.insert(i, "\n");
50 i += 1;
51 if let Some(carryover) = self.carryover {
52 words.insert(i, carryover);
53 self.line_width += carryover.len();
54 i += 1;
55 }
56 }
57 self.line_width += word_width + trimmed_delta;
58
59 i += 1;
60 }
61 words
62 }
63}
64