r3bl-org/r3bl-open-core

Add Hex and a Random Variant to Colors Enum

Opened this issue · 4 comments

Currently the Color Enum contains two variants, RBG and ANSI256. Apart from these, the following two variants can be added

  • Color::Hex(String) => This variant takes in Color as a Hex Format and converts it internally to RGB. Converting Hex to ANSI256 will not be required as RGB to ANSI256 function already exists.
  • Color::Random => Calling something like this AnsiStyledText { text: "Print a bold text w/ random color", style: &[ Style::Bold, Style::Foreground(Color::Random), ], }.println(); should print a bold text with a random color.

Hey @nazmulidris. Can you assign this issue to me. By the way, should I be using rand crate for generating a random number?, or can we do something with any built-in crate to generate random numbers instead using an external dependency?

@LuciAkirami Great question about rand crate. We have a ColorWheel implementation in the r3bl_tui crate (in the tui folder of the repo). Maybe take a look there to see if you can find how ColorWheel does it. If this is not enough information to go on, PLMK and I will dig deeper into this later & give you more info 👍🏽

Hi @nazmulidris Working on this after a really long time, sorry for that (busy with office work dangg). So, I'm thinking of doing something like the below

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Color {
    Rgb(u8, u8, u8),
    Ansi256(u8),
    HexColor,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HexColor<'a>{
    pub hex: &'a str,
}

mod hex_color_impl {
    use crate::{
                Ansi256Color,
                HexColor,
                RgbColor,
                TransformColor};
    
    use crate::convert::convert_hex_to_rgb;

    impl TransformColor for HexColor<'_> {
        /// Returns a [RgbColor] representation of the `self` color.
        fn as_rgb(&self) -> RgbColor {
            let rgb = convert_hex_to_rgb(&self.hex);
            RgbColor {
                red: rgb.red,
                green: rgb.green,
                blue: rgb.blue,
            }
        }

        /// Returns the index of a color in 256-color ANSI palette approximating the `self`
        /// color.
        fn as_ansi256(&self) -> Ansi256Color {
            let rgb = convert_hex_to_rgb(&self.hex);
            let rgb = RgbColor {
                red: rgb.red,
                green: rgb.green,
                blue: rgb.blue,
            };
            rgb.as_ansi256()
        }

        /// Returns the index of a color in 256-color ANSI palette approximating the `self`
        /// color as grayscale.
        fn as_grayscale(&self) -> Ansi256Color {
            let rgb = convert_hex_to_rgb(&self.hex);
            let rgb = RgbColor {
                red: rgb.red,
                green: rgb.green,
                blue: rgb.blue,
            };
            rgb.as_grayscale()
        }
    }
}

As for the conversion, below is the code

pub fn convert_hex_to_rgb(hex: &str) -> RgbColor {
    let hex = hex.trim_start_matches('#');
    let red = u8::from_str_radix(&hex[0..2], 16).unwrap_or(0);
    let green = u8::from_str_radix(&hex[2..4], 16).unwrap_or(0);
    let blue = u8::from_str_radix(&hex[4..6], 16).unwrap_or(0);
    RgbColor { red, green, blue }
}

Yet to add checking if the given hex is valid or not. I just want to get a confirmation that I'm going in a right direction

@LuciAkirami This is the right direction. Thanks for sharing the code. It looks good. Looking forward to the PR.

Also if you feel like the PR isn't ready and you want us to take a look at it, just mark it as draft and share it for review. We will understand that since it's marked as draft that the code is in very early stages of development 👍🏽

Also I put your code in Rust playground and it is pretty cool. I didn't know that HexColor could be Copy, since it owns a reference w/ lifetime 'a.

fn main() {
    let hex_string = "abc".to_string();
    let hex_string_ref = &hex_string;
    let it = HexColor { hex: hex_string_ref };
    
    takes_hex(it);

    std::mem::drop(it);

    println!("{:?}", it);
}


fn takes_hex(arg: HexColor) {
  // Drops arg!
}


#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HexColor<'a>{
    pub hex: &'a str,
}