cross: add terminal cursor position report

This commit is contained in:
2025-06-20 15:01:41 +03:00
parent d08a42d5b2
commit f3eb88ac19
3 changed files with 64 additions and 0 deletions
+49
View File
@@ -196,6 +196,55 @@ impl TerminalInput {
self.parse_utf8_from_buffer()
}
pub fn read_cursor_position_report(&mut self) -> io::Result<Option<(u32, u32)>> {
#[derive(Clone, Copy)]
enum State {
ReadRow,
ReadColumn,
}
// CSI r ; c R
let mut ch_buffer = [0];
let mut state = State::ReadRow;
let mut row = 0;
let mut column = 0;
self.stdin.read_exact(&mut ch_buffer)?;
if ch_buffer[0] != b'\x1B' {
return Ok(None);
}
self.stdin.read_exact(&mut ch_buffer)?;
if ch_buffer[0] != b'[' {
return Ok(None);
}
loop {
self.stdin.read_exact(&mut ch_buffer)?;
let ch = ch_buffer[0];
match (state, ch) {
(State::ReadRow, b';') => {
state = State::ReadColumn;
}
(State::ReadRow, b'0'..=b'9') => {
row *= 10;
row += (ch - b'0') as u32;
}
(State::ReadColumn, b'R') => {
return Ok(Some((row, column)));
}
(State::ReadColumn, b'0'..=b'9') => {
column *= 10;
column += (ch - b'0') as u32;
}
(_, _) => {
return Ok(None);
}
}
}
}
pub fn read_key(&mut self) -> io::Result<TermKey> {
while self.buffer_len < self.buffer.len() {
if let Some(key) = self.parse_from_buffer() {
+12
View File
@@ -28,6 +28,7 @@ pub trait RawTerminal {
fn raw_leave_alternate_mode(&mut self) -> io::Result<()>;
fn raw_clear_all(&mut self) -> io::Result<()>;
fn raw_clear_line(&mut self, what: u32) -> io::Result<()>;
fn raw_report_cursor_position(&mut self) -> io::Result<()>;
fn raw_move_cursor(&mut self, row: usize, column: usize) -> io::Result<()>;
fn raw_set_cursor_style(&mut self, style: CursorStyle) -> io::Result<()>;
fn raw_set_color(&mut self, fgbg: u32, color: Color) -> io::Result<()>;
@@ -84,6 +85,10 @@ impl RawTerminal for Stdout {
write!(self, "\x1B[{}K", what)
}
fn raw_report_cursor_position(&mut self) -> io::Result<()> {
write!(self, "\x1B[6n")
}
fn raw_move_cursor(&mut self, row: usize, column: usize) -> io::Result<()> {
write!(self, "\x1B[{};{}f", row + 1, column + 1)
}
@@ -140,9 +145,16 @@ impl Term {
Ok(Self { stdin, stdout })
}
pub fn report_cursor_position(&mut self) -> io::Result<Option<(u32, u32)>> {
self.stdout.raw_report_cursor_position()?;
self.stdout.flush()?;
self.stdin.read_cursor_position_report()
}
pub fn set_cursor_position(&mut self, row: usize, column: usize) -> io::Result<()> {
self.stdout.raw_move_cursor(row, column)
}
pub fn set_cursor_visible(&mut self, visible: bool) -> io::Result<()> {
#[cfg(unix)]
{
+3
View File
@@ -13,6 +13,9 @@ fn main() {
term.set_cursor_position(i, 0).ok();
write!(term, "{key:?}").ok();
}
let (row, column) = term.report_cursor_position().unwrap().unwrap();
term.set_cursor_position(25, 0).ok();
write!(term, "row = {row}, column = {column}").ok();
term.flush().ok();
let key = term.read_key().unwrap();