#![warn(clippy::cargo)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![warn(clippy::as_conversions)]
#![warn(clippy::get_unwrap)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::similar_names)]
#![allow(clippy::struct_excessive_bools)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::type_complexity)]
pub mod blocking;
pub mod color;
pub use vt100::Color;
mod error;
pub use error::{Error, Result};
mod key;
pub use key::Key;
mod private;
#[cfg(feature = "async")]
mod output;
#[cfg(feature = "async")]
pub use output::{Output, ScreenGuard};
#[cfg(feature = "async")]
mod input;
#[cfg(feature = "async")]
pub use input::{Input, RawGuard};
const INIT: &[u8] = b"\x1b7\x1b[?47h\x1b[2J\x1b[H\x1b[?25h";
const DEINIT: &[u8] = b"\x1b[?47l\x1b8\x1b[?25h";
pub trait Textmode: private::Output {
fn screen(&self) -> &vt100::Screen {
self.next().screen()
}
fn write(&mut self, buf: &[u8]) {
self.next_mut().process(buf);
}
fn set_size(&mut self, rows: u16, cols: u16) {
self.cur_mut().set_size(rows, cols);
self.next_mut().set_size(rows, cols);
}
fn write_str(&mut self, text: &str) {
self.write(text.as_bytes());
}
fn move_to(&mut self, row: u16, col: u16) {
self.write(b"\x1b[");
self.write_u16(row + 1);
self.write(b";");
self.write_u16(col + 1);
self.write(b"H");
}
fn move_relative(&mut self, row_offset: i16, col_offset: i16) {
let abs_row_offset = row_offset.unsigned_abs();
let abs_col_offset = col_offset.unsigned_abs();
if row_offset > 0 {
self.write(b"\x1b[");
self.write_u16(abs_row_offset);
self.write(b"B");
}
if row_offset < 0 {
self.write(b"\x1b[");
self.write_u16(abs_row_offset);
self.write(b"A");
}
if col_offset > 0 {
self.write(b"\x1b[");
self.write_u16(abs_col_offset);
self.write(b"C");
}
if col_offset < 0 {
self.write(b"\x1b[");
self.write_u16(abs_col_offset);
self.write(b"D");
}
}
fn clear(&mut self) {
self.write(b"\x1b[2J");
}
fn clear_line(&mut self) {
self.write(b"\x1b[K");
}
fn reset_attributes(&mut self) {
self.write(b"\x1b[m");
}
fn set_fgcolor(&mut self, color: vt100::Color) {
match color {
vt100::Color::Default => {
self.write(b"\x1b[39m");
}
vt100::Color::Idx(i) => {
if i < 8 {
self.write(b"\x1b[");
self.write_u8(30 + i);
} else if i < 16 {
self.write(b"\x1b[");
self.write_u8(82 + i);
} else {
self.write(b"\x1b[38;5;");
self.write_u8(i);
}
self.write(b"m");
}
vt100::Color::Rgb(r, g, b) => {
self.write(b"\x1b[38;2;");
self.write_u8(r);
self.write(b";");
self.write_u8(g);
self.write(b";");
self.write_u8(b);
self.write(b"m");
}
}
}
fn set_bgcolor(&mut self, color: vt100::Color) {
match color {
vt100::Color::Default => {
self.write(b"\x1b[49m");
}
vt100::Color::Idx(i) => {
if i < 8 {
self.write(b"\x1b[");
self.write_u8(40 + i);
} else if i < 16 {
self.write(b"\x1b[");
self.write_u8(92 + i);
} else {
self.write(b"\x1b[48;5;");
self.write_u8(i);
}
self.write(b"m");
}
vt100::Color::Rgb(r, g, b) => {
self.write(b"\x1b[48;2;");
self.write_u8(r);
self.write(b";");
self.write_u8(g);
self.write(b";");
self.write_u8(b);
self.write(b"m");
}
}
}
fn set_bold(&mut self, bold: bool) {
if bold {
self.write(b"\x1b[1m");
} else {
self.write(b"\x1b[22m");
}
}
fn set_italic(&mut self, italic: bool) {
if italic {
self.write(b"\x1b[3m");
} else {
self.write(b"\x1b[23m");
}
}
fn set_underline(&mut self, underline: bool) {
if underline {
self.write(b"\x1b[4m");
} else {
self.write(b"\x1b[24m");
}
}
fn set_inverse(&mut self, inverse: bool) {
if inverse {
self.write(b"\x1b[7m");
} else {
self.write(b"\x1b[27m");
}
}
fn hide_cursor(&mut self, hide: bool) {
if hide {
self.write(b"\x1b[?25l");
} else {
self.write(b"\x1b[?25h");
}
}
}