You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Also parse multi-digit cursor positions correctly.
- Clear the terminal after sending the code.
- accept an u16, as terminal can be up to 65536 chars wide or long
- just read a limited buffer, not an entire line;
I can use a fixed-size buffer because of the above.
- note two current FIXMEs in the code.
- restrict this code to UNIX systems for now.
// Send the code "ESC[6n" to the terminal: asking for the current cursor position.
47
46
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
-
letmut buf = [0u8;6];
47
+
// We expect a response of the form "ESC[n;mR", where n and m are the row and column of the cursor.
48
+
// n and m are at most 65536, so 4+2*5 bytes should suffice for these purposes.
49
+
// TODO: this blocks for user input!
50
+
letmut buf = [0u8;4 + 2*5];
50
51
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() => returnErr(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
-
returnErr(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))
52
+
out.clear_chars(num_read)?;
53
+
// FIXME: re-use ANSI code parser instead of rolling my own.
54
+
match&buf[..]{
55
+
[b'\x1B',b'[', middle @ ..,b'R'] => {
56
+
// A valid terminal response means `middle` is valid UTF-8.
57
+
// Use string methods to simplify the parsing of input.
58
+
let middle = match std::str::from_utf8(middle){
59
+
Ok(m) => m,
60
+
Err(_) => returnErr(io::Error::new(io::ErrorKind::Other,format!("invalid terminal response: middle part of the output {:?} must be valid UTF-8", buf))),
61
+
};
62
+
let(nstr, mstr) = match middle.split_once(';'){
63
+
Some((nstr, mstr)) => (nstr, mstr),
64
+
None => returnErr(io::Error::new(io::ErrorKind::Other,format!("invalid terminal response: middle part of the output should be of the form n;m, got {}", middle))),
65
+
};
66
+
let(n, m) = (nstr.parse::<u16>().unwrap(), mstr.parse::<u16>().unwrap());
67
+
Ok((n, m))
68
+
},
69
+
_ => returnErr(io::Error::new(io::ErrorKind::Other,"invalid terminal response: should be of the form ESC[n;mR")),
0 commit comments