Position cursor via buffer
This commit is contained in:
parent
bbaea3b5bf
commit
cc2f102141
3 changed files with 51 additions and 9 deletions
|
|
@ -51,6 +51,7 @@ impl Cell {
|
|||
pub struct Buffer {
|
||||
size: Size,
|
||||
data: Vec<Cell>,
|
||||
cursor: Option<Pos>,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
|
|
@ -59,6 +60,7 @@ impl Buffer {
|
|||
Self {
|
||||
size: Size::ZERO,
|
||||
data: vec![],
|
||||
cursor: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,19 +79,32 @@ impl Buffer {
|
|||
self.size
|
||||
}
|
||||
|
||||
/// Resize the buffer and reset its contents.
|
||||
///
|
||||
/// The buffer's contents are reset even if the buffer is already the
|
||||
/// correct size.
|
||||
pub fn resize(&mut self, size: Size) {
|
||||
let width: usize = size.width.into();
|
||||
let height: usize = size.height.into();
|
||||
let len = width * height;
|
||||
if size == self.size() {
|
||||
self.data.fill_with(Cell::empty);
|
||||
self.cursor = None;
|
||||
} else {
|
||||
let width: usize = size.width.into();
|
||||
let height: usize = size.height.into();
|
||||
let len = width * height;
|
||||
|
||||
self.size = size;
|
||||
self.data.clear();
|
||||
self.data.resize_with(len, Cell::empty);
|
||||
self.size = size;
|
||||
self.data.clear();
|
||||
self.data.resize_with(len, Cell::empty);
|
||||
self.cursor = None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset all cells of the buffer to be empty and have no styling.
|
||||
/// Reset the contents of the buffer.
|
||||
///
|
||||
/// `buf.reset()` is equivalent to `buf.resize(buf.size())`.
|
||||
pub fn reset(&mut self) {
|
||||
self.resize(self.size);
|
||||
self.data.fill_with(Cell::empty);
|
||||
self.cursor = None;
|
||||
}
|
||||
|
||||
pub fn write(&mut self, mut pos: Pos, content: &str, style: ContentStyle) {
|
||||
|
|
@ -118,6 +133,14 @@ impl Buffer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> Option<Pos> {
|
||||
self.cursor
|
||||
}
|
||||
|
||||
pub fn set_cursor(&mut self, pos: Option<Pos>) {
|
||||
self.cursor = pos;
|
||||
}
|
||||
|
||||
pub fn cells(&self) -> Cells<'_> {
|
||||
Cells {
|
||||
buffer: self,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::io::Write;
|
||||
use std::{io, mem};
|
||||
|
||||
use crossterm::cursor::MoveTo;
|
||||
use crossterm::cursor::{Hide, MoveTo, Show};
|
||||
use crossterm::style::{PrintStyledContent, StyledContent};
|
||||
use crossterm::terminal::{Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen};
|
||||
use crossterm::{ExecutableCommand, QueueableCommand};
|
||||
|
|
@ -65,9 +65,11 @@ impl Terminal {
|
|||
}
|
||||
|
||||
self.draw_differences()?;
|
||||
self.update_cursor()?;
|
||||
self.out.flush()?;
|
||||
|
||||
mem::swap(&mut self.prev_buffer, &mut self.curr_buffer);
|
||||
self.curr_buffer.reset();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -80,7 +82,23 @@ impl Terminal {
|
|||
.queue(MoveTo(x, y))?
|
||||
.queue(PrintStyledContent(content))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_cursor(&mut self) -> io::Result<()> {
|
||||
if let Some(pos) = self.curr_buffer.cursor() {
|
||||
let size = self.curr_buffer.size();
|
||||
let x_in_bounds = 0 <= pos.x && pos.x < size.width as i32;
|
||||
let y_in_bounds = 0 <= pos.y && pos.y < size.height as i32;
|
||||
if x_in_bounds && y_in_bounds {
|
||||
self.out
|
||||
.queue(Show)?
|
||||
.queue(MoveTo(pos.x as u16, pos.y as u16))?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
self.out.queue(Hide)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue