From 9423d49e79dedb840937b467427b3c295379d95d Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Mon, 17 Aug 2020 21:29:37 +0200 Subject: [PATCH] Add support for 3/4-bit colors 3-bit colors are added as an enum, and 4-bit colors a struct contains this enum and a separate bright bit, which is not the most space-efficient. --- src/basic_color.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ tests/tests.rs | 17 ++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/basic_color.rs diff --git a/src/basic_color.rs b/src/basic_color.rs new file mode 100644 index 0000000..d27d292 --- /dev/null +++ b/src/basic_color.rs @@ -0,0 +1,78 @@ +use crate::{Canvas, Color}; + +/// A 3-bit color type +/// +/// The exact colors usually depend on the terminal color scheme. +#[derive(Copy, Clone, Debug)] +pub enum Color3 { + BLACK = 0, + RED = 1, + GREEN = 2, + YELLOW = 3, + BLUE = 4, + MAGENTA = 5, + CYAN = 6, + WHITE = 7, +} + +impl Color for Color3 { + fn prelude(&self, f: &mut core::fmt::Formatter, canvas: crate::Canvas) -> core::fmt::Result { + match canvas { + Canvas::Foreground => write!(f, "\x1B[{}m", 30 + *self as u8), + Canvas::Background => write!(f, "\x1B[{}m", 40 + *self as u8), + } + } +} + +/// A 4-bit color type +/// +/// The different possibilities are available through associated constants; +/// their exact colors usually depend on the terminal color scheme. A 4-bit +/// color without its bright bit set is identical to its corresponding 3-bit +/// color (not necessarily the one with the same name). +#[derive(Copy, Clone, Debug)] +pub struct Color4 { + color3: Color3, + bright: bool, +} + +impl Color4 { + /// Build a Color4 based on [`Color3`] and a bright bit + pub const fn new(color3: Color3, bright: bool) -> Self { + Self { color3, bright } + } + + pub const BLACK: Self = Self::new(Color3::BLACK, false); + pub const RED: Self = Self::new(Color3::RED, false); + pub const GREEN: Self = Self::new(Color3::GREEN, false); + pub const YELLOW: Self = Self::new(Color3::YELLOW, false); + pub const BLUE: Self = Self::new(Color3::BLUE, false); + pub const MAGENTA: Self = Self::new(Color3::MAGENTA, false); + pub const CYAN: Self = Self::new(Color3::CYAN, false); + pub const LIGHT_GRAY: Self = Self::new(Color3::WHITE, false); + pub const DARK_GRAY: Self = Self::new(Color3::BLACK, true); + pub const BRIGHT_RED: Self = Self::new(Color3::RED, true); + pub const BRIGHT_GREEN: Self = Self::new(Color3::GREEN, true); + pub const BRIGHT_YELLOW: Self = Self::new(Color3::YELLOW, true); + pub const BRIGHT_BLUE: Self = Self::new(Color3::BLUE, true); + pub const BRIGHT_MAGENTA: Self = Self::new(Color3::MAGENTA, true); + pub const BRIGHT_CYAN: Self = Self::new(Color3::CYAN, true); + pub const WHITE: Self = Self::new(Color3::WHITE, true); +} + +impl Color for Color4 { + fn prelude(&self, f: &mut core::fmt::Formatter, canvas: crate::Canvas) -> core::fmt::Result { + match canvas { + Canvas::Foreground => write!( + f, + "\x1B[{}m", + if self.bright { 90 } else { 30 } + self.color3 as u8 + ), + Canvas::Background => write!( + f, + "\x1B[{}m", + if self.bright { 100 } else { 40 } + self.color3 as u8 + ), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index d587975..7221fad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,12 +75,14 @@ You need to [set your console mode](https://docs.microsoft.com/en-us/windows/con */ mod background; +mod basic_color; mod canvas; mod color; mod colors; mod foreground; pub use background::*; +pub use basic_color::*; pub use canvas::*; pub use color::*; pub use colors::*; diff --git a/tests/tests.rs b/tests/tests.rs index 464486e..62dc20b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -50,3 +50,20 @@ fn foo() { let foo = Foo(1, 2); println!("{:?}", foo.fg(green())); } + +#[test] +fn color3() { + let hello_world = "Hello, world"; + let formatted = hello_world.fg(Color3::BLUE); + assert_eq!("\u{1b}[34mHello, world\u{1b}[0m", format!("{}", formatted)); +} + +#[test] +fn color4() { + let hello_world = "Hello, world"; + let formatted = hello_world.fg(Color4::BLACK).bg(Color4::WHITE); + assert_eq!( + "\u{1b}[107m\u{1b}[30mHello, world\u{1b}[0m\u{1b}[0m", + format!("{}", formatted) + ); +}