diff --git a/src/widget.rs b/src/widget.rs index dd2bf0f..4e21cf6 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,5 +1,6 @@ use crate::textarea::TextArea; use crate::util::num_digits; +use std::cmp; use std::sync::atomic::{AtomicU32, Ordering}; use tui::buffer::Buffer; use tui::layout::Rect; @@ -42,6 +43,18 @@ impl<'a> Renderer<'a> { pub fn new(textarea: &'a TextArea<'a>) -> Self { Self(textarea) } + + #[inline] + fn text(&self, top_row: usize, height: usize) -> Text<'a> { + let lines_len = self.0.lines().len(); + let lnum_len = num_digits(lines_len); + let bottom_row = cmp::min(top_row + height, lines_len); + let mut lines = Vec::with_capacity(bottom_row - top_row); + for (i, line) in self.0.lines()[top_row..bottom_row].iter().enumerate() { + lines.push(self.0.line_spans(line.as_str(), top_row + i, lnum_len)); + } + Text::from(lines) + } } impl<'a> Widget for Renderer<'a> { @@ -64,31 +77,20 @@ impl<'a> Widget for Renderer<'a> { let cursor = self.0.cursor(); let (top_row, top_col) = self.0.scroll_top.load(); - let row = next_scroll_top(top_row, cursor.0 as u16, inner_area.height); - let col = next_scroll_top(top_col, cursor.1 as u16, inner_area.width); + let top_row = next_scroll_top(top_row, cursor.0 as u16, inner_area.height); + let top_col = next_scroll_top(top_col, cursor.1 as u16, inner_area.width); - let lnum_len = num_digits(self.0.lines().len()); - let lines: Vec<_> = self - .0 - .lines() - .iter() - .map(String::as_str) - .enumerate() - .skip(row as usize) - .take(inner_area.height as usize) - .map(|(row, line)| self.0.line_spans(line, row, lnum_len)) - .collect(); - - let mut inner = Paragraph::new(Text::from(lines)).style(self.0.style()); + let text = self.text(top_row as usize, inner_area.height as usize); + let mut inner = Paragraph::new(text).style(self.0.style()); if let Some(b) = self.0.block() { inner = inner.block(b.clone()); } - if col != 0 { - inner = inner.scroll((0, col)); + if top_col != 0 { + inner = inner.scroll((0, top_col)); } // Store scroll top position for rendering on the next tick - self.0.scroll_top.store(row, col); + self.0.scroll_top.store(top_row, top_col); inner.render(area, buf); }