From 9e1ba2024576d949af59d00c6fea547bb3bdc947 Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Mon, 17 Aug 2020 21:08:39 +0200 Subject: [PATCH 1/4] Update rgb crate Disable default features as they're not used. --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbdd784..18af134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,13 @@ name = "ansi_rgb" version = "0.3.0" dependencies = [ - "rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rgb 0.8.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rgb" -version = "0.8.13" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" +"checksum rgb 0.8.24 (registry+https://github.com/rust-lang/crates.io-index)" = "7466cad0eb3303798229ffab23bb8f598d185c71f3dfa17cd751d440e375782a" diff --git a/Cargo.toml b/Cargo.toml index 68dde5b..8459870 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" \ No newline at end of file +rgb = { version = "0.8", default-features = false } From 67c2cf8e4947cda1a6cb900b5fb2f548fc548feb Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Mon, 17 Aug 2020 21:09:16 +0200 Subject: [PATCH 2/4] Format Rust code using cargo fmt --- src/background.rs | 26 ++++++++++++-------------- src/canvas.rs | 4 ++-- src/color.rs | 2 +- src/colors.rs | 6 +++--- src/foreground.rs | 26 ++++++++++++-------------- src/lib.rs | 2 +- tests/tests.rs | 14 ++++++++++---- 7 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/background.rs b/src/background.rs index 1db5716..115a3cb 100644 --- a/src/background.rs +++ b/src/background.rs @@ -1,35 +1,33 @@ -use core::fmt; use crate::Canvas; use crate::Color; +use core::fmt; /// Adds a background color -pub trait Background: Sized { +pub trait Background: Sized { /// Adds the given background color fn bg(self, color: TColor) -> WithBackground; } /// Something with a background color -pub struct WithBackground { +pub struct WithBackground { t: T, - color: TColor + color: TColor, } -impl Background for T { +impl Background for T { fn bg(self, color: TColor) -> WithBackground { - WithBackground { - t: self, - color - } + WithBackground { t: self, color } } } macro_rules! impl_me { ($bound:path, $format_arg:expr) => { - impl $bound for WithBackground { + impl $bound for WithBackground { 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)) } } }; @@ -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}"); \ No newline at end of file +impl_me!(fmt::UpperHex, "{:X}"); diff --git a/src/canvas.rs b/src/canvas.rs index 872ad7e..e537561 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -1,4 +1,4 @@ pub enum Canvas { Background, - Foreground -} \ No newline at end of file + Foreground, +} diff --git a/src/color.rs b/src/color.rs index cd81134..997a626 100644 --- a/src/color.rs +++ b/src/color.rs @@ -4,4 +4,4 @@ use core::fmt; pub trait Color { fn prelude(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result; fn epilogue(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result; -} \ No newline at end of file +} diff --git a/src/colors.rs b/src/colors.rs index 76fa1f0..1c5837d 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -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), } } fn epilogue(&self, f: &mut core::fmt::Formatter, _canvas: crate::Canvas) -> core::fmt::Result { @@ -82,4 +82,4 @@ pub const fn magenta() -> RGB8 { /// Makes magenta pink pub const fn magenta_pink() -> RGB8 { RGB8::new(255, 0, 128) -} \ No newline at end of file +} diff --git a/src/foreground.rs b/src/foreground.rs index a8bfdf5..f79e6f5 100644 --- a/src/foreground.rs +++ b/src/foreground.rs @@ -1,35 +1,33 @@ -use core::fmt; use crate::Canvas; use crate::Color; +use core::fmt; /// Adds a foreground color -pub trait Foreground: Sized { +pub trait Foreground: Sized { /// Adds the given foreground color fn fg(self, color: TColor) -> WithForeground; } /// Something with a foreground color -pub struct WithForeground { +pub struct WithForeground { t: T, - color: TColor + color: TColor, } -impl Foreground for T { +impl Foreground for T { fn fg(self, color: TColor) -> WithForeground { - WithForeground { - t: self, - color - } + WithForeground { t: self, color } } } macro_rules! impl_me { ($bound:path, $format_arg:expr) => { - impl $bound for WithForeground { + impl $bound for WithForeground { 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)) } } }; @@ -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}"); \ No newline at end of file +impl_me!(fmt::UpperHex, "{:X}"); diff --git a/src/lib.rs b/src/lib.rs index c23463e..d587975 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,4 +84,4 @@ pub use background::*; pub use canvas::*; pub use color::*; pub use colors::*; -pub use foreground::*; \ No newline at end of file +pub use foreground::*; diff --git a/tests/tests.rs b/tests/tests.rs index b102a2b..464486e 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -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()), @@ -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)) ); } @@ -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] @@ -43,4 +49,4 @@ fn foo() { let foo = Foo(1, 2); println!("{:?}", foo.fg(green())); -} \ No newline at end of file +} From ed81de8b270ee1b84476664944c7f7cc38f74768 Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Mon, 17 Aug 2020 21:28:06 +0200 Subject: [PATCH 3/4] Make epilogue a provided method It should be the same for all colors, but can be overwritten this way. --- src/color.rs | 4 +++- src/colors.rs | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/color.rs b/src/color.rs index 997a626..5e1881e 100644 --- a/src/color.rs +++ b/src/color.rs @@ -3,5 +3,7 @@ use core::fmt; pub trait Color { fn prelude(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result; - fn epilogue(&self, f: &mut fmt::Formatter, canvas: Canvas) -> fmt::Result; + fn epilogue(&self, f: &mut core::fmt::Formatter, _canvas: crate::Canvas) -> core::fmt::Result { + f.write_str("\x1B[0m") + } } diff --git a/src/colors.rs b/src/colors.rs index 1c5837d..92c74f1 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -9,9 +9,6 @@ impl Color for RGB8 { Canvas::Background => write!(f, "\x1B[48;2;{};{};{}m", self.r, self.g, self.b), } } - fn epilogue(&self, f: &mut core::fmt::Formatter, _canvas: crate::Canvas) -> core::fmt::Result { - write!(f, "\x1B[0m") - } } /// Makes white From 1494e9eae121f21006d195fee1c3981c019ee522 Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Mon, 17 Aug 2020 21:29:37 +0200 Subject: [PATCH 4/4] 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) + ); +}