diff --git a/src/backend/crossterm.rs b/src/backend/crossterm.rs index b3c79dd3..1f147a8a 100644 --- a/src/backend/crossterm.rs +++ b/src/backend/crossterm.rs @@ -69,6 +69,16 @@ impl Backend for CrosstermBackend { Ok(()) } + fn get_cursor(&mut self) -> io::Result<(u16, u16)> { + let cursor = crossterm::cursor(); + Ok(cursor.pos()) + } + + fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> { + let cursor = crossterm::cursor(); + cursor.goto(x, y).map_err(convert_error) + } + fn size(&self) -> io::Result { let terminal = crossterm::terminal(); let (width, height) = terminal.terminal_size(); diff --git a/src/backend/mod.rs b/src/backend/mod.rs index cc60c5f5..5abe0cb9 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -27,6 +27,8 @@ pub trait Backend { I: Iterator; fn hide_cursor(&mut self) -> Result<(), io::Error>; fn show_cursor(&mut self) -> Result<(), io::Error>; + fn get_cursor(&mut self) -> Result<(u16, u16), io::Error>; + fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error>; fn clear(&mut self) -> Result<(), io::Error>; fn size(&self) -> Result; fn flush(&mut self) -> Result<(), io::Error>; diff --git a/src/backend/rustbox.rs b/src/backend/rustbox.rs index 73c1772a..8bed14c4 100644 --- a/src/backend/rustbox.rs +++ b/src/backend/rustbox.rs @@ -51,6 +51,13 @@ impl Backend for RustboxBackend { fn show_cursor(&mut self) -> Result<(), io::Error> { Ok(()) } + fn get_cursor(&mut self) -> io::Result<(u16, u16)> { + Err(io::Error::from(io::ErrorKind::Other)) + } + fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> { + self.rustbox.set_cursor(x as isize, y as isize); + Ok(()) + } fn clear(&mut self) -> Result<(), io::Error> { self.rustbox.clear(); Ok(()) diff --git a/src/backend/termion.rs b/src/backend/termion.rs index 330a5dfc..f75b2c8b 100644 --- a/src/backend/termion.rs +++ b/src/backend/termion.rs @@ -59,6 +59,16 @@ where self.stdout.flush() } + /// Gets cursor position (0-based index) + fn get_cursor(&mut self) -> io::Result<(u16, u16)> { + termion::cursor::DetectCursorPos::cursor_pos(&mut self.stdout).map(|(x, y)| (x - 1, y - 1)) + } + + /// Sets cursor position (0-based index) + fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> { + write!(self.stdout, "{}", termion::cursor::Goto(x + 1, y + 1)) + } + fn draw<'a, I>(&mut self, content: I) -> io::Result<()> where I: Iterator, diff --git a/src/backend/test.rs b/src/backend/test.rs index 616fe3ad..10573aa2 100644 --- a/src/backend/test.rs +++ b/src/backend/test.rs @@ -9,6 +9,7 @@ pub struct TestBackend { buffer: Buffer, height: u16, cursor: bool, + pos: (u16, u16), } impl TestBackend { @@ -18,6 +19,7 @@ impl TestBackend { height, buffer: Buffer::empty(Rect::new(0, 0, width, height)), cursor: false, + pos: (0, 0), } } @@ -46,6 +48,13 @@ impl Backend for TestBackend { self.cursor = true; Ok(()) } + fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> { + Ok(self.pos) + } + fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> { + self.pos = (x, y); + Ok(()) + } fn clear(&mut self) -> Result<(), io::Error> { Ok(()) } diff --git a/src/terminal.rs b/src/terminal.rs index 35739a40..aea83598 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -161,6 +161,12 @@ where self.hidden_cursor = false; Ok(()) } + pub fn get_cursor(&mut self) -> io::Result<(u16, u16)> { + self.backend.get_cursor() + } + pub fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> { + self.backend.set_cursor(x, y) + } pub fn clear(&mut self) -> io::Result<()> { self.backend.clear() }