Position cursor via buffer

This commit is contained in:
Joscha 2022-05-21 21:07:24 +02:00
parent bbaea3b5bf
commit cc2f102141
3 changed files with 51 additions and 9 deletions

View file

@ -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,

View file

@ -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(())
}
}