use std::cell::Cell;
use std::fmt;
use std::str;
pub const CLEAR: &str = "\x1B[2J";
pub const MAIN: &str = "\x1B[?1049l";
pub const ALTERNATE: &str = "\x1B[?1049h";
pub const HIDE: &str = "\x1B[?25l";
pub const SHOW: &str = "\x1B[?25h";
pub const RESET: Paint = Paint {
color: Color::Reset,
ground: Ground::Back,
};
#[derive(Copy, Clone, Debug, Default)]
pub struct Move(pub u16, pub u16);
impl fmt::Display for Move {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "\x1B[{};{}H", self.1 + 1, self.0 + 1)
}
}
#[derive(Clone, Debug)]
pub struct Brush {
paint: Paint,
dried: Cell<bool>,
on: bool,
}
impl Brush {
pub fn new(color: Color) -> Self {
Brush {
paint: Paint {
color,
ground: Ground::Back,
},
dried: Cell::new(true),
on: false,
}
}
pub fn dip(&mut self, color: Color) {
let old = self.paint;
let new = Paint {
color,
ground: Ground::Back,
};
if self.on {
self.dried.set(old == new && self.dried.get());
}
self.paint = new;
}
pub fn raise(&mut self) {
self.set(false)
}
pub fn set(&mut self, on: bool) {
self.dried.set(on == self.on && self.dried.get());
self.on = on;
}
}
impl fmt::Display for Brush {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if self.dried.get() {
return Ok(());
}
self.dried.set(true);
write!(fmt, "{}", if self.on { self.paint } else { RESET })
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Paint {
pub color: Color,
pub ground: Ground,
}
impl fmt::Display for Paint {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let g = self.ground as u8;
match self.color {
Color::C8(c) => write!(fmt, "\x1B[{};5;{}m", g, c.0),
Color::C24(c) => write!(fmt, "\x1B[{};2;{};{};{}m", g, c.r, c.g, c.b),
Color::Reset => write!(fmt, "\x1B[{}m", g + 1),
}
}
}
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Ground {
Fore = 38,
Back = 48,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Color {
C8(C8),
C24(C24),
Reset,
}
impl str::FromStr for Color {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(c) = s.parse::<u8>() {
return Ok(Color::C8(C8(c)));
}
let mut it = s.split(',');
let (r, g, b) = match (it.next(), it.next(), it.next(), it.next()) {
(Some(r), Some(g), Some(b), None) => (r, g, b),
_ => return Err(format!("[USER ERROR]: invalid color specifier {}", s)),
};
match (r.parse::<u8>(), g.parse::<u8>(), b.parse::<u8>()) {
(Ok(r), Ok(g), Ok(b)) => Ok(Color::C24(C24 { r, g, b })),
_ => Err(format!("[USER ERROR]: invalid color specifier {}", s)),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct C8(pub u8);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct C24 {
pub r: u8,
pub g: u8,
pub b: u8,
}