Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More colors and some minor changes #11

Merged
merged 5 commits into from
Aug 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
);
}