@@ 10,17 10,26 @@ use std::io;
use super::{COLOR_TITLE_BG, COLOR_TITLE_FG};
use textwrap;
-
-pub fn span(line: &str, cols: u16) -> Vec<String> {
- let wrapped_str = textwrap::fill(line, cols as usize);
- let lines = wrapped_str
- .lines()
- .map(|line| { line.to_owned() })
- .collect::<Vec<_>>();
-
- lines
+struct Span {
+ lines: Vec<String>,
}
+impl Span {
+ pub fn new(buf: &str, cols: u16) -> Self {
+ let wrapped_str = textwrap::fill(buf, cols as usize);
+
+ let lines = wrapped_str
+ .lines()
+ .map(|line| { line.to_owned() })
+ .collect::<Vec<_>>();
+
+ Self { lines: lines }
+ }
+
+ pub fn line_iter(&self) -> impl Iterator<Item = &String> {
+ self.lines.iter().rev()
+ }
+}
/// The `Buffer` stores a list of lines which need to be displayed
/// in a fixed-width context. Lines can be added to the buffer and
/// then displayed at any arbitrary resolution later.
@@ 29,11 38,8 @@ pub struct Buffer {
rows: u16,
lines: Vec<String>,
-
- page_idx: usize,
- curr_page: Vec<String>,
- next_page: Vec<String>,
- offset_lines: usize,
+ viewport_spans: Vec<Span>,
+ current_line_ptr: usize,
needs_repaint: bool,
}
@@ 45,12 51,8 @@ impl Buffer {
rows: rows,
lines: vec![],
-
-
- curr_page: vec![],
- next_page: vec![],
- page_idx: 0,
- offset_lines: 0,
+ viewport_spans: vec![],
+ current_line_ptr: 0,
needs_repaint: true,
}
@@ 67,47 69,18 @@ impl Buffer {
self.needs_repaint = true;
}
- pub fn draw_page_n(&mut self, page_num: usize) -> Vec<String> {
- self.lines
- .iter()
- .rev()
- .flat_map(|line| { span(line, self.cols) })
- .skip(self.rows as usize * page_num)
- .take(self.rows as usize)
- .collect::<Vec<_>>()
- }
-
pub fn scroll_up(&mut self) {
- let offset_len = 3;
- let new_offset = cmp::min(self.next_page.len(), self.offset_lines + offset_len);
-
- if new_offset == self.rows as usize {
- self.page_idx += 1;
- self.offset_lines = 0;
- self.needs_repaint = true;
- } else if new_offset > self.rows as usize && self.next_page.len() > 0 {
- // go to next page
- self.page_idx += 1;
- self.offset_lines = 0;
- self.needs_repaint = true;
- } else if new_offset > self.offset_lines {
- self.offset_lines = new_offset;
+ if (self.current_line_ptr + 1) <= self.lines.len() {
+ self.current_line_ptr += 1;
self.needs_repaint = true;
}
}
pub fn scroll_down(&mut self) {
- let offset_len = std::cmp::min(3, self.offset_lines);
-
- if offset_len >= self.offset_lines && self.page_idx > 0 {
- self.page_idx -= 1;
- self.offset_lines = self.rows as usize - offset_len;
- self.needs_repaint = true;
- } else if offset_len > 0 {
- self.offset_lines -= offset_len;
+ if self.current_line_ptr > 0 {
+ self.current_line_ptr -= 1;
self.needs_repaint = true;
}
-
}
/// The caller *must* set the cursor to the row where this buffer should be rendered.
@@ 117,48 90,33 @@ impl Buffer {
if !self.needs_repaint { return Ok(()); }
self.needs_repaint = false;
- // draw the current neighboring pages
- self.curr_page = self.draw_page_n(self.page_idx);
- self.next_page = self.draw_page_n(self.page_idx + 1);
-
// move to bottom-most row.
stdout
.queue(cursor::MoveDown(self.rows - 1))?
.queue(cursor::MoveToColumn(0))?;
- let mut rows_drawn = self.rows;
-
- // draw (rows - offset) lines from front buffer
- for line in self.curr_page.iter().skip(self.offset_lines) {
- stdout
- .queue(Clear(ClearType::CurrentLine))?
- .queue(Print(line))?
- .queue(cursor::MoveUp(1))?
- .queue(cursor::MoveToColumn(0))?;
+ // resize the spans starting from current line
+ self.viewport_spans = self.lines
+ .iter()
+ .rev()
+ .skip(self.current_line_ptr)
+ .map(|line| Span::new(line, self.cols))
+ .collect::<Vec<_>>();
- rows_drawn -= 1;
- }
+ let viewport_lines = self.viewport_spans
+ .iter()
+ .flat_map(|span| span.line_iter())
+ .take(self.rows as usize);
- // draw remaining (offset) lines from back buffer
- for line in self.next_page.iter().take(self.offset_lines) {
+ for line in viewport_lines {
stdout
- .queue(Clear(ClearType::CurrentLine))?
- .queue(Print(line))?
- .queue(cursor::MoveUp(1))?
- .queue(cursor::MoveToColumn(0))?;
-
- rows_drawn -= 1;
+ .queue(Clear(ClearType::CurrentLine))?
+ .queue(Print(line))?
+ .queue(cursor::MoveUp(1))?
+ .queue(cursor::MoveToColumn(0))?;
}
- // clear rest of buffer ...
- while rows_drawn > 0 {
- stdout
- .queue(Clear(ClearType::CurrentLine))?
- .queue(cursor::MoveUp(1))?
- .queue(cursor::MoveToColumn(0))?;
- rows_drawn -= 1;
- }
// while rows_left > 0 {
// // grab the next buffer line