cross: add terminal cursor position report
This commit is contained in:
@@ -192,6 +192,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() {
|
||||
|
||||
@@ -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)]
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user