use std::io::{self, Write}; #[derive(Debug, Clone, Copy)] pub enum Direction { Up, Down, Left, Right, } pub fn fmove_cursor(direction: Direction, n: usize, stdout: &mut dyn Write) -> std::io::Result<()> { if n == 0 { return Ok(()); } let code = match direction { Direction::Up => 'A', Direction::Down => 'B', Direction::Right => 'C', Direction::Left => 'D', }; write!(stdout, "\x1b[{n}{code}") } pub fn move_cursor(direction: Direction, n: usize) { fmove_cursor(direction, n, &mut std::io::stdout()).unwrap() } pub fn save() { std::io::stdout().lock().write_all(b"\x1b[s").unwrap(); } pub fn restore() { std::io::stdout().lock().write_all(b"\x1b[u").unwrap(); } /// Represents a cursor position #[derive(Debug, Clone, Copy)] pub struct CursorPos { pub row: usize, pub col: usize, } impl Default for CursorPos { fn default() -> Self { Self { row: 1, col: 1 } } } impl CursorPos { pub fn f_go_to(&self, stdout: &mut dyn Write) -> std::io::Result<()> { write!(stdout, "\x1b[{};{}H", self.row, self.col) } pub fn go_to(&self) { let mut stdout = io::stdout().lock(); self.f_go_to(&mut stdout).unwrap(); stdout.flush().unwrap(); } }