@@ -38,6 +38,34 @@ pub fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> {
38
38
out. write_str ( & format ! ( "\x1B [{};{}H" , y + 1 , x + 1 ) )
39
39
}
40
40
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
+
41
69
pub fn clear_chars ( out : & Term , n : usize ) -> io:: Result < ( ) > {
42
70
if n > 0 {
43
71
out. write_str ( & format ! ( "\x1b [{}D\x1b [0K" , n) )
0 commit comments