@@ -38,6 +38,34 @@ pub fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> {
3838 out. write_str ( & format ! ( "\x1B [{};{}H" , y + 1 , x + 1 ) )
3939}
4040
41+ /// Return the current cursor's position as a tuple `(n, m)`,
42+ /// where `n` is the row and `m` the column of the cursor (both 1-based).
43+ // FIXME: allow a larger range of characters than u8.
44+ // FIXME: clear the terminal after this operation.
45+ pub fn get_cursor_position ( mut out : & Term ) -> io:: Result < ( u8 , u8 ) > {
46+ // Send the code ESC6n to the terminal: asking for the current cursor position.
47+ out. write_str ( "\x1b [6n" ) ?;
48+ // We expect a response ESC[n;mR, where n and m are the row and column of the cursor.
49+ let mut buf = [ 0u8 ; 6 ] ;
50+ let num_read = io:: Read :: read ( & mut out, & mut buf) ?;
51+ let ( n, m) = match & buf[ ..] {
52+ // If we didn't read enough bytes, we certainly didn't get the response we wanted.
53+ _ if num_read < buf. len ( ) => return Err ( std:: io:: Error :: new (
54+ io:: ErrorKind :: Other , format ! ( "invalid terminal response: expected six bytes, only read {}" , num_read)
55+ ) ) ,
56+ [ a, b, n, c, m, d] => {
57+ // The bytes a, b, c and d should be byte string \x1 [ ; R.
58+ if & [ * a, * b, * c, * d] != b"\x1b [;R" {
59+ return Err ( std:: io:: Error :: new ( io:: ErrorKind :: Other , "invalid terminal response: should be of the form ESC[n;mR" ) ) ;
60+ } else {
61+ ( n, m)
62+ }
63+ }
64+ _ => unreachable ! ( ) ,
65+ } ;
66+ Ok ( ( * n, * m) )
67+ }
68+
4169pub fn clear_chars ( out : & Term , n : usize ) -> io:: Result < ( ) > {
4270 if n > 0 {
4371 out. write_str ( & format ! ( "\x1b [{}D\x1b [0K" , n) )
0 commit comments