Skip to content

Commit

Permalink
Add support for 3/4-bit colors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hanmertens committed Aug 17, 2020
1 parent ed81de8 commit 1494e9e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
78 changes: 78 additions & 0 deletions src/basic_color.rs
Original file line number Diff line number Diff line change
@@ -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
),
}
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down
17 changes: 17 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
);
}

0 comments on commit 1494e9e

Please sign in to comment.