use crate::Position; use std::io::{self, stdout, Error, Write}; use termion::color::{Bg, Fg, Reset, Rgb}; use termion::event::Key; use termion::input::TermRead; use termion::raw::{IntoRawMode, RawTerminal}; pub struct Size { pub height: u16, pub width: u16, } pub struct Terminal { size: Size, _stdout: RawTerminal, } impl Terminal { /// # Errors /// Returns an error if terminal size cannot be retrieved or raw mode cannot be enabled. pub fn new() -> Result { let size = termion::terminal_size()?; Ok(Self { size: Size { width: size.0, height: size.1.saturating_sub(2), }, _stdout: stdout().into_raw_mode()?, }) } #[must_use] pub fn size(&self) -> &Size { &self.size } pub fn clear_screen() { print!("{}", termion::clear::All); } pub fn clear_current_line() { print!("{}", termion::clear::CurrentLine); } #[allow(clippy::cast_possible_truncation)] pub fn reposition_cursor(position: &Position) { let Position { mut x, mut y } = position; x = x.saturating_add(1); y = y.saturating_add(1); let x = x as u16; let y = y as u16; print!("{}", termion::cursor::Goto(x, y)); } /// # Errors /// Returns an error if stdout cannot be flushed pub fn flush() -> Result<(), Error> { io::stdout().flush() } /// # Errors /// Returns an error if input events can't be retrieved pub fn read_key() -> Result { loop { if let Some(key) = io::stdin().lock().keys().next() { return key; } } } pub fn hide_cursor() { print!("{}", termion::cursor::Hide); } pub fn show_cursor() { print!("{}", termion::cursor::Show); } pub fn set_bg_color(color: Rgb) { print!("{}", Bg(color)); } pub fn reset_bg_color() { print!("{}", Bg(Reset)); } pub fn set_fg_color(color: Rgb) { print!("{}", Fg(color)); } pub fn reset_fg_color() { print!("{}", Fg(Reset)); } }