Skip to content

Further documentation improvements #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
29 changes: 29 additions & 0 deletions src/common_term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,35 @@ pub fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> {
out.write_str(&format!("\x1B[{};{}H", y + 1, x + 1))
}

/// Return the current cursor's position as a tuple `(n, m)`,
/// where `n` is the row and `m` the column of the cursor (both 1-based).
// FIXME: allow a larger range of characters than u8.
// FIXME: clear the terminal after this operation.
pub fn get_cursor_position(mut out: &Term) -> io::Result<(u8, u8)> {
// Send the code ESC6n to the terminal: asking for the current cursor position.
out.write_str("\x1b[6n")?;
// We expect a response ESC[n;mR, where n and m are the row and column of the cursor.
let mut buf = [0u8; 6];
let num_read = io::Read::read(&mut out, &mut buf)?;
let (n, m) = match buf.as_slice() {
//[a, b, nbyte, c, mbyte, d] if [a, b, c, d] = sdf => (nbyte, mbyte),
// If we didn't read enough bytes, we certainly didn't get the response we wanted.
_ if num_read < buf.len() => return Err(std::io::Error::new(
io::ErrorKind::Other, format!("invalid terminal response: expected six bytes, only read {}", num_read)
)),
[a, b, n, c, m, d] => {
// The bytes a, b, c and d should be byte string \x1 [ ; R.
if &[*a, *b, *c, *d] != b"\x1b[;R" {
return Err(std::io::Error::new(io::ErrorKind::Other, "invalid terminal response: should be of the form ESC[n;mR"));
} else {
(n, m)
}
}
_ => unreachable!(),
};
Ok((*n, *m))
}

pub fn clear_chars(out: &Term, n: usize) -> io::Result<()> {
if n > 0 {
out.write_str(&format!("\x1b[{}D\x1b[0K", n))
Expand Down
11 changes: 8 additions & 3 deletions src/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,16 @@ impl Term {
clear_line(self)
}

/// Clear the last `n` lines before the current line.
/// Clear the last `n` lines before the current line, if possible.
///
/// This positions the cursor at the beginning of the first line
/// that was cleared.
/// Position the cursor at the beginning of the first line that was cleared.
/// Error when `n` is larger than the number of lines before the current cursor.
pub fn clear_last_lines(&self, n: usize) -> io::Result<()> {
let (current_row, _) = get_cursor_position(self)?;
if usize::from(current_row) < n {
// We cannot move up n lines, only current_row ones.
return Err(io::Error::new(io::ErrorKind::Other, format!("can only move up {} lines, not {}", current_row, n)));
}
self.move_cursor_up(n)?;
for _ in 0..n {
self.clear_line()?;
Expand Down