| use super::core::display_width; |
| |
| #[derive(Debug)] |
| pub(crate) struct LineWrapper<'w> { |
| hard_width: usize, |
| line_width: usize, |
| carryover: Option<&'w str>, |
| } |
| |
| impl<'w> LineWrapper<'w> { |
| pub(crate) fn new(hard_width: usize) -> Self { |
| Self { |
| hard_width, |
| line_width: 0, |
| carryover: None, |
| } |
| } |
| |
| pub(crate) fn reset(&mut self) { |
| self.line_width = 0; |
| self.carryover = None; |
| } |
| |
| pub(crate) fn wrap(&mut self, mut words: Vec<&'w str>) -> Vec<&'w str> { |
| if self.carryover.is_none() { |
| if let Some(word) = words.first() { |
| if word.trim().is_empty() { |
| self.carryover = Some(*word); |
| } else { |
| self.carryover = Some(""); |
| } |
| } |
| } |
| |
| let mut i = 0; |
| while i < words.len() { |
| let word = &words[i]; |
| let trimmed = word.trim_end(); |
| let word_width = display_width(trimmed); |
| let trimmed_delta = word.len() - trimmed.len(); |
| if i != 0 && self.hard_width < self.line_width + word_width { |
| if 0 < i { |
| let last = i - 1; |
| let trimmed = words[last].trim_end(); |
| words[last] = trimmed; |
| } |
| |
| self.line_width = 0; |
| words.insert(i, "\n"); |
| i += 1; |
| if let Some(carryover) = self.carryover { |
| words.insert(i, carryover); |
| self.line_width += carryover.len(); |
| i += 1; |
| } |
| } |
| self.line_width += word_width + trimmed_delta; |
| |
| i += 1; |
| } |
| words |
| } |
| } |