| 1 | use super::core::display_width; |
| 2 | |
| 3 | #[derive (Debug)] |
| 4 | pub(crate) struct LineWrapper<'w> { |
| 5 | hard_width: usize, |
| 6 | line_width: usize, |
| 7 | carryover: Option<&'w str>, |
| 8 | } |
| 9 | |
| 10 | impl<'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 | |