diff --git a/src/lib.rs b/src/lib.rs index a96384b..f51ac7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,6 +114,18 @@ impl Multiview { tile.scroll_up(); } + /// Scrolls down to the bottom of the current selected tile. + pub fn scroll_full_down(&mut self) { + let tile = self.tile_mut(self.selected); + tile.scroll_full_down(); + } + + /// Scrolls up to the top the current selected tile. + pub fn scroll_full_up(&mut self) { + let tile = self.tile_mut(self.selected); + tile.scroll_full_up(); + } + /// Push a string into a tile's stdout. pub fn push_stdout(&mut self, (i, j): (u16, u16), content: String) { let tile = self.tile_mut((i, j)); @@ -149,6 +161,12 @@ pub enum Msg { /// Scroll down one line. ScrollDown, + /// Scroll to the top of the log. + ScrollFullUp, + + /// Scroll to the bottom of the log. + ScrollFullDown, + /// The program was asked to exit. Exit, } @@ -217,6 +235,8 @@ pub fn main() -> io::Result<()> { Event::Key(Key::Char('q')) => sender.send(Msg::Exit).unwrap(), Event::Key(Key::Down) => sender.send(Msg::ScrollDown).unwrap(), Event::Key(Key::Up) => sender.send(Msg::ScrollUp).unwrap(), + Event::Key(Key::End) => sender.send(Msg::ScrollFullDown).unwrap(), + Event::Key(Key::Home) => sender.send(Msg::ScrollFullUp).unwrap(), Event::Mouse(MouseEvent::Press(p, x, y)) => match p { MouseButton::WheelUp => sender.send(Msg::ScrollUp).unwrap(), MouseButton::WheelDown => sender.send(Msg::ScrollDown).unwrap(), @@ -236,6 +256,8 @@ pub fn main() -> io::Result<()> { Ok(Msg::Click(x, y)) => multiview.select_tile((x, y), term_size), Ok(Msg::ScrollDown) => multiview.scroll_down(), Ok(Msg::ScrollUp) => multiview.scroll_up(), + Ok(Msg::ScrollFullDown) => multiview.scroll_full_down(), + Ok(Msg::ScrollFullUp) => multiview.scroll_full_up(), Ok(Msg::Exit) => break, Err(_) => (), } diff --git a/src/tile.rs b/src/tile.rs index 91f174e..5a1cfa4 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -91,7 +91,6 @@ impl TileBuilder { inner_size: (w - 4, h - 5), sender: self.sender?, stdout: String::new(), - cursor: None, len: 0, scroll: 0, number_lines: 1, @@ -112,11 +111,6 @@ pub struct Tile { /// We put both stdout and stderr here to avoid dealing with order between stdout and stderr. pub stdout: String, - /// The cursor where stdout should write. - /// - /// If None, stdout should push at the end of the string. - pub cursor: Option, - /// The number of chars in stdout. pub len: usize, @@ -248,106 +242,27 @@ impl Tile { /// Push content into the stdout of the tile. pub fn push_stdout(&mut self, content: String) { - let mut clear_line_counter = 0; - for c in content.chars() { - // Check if we're running into \x1b[K - clear_line_counter = match (c, clear_line_counter) { - ('\x1b', _) => { - self.counting = false; - 1 - } - ('[', 1) => 2, - ('K', 2) => 3, - _ => 0, - }; - - if let (3, Some(cursor)) = (clear_line_counter, self.cursor) { - // Find the size of the string until the next '\n' or end - let mut counter = 0; - loop { - counter += 1; - - // TODO fix utf8 - if self.stdout.len() <= counter + cursor - || &self.stdout[cursor + counter..cursor + counter + 1] == "\n" - { - break; - } - } - - self.stdout - .replace_range((cursor - 2)..(cursor + counter), ""); - self.len -= 2 + counter; - self.cursor = None; - self.counting = true; - continue; + if c == '\x1b' { + self.counting = false; } - if c == '\r' { - // Set cursor at the right place - let mut index = self.len; - let mut reverse = self.stdout.chars().rev(); + if c == '\n' { + self.stdout.push(c); + self.len += 1; self.column_number = 0; - - loop { - match reverse.next() { - Some('\n') | None => break, - _ => index -= 1, + self.number_lines += 1; + } else { + // TODO fix utf8 + self.stdout.push(c); + if self.counting { + self.column_number += 1; + if self.column_number == self.inner_size.0 + 1 { + self.column_number = 0; + self.number_lines += 1; } } - - self.cursor = Some(index); - } else { - let new_cursor = match self.cursor { - Some(index) => { - if c == '\n' { - self.stdout.push(c); - self.len += 1; - self.column_number = 0; - self.number_lines += 1; - None - } else { - // TODO fix utf8 - if index >= self.stdout.len() { - self.stdout.push(c); - if self.counting { - self.column_number += 1; - if self.column_number == self.inner_size.0 + 1 { - self.column_number = 0; - self.number_lines += 1; - } - } - self.len += 1; - None - } else { - self.stdout.replace_range(index..index + 1, &c.to_string()); - Some(index + 1) - } - } - } - - None => { - self.stdout.push(c); - - if c == '\n' { - self.column_number = 0; - self.number_lines += 1; - } else { - if self.counting { - self.column_number += 1; - if self.column_number == self.inner_size.0 + 1 { - self.column_number = 0; - self.number_lines += 1; - } - } - } - self.len += 1; - None - } - }; - - self.cursor = new_cursor; + self.len += 1; } if c == 'm' { @@ -461,6 +376,16 @@ impl Tile { } } + '\r' => { + current_char_index = 0; + if line_index >= scroll && line_index <= h + scroll { + buffer.push(format!( + "{}", + cursor::Goto(x, y + line_index as u16 - scroll) + )); + } + } + _ => { if line_index >= scroll && line_index <= h + scroll { if counting { @@ -518,4 +443,17 @@ impl Tile { self.scroll += 1; } } + + /// Scrolls up one line. + pub fn scroll_full_up(&mut self) { + self.scroll = 0; + } + + /// Scrolls down one line. + pub fn scroll_full_down(&mut self) { + self.scroll = self.number_lines - self.inner_size.1 as isize - 1; + if self.scroll < 0 { + self.scroll = 0; + } + } }