Skip to content

Commit

Permalink
Merge pull request #11 from hanmertens/more_colors
Browse files Browse the repository at this point in the history
More colors and some minor changes
  • Loading branch information
matthew-a-thomas authored Aug 17, 2020
2 parents 5a60e31 + 1a6fc65 commit 38f5f64
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 44 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ maintenance = { status = "actively-developed" }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rgb = "0.8"
rgb = { version = "0.8", default-features = false }
26 changes: 12 additions & 14 deletions src/background.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
use core::fmt;
use crate::Canvas;
use crate::Color;
use core::fmt;

/// Adds a background color
pub trait Background<TColor : Color>: Sized {
pub trait Background<TColor: Color>: Sized {
/// Adds the given background color
fn bg(self, color: TColor) -> WithBackground<Self, TColor>;
}

/// Something with a background color
pub struct WithBackground<T, TColor : Color> {
pub struct WithBackground<T, TColor: Color> {
t: T,
color: TColor
color: TColor,
}

impl<T, TColor : Color> Background<TColor> for T {
impl<T, TColor: Color> Background<TColor> for T {
fn bg(self, color: TColor) -> WithBackground<Self, TColor> {
WithBackground {
t: self,
color
}
WithBackground { t: self, color }
}
}

macro_rules! impl_me {
($bound:path, $format_arg:expr) => {
impl<T : $bound, TColor : Color> $bound for WithBackground<T, TColor> {
impl<T: $bound, TColor: Color> $bound for WithBackground<T, TColor> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.color.prelude(f, Canvas::Background)
.and_then(|_| write!(f, $format_arg, self.t))
.and_then(|_| self.color.epilogue(f, Canvas::Background))
self.color
.prelude(f, Canvas::Background)
.and_then(|_| write!(f, $format_arg, self.t))
.and_then(|_| self.color.epilogue(f, Canvas::Background))
}
}
};
Expand All @@ -43,4 +41,4 @@ impl_me!(fmt::LowerHex, "{:x}");
impl_me!(fmt::Octal, "{:o}");
impl_me!(fmt::Pointer, "{:p}");
impl_me!(fmt::UpperExp, "{:E}");
impl_me!(fmt::UpperHex, "{:X}");
impl_me!(fmt::UpperHex, "{:X}");
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
),
}
}
}
4 changes: 2 additions & 2 deletions src/canvas.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub enum Canvas {
Background,
Foreground
}
Foreground,
}
4 changes: 2 additions & 2 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ pub trait Color {
fn prelude(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result;
#[allow(unused)]
fn epilogue(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result {
write!(f, "\x1B[0m")
f.write_str("\x1B[0m")
}
}
}
6 changes: 3 additions & 3 deletions src/colors.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use rgb::RGB8;
use crate::Canvas;
use crate::Color;
use rgb::RGB8;

impl Color for RGB8 {
fn prelude(&self, f: &mut core::fmt::Formatter, canvas: crate::Canvas) -> core::fmt::Result {
match canvas {
Canvas::Foreground => write!(f, "\x1B[38;2;{};{};{}m", self.r, self.g, self.b),
Canvas::Background => write!(f, "\x1B[48;2;{};{};{}m", self.r, self.g, self.b)
Canvas::Background => write!(f, "\x1B[48;2;{};{};{}m", self.r, self.g, self.b),
}
}
}
Expand Down Expand Up @@ -79,4 +79,4 @@ pub const fn magenta() -> RGB8 {
/// Makes <code style="color: black; background: #FF0080">magenta pink</code>
pub const fn magenta_pink() -> RGB8 {
RGB8::new(255, 0, 128)
}
}
26 changes: 12 additions & 14 deletions src/foreground.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
use core::fmt;
use crate::Canvas;
use crate::Color;
use core::fmt;

/// Adds a foreground color
pub trait Foreground<TColor : Color>: Sized {
pub trait Foreground<TColor: Color>: Sized {
/// Adds the given foreground color
fn fg(self, color: TColor) -> WithForeground<Self, TColor>;
}

/// Something with a foreground color
pub struct WithForeground<T, TColor : Color> {
pub struct WithForeground<T, TColor: Color> {
t: T,
color: TColor
color: TColor,
}

impl<T, TColor : Color> Foreground<TColor> for T {
impl<T, TColor: Color> Foreground<TColor> for T {
fn fg(self, color: TColor) -> WithForeground<Self, TColor> {
WithForeground {
t: self,
color
}
WithForeground { t: self, color }
}
}

macro_rules! impl_me {
($bound:path, $format_arg:expr) => {
impl<T : $bound, TColor : Color> $bound for WithForeground<T, TColor> {
impl<T: $bound, TColor: Color> $bound for WithForeground<T, TColor> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.color.prelude(f, Canvas::Foreground)
.and_then(|_| write!(f, $format_arg, self.t))
.and_then(|_| self.color.epilogue(f, Canvas::Foreground))
self.color
.prelude(f, Canvas::Foreground)
.and_then(|_| write!(f, $format_arg, self.t))
.and_then(|_| self.color.epilogue(f, Canvas::Foreground))
}
}
};
Expand All @@ -43,4 +41,4 @@ impl_me!(fmt::LowerHex, "{:x}");
impl_me!(fmt::Octal, "{:o}");
impl_me!(fmt::Pointer, "{:p}");
impl_me!(fmt::UpperExp, "{:E}");
impl_me!(fmt::UpperHex, "{:X}");
impl_me!(fmt::UpperHex, "{:X}");
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ 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::*;
pub use foreground::*;
pub use foreground::*;
31 changes: 27 additions & 4 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use rgb::RGB8;

#[test]
fn use_all_colors() {
println!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
println!(
"{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
"Red".fg(red()),
"Orange".fg(orange()),
"Yellow".fg(yellow()),
Expand All @@ -16,7 +17,9 @@ fn use_all_colors() {
"Blue magenta".fg(white()).bg(blue_magenta()),
"Magenta".fg(magenta()),
"Magenta pink".fg(magenta_pink()),
"Custom color".fg(RGB8::new(123, 231, 111)).bg(RGB8::new(10, 100, 20))
"Custom color"
.fg(RGB8::new(123, 231, 111))
.bg(RGB8::new(10, 100, 20))
);
}

Expand All @@ -32,7 +35,10 @@ fn formatting_of_pointers() {
// https://github.com/rust-osdev/ansi_rgb/issues/2
let hello_world = "Hello, world";
let formatted = hello_world.fg(red()).bg(blue());
assert_eq!("\u{1b}[48;2;0;0;255m\u{1b}[38;2;255;0;0mHello, world\u{1b}[0m\u{1b}[0m", format!("{}", formatted));
assert_eq!(
"\u{1b}[48;2;0;0;255m\u{1b}[38;2;255;0;0mHello, world\u{1b}[0m\u{1b}[0m",
format!("{}", formatted)
);
}

#[test]
Expand All @@ -43,4 +49,21 @@ 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 38f5f64

Please sign in to comment.