use std::io::{IsTerminal, Write};
pub(crate) const HIDE_CURSOR: &[u8] = b"\x1b[?25l";
pub(crate) const SHOW_CURSOR: &[u8] = b"\x1b[?25h";
const CLEAR_CURRENT_LINE: &[u8] = b"\x1b[2K";
const MOVE_TO_COLUMN_0: &[u8] = b"\x1b[1G";
const CLEAR_FROM_CURSOR_DOWN: &[u8] = b"\x1b[J";
pub(crate) fn clear_line<W: Write>(w: &mut W) -> std::io::Result<()> {
w.write_all(CLEAR_CURRENT_LINE)?;
w.write_all(MOVE_TO_COLUMN_0)?;
Ok(())
}
pub(crate) fn move_up<W: Write>(w: &mut W, n: u16) -> std::io::Result<()> {
write!(w, "\x1b[{n}A")
}
pub(crate) struct CursorGuard {
pub(crate) is_tty: bool,
}
impl Drop for CursorGuard {
fn drop(&mut self) {
if self.is_tty {
let mut stdout = std::io::stdout().lock();
let _ = clear_line(&mut stdout);
let _ = stdout.write_all(SHOW_CURSOR);
let _ = stdout.flush();
}
}
}
pub fn reset() -> std::io::Result<()> {
let mut stdout = std::io::stdout().lock();
if !stdout.is_terminal() {
return Ok(());
}
stdout.write_all(SHOW_CURSOR)?;
stdout.write_all(MOVE_TO_COLUMN_0)?;
stdout.write_all(CLEAR_FROM_CURSOR_DOWN)?;
stdout.flush()?;
Ok(())
}