refactor: move flavours into enum

This commit is contained in:
Gingeh 2022-10-24 15:10:57 +11:00 committed by Hamothy
parent 3223f436fa
commit 309790a80f
10 changed files with 444 additions and 465 deletions

View file

@ -1,15 +1,15 @@
use catppuccin::{LATTE, MOCHA};
use catppuccin::Flavour;
fn main() {
let (r, g, b) = LATTE.teal.into();
let (r, g, b) = Flavour::Latte.palette().teal.into();
println!(
"Latte's teal is #{}, which is rgb({r}, {g}, {b})",
LATTE.teal.hex()
Flavour::Latte.palette().teal.hex()
);
let (r, g, b) = MOCHA.teal.into();
let (r, g, b) = Flavour::Mocha.palette().teal.into();
println!(
"Mocha's teal is #{}, which is rgb({r}, {g}, {b})",
MOCHA.teal.hex()
Flavour::Mocha.palette().teal.hex()
);
}

View file

@ -3,10 +3,10 @@ use catppuccin::flavours_iter;
fn main() {
// iterate over the four Catppuccin flavours.
for flavour in flavours_iter() {
println!("{}", flavour.name);
println!("{}", flavour.name());
// iterate over the 26 colours in the flavour.
for (i, colour) in flavour.iter().enumerate() {
for (i, colour) in flavour.palette().iter().enumerate() {
print!("{}", colour.ansi_paint("██"));
// the 14 analogous colours go on one line,

View file

@ -11,9 +11,9 @@ impl Colour {
/// # Examples
///
/// ```
/// use catppuccin::MOCHA;
/// use catppuccin::Flavour;
///
/// let hex = MOCHA.teal.hex();
/// let hex = Flavour::Mocha.palette().teal.hex();
/// assert_eq!(hex, "94E2D5");
/// ```
pub fn hex(&self) -> String {

View file

@ -1,126 +1,284 @@
use crate::Colour;
/// Contains the colour options for a flavour of Catppuccin.
#[derive(Debug, PartialEq, Eq)]
pub struct Flavour {
pub name: &'static str,
pub rosewater: Colour,
pub flamingo: Colour,
pub pink: Colour,
pub mauve: Colour,
pub red: Colour,
pub maroon: Colour,
pub peach: Colour,
pub yellow: Colour,
pub green: Colour,
pub teal: Colour,
pub sky: Colour,
pub sapphire: Colour,
pub blue: Colour,
pub lavender: Colour,
pub text: Colour,
pub subtext1: Colour,
pub subtext0: Colour,
pub overlay2: Colour,
pub overlay1: Colour,
pub overlay0: Colour,
pub surface2: Colour,
pub surface1: Colour,
pub surface0: Colour,
pub base: Colour,
pub mantle: Colour,
pub crust: Colour,
use crate::{Colour, Palette};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Flavour {
Latte,
Frappe,
Macchiato,
Mocha,
}
impl Flavour {
/// Returns an iterator over the colours in the flavour.
pub fn iter(&self) -> std::array::IntoIter<&Colour, 26> {
[
&self.rosewater,
&self.flamingo,
&self.pink,
&self.mauve,
&self.red,
&self.maroon,
&self.peach,
&self.yellow,
&self.green,
&self.teal,
&self.sky,
&self.sapphire,
&self.blue,
&self.lavender,
&self.text,
&self.subtext1,
&self.subtext0,
&self.overlay2,
&self.overlay1,
&self.overlay0,
&self.surface2,
&self.surface1,
&self.surface0,
&self.base,
&self.mantle,
&self.crust,
]
.into_iter()
pub fn name(self) -> &'static str {
match self {
Self::Latte => "latte",
Self::Frappe => "frappe",
Self::Macchiato => "macchiato",
Self::Mocha => "mocha",
}
}
pub fn palette(self) -> Palette {
match self {
Self::Latte => Palette {
rosewater: Colour(220, 138, 120),
flamingo: Colour(221, 120, 120),
pink: Colour(234, 118, 203),
mauve: Colour(136, 57, 239),
red: Colour(210, 15, 57),
maroon: Colour(230, 69, 83),
peach: Colour(254, 100, 11),
yellow: Colour(223, 142, 29),
green: Colour(64, 160, 43),
teal: Colour(23, 146, 153),
sky: Colour(4, 165, 229),
sapphire: Colour(32, 159, 181),
blue: Colour(30, 102, 245),
lavender: Colour(114, 135, 253),
text: Colour(76, 79, 105),
subtext1: Colour(92, 95, 119),
subtext0: Colour(108, 111, 133),
overlay2: Colour(124, 127, 147),
overlay1: Colour(140, 143, 161),
overlay0: Colour(156, 160, 176),
surface2: Colour(172, 176, 190),
surface1: Colour(188, 192, 204),
surface0: Colour(204, 208, 218),
base: Colour(239, 241, 245),
mantle: Colour(230, 233, 239),
crust: Colour(220, 224, 232),
},
Self::Frappe => Palette {
rosewater: Colour(242, 213, 207),
flamingo: Colour(238, 190, 190),
pink: Colour(244, 184, 228),
mauve: Colour(202, 158, 230),
red: Colour(231, 130, 132),
maroon: Colour(234, 153, 156),
peach: Colour(239, 159, 118),
yellow: Colour(229, 200, 144),
green: Colour(166, 209, 137),
teal: Colour(129, 200, 190),
sky: Colour(153, 209, 219),
sapphire: Colour(133, 193, 220),
blue: Colour(140, 170, 238),
lavender: Colour(186, 187, 241),
text: Colour(198, 208, 245),
subtext1: Colour(181, 191, 226),
subtext0: Colour(165, 173, 206),
overlay2: Colour(148, 156, 187),
overlay1: Colour(131, 139, 167),
overlay0: Colour(115, 121, 148),
surface2: Colour(98, 104, 128),
surface1: Colour(81, 87, 109),
surface0: Colour(65, 69, 89),
base: Colour(48, 52, 70),
mantle: Colour(41, 44, 60),
crust: Colour(35, 38, 52),
},
Self::Macchiato => Palette {
rosewater: Colour(244, 219, 214),
flamingo: Colour(240, 198, 198),
pink: Colour(245, 189, 230),
mauve: Colour(198, 160, 246),
red: Colour(237, 135, 150),
maroon: Colour(238, 153, 160),
peach: Colour(245, 169, 127),
yellow: Colour(238, 212, 159),
green: Colour(166, 218, 149),
teal: Colour(139, 213, 202),
sky: Colour(145, 215, 227),
sapphire: Colour(125, 196, 228),
blue: Colour(138, 173, 244),
lavender: Colour(183, 189, 248),
text: Colour(202, 211, 245),
subtext1: Colour(184, 192, 224),
subtext0: Colour(165, 173, 203),
overlay2: Colour(147, 154, 183),
overlay1: Colour(128, 135, 162),
overlay0: Colour(110, 115, 141),
surface2: Colour(91, 96, 120),
surface1: Colour(73, 77, 100),
surface0: Colour(54, 58, 79),
base: Colour(36, 39, 58),
mantle: Colour(30, 32, 48),
crust: Colour(24, 25, 38),
},
Self::Mocha => Palette {
rosewater: Colour(245, 224, 220),
flamingo: Colour(242, 205, 205),
pink: Colour(245, 194, 231),
mauve: Colour(203, 166, 247),
red: Colour(243, 139, 168),
maroon: Colour(235, 160, 172),
peach: Colour(250, 179, 135),
yellow: Colour(249, 226, 175),
green: Colour(166, 227, 161),
teal: Colour(148, 226, 213),
sky: Colour(137, 220, 235),
sapphire: Colour(116, 199, 236),
blue: Colour(137, 180, 250),
lavender: Colour(180, 190, 254),
text: Colour(205, 214, 244),
subtext1: Colour(186, 194, 222),
subtext0: Colour(166, 173, 200),
overlay2: Colour(147, 153, 178),
overlay1: Colour(127, 132, 156),
overlay0: Colour(108, 112, 134),
surface2: Colour(88, 91, 112),
surface1: Colour(69, 71, 90),
surface0: Colour(49, 50, 68),
base: Colour(30, 30, 46),
mantle: Colour(24, 24, 37),
crust: Colour(17, 17, 27),
}
}
}
}
/// Given a colour table taken from the main catppuccin readme, validate each
/// colour in the given flavour implementation.
/// Copy the table in question from the following URL:
/// https://github.com/catppuccin/catppuccin#-palettes
#[cfg(test)]
pub(crate) fn validate_colours(flavour: Flavour, colours: &str) {
fn from_hex(hex: &str) -> Colour {
let hex = hex.strip_prefix('#').unwrap_or(hex);
let hex = i32::from_str_radix(hex, 16).expect(&format!(
"failed to parse hex string: {hex} (check paste format)"
));
mod tests {
use super::Flavour;
use crate::palette::validate_colours;
use indoc::indoc;
Colour(
((hex & 0x00FF0000) >> 16) as u8,
((hex & 0x0000FF00) >> 8) as u8,
(hex & 0x000000FF) as u8,
)
#[test]
fn validate_latte_colours() {
validate_colours(
Flavour::Latte.palette(),
indoc! {"
Rosewater #dc8a78 rgb(220, 138, 120) hsl(11, 59%, 67%)
Flamingo #dd7878 rgb(221, 120, 120) hsl(0, 60%, 67%)
Pink #ea76cb rgb(234, 118, 203) hsl(316, 73%, 69%)
Mauve #8839ef rgb(136, 57, 239) hsl(266, 85%, 58%)
Red #d20f39 rgb(210, 15, 57) hsl(347, 87%, 44%)
Maroon #e64553 rgb(230, 69, 83) hsl(355, 76%, 59%)
Peach #fe640b rgb(254, 100, 11) hsl(22, 99%, 52%)
Yellow #df8e1d rgb(223, 142, 29) hsl(35, 77%, 49%)
Green #40a02b rgb(64, 160, 43) hsl(109, 58%, 40%)
Teal #179299 rgb(23, 146, 153) hsl(183, 74%, 35%)
Sky #04a5e5 rgb(4, 165, 229) hsl(197, 97%, 46%)
Sapphire #209fb5 rgb(32, 159, 181) hsl(189, 70%, 42%)
Blue #1e66f5 rgb(30, 102, 245) hsl(220, 91%, 54%)
Lavender #7287fd rgb(114, 135, 253) hsl(231, 97%, 72%)
Text #4c4f69 rgb(76, 79, 105) hsl(234, 16%, 35%)
Subtext1 #5c5f77 rgb(92, 95, 119) hsl(233, 13%, 41%)
Subtext0 #6c6f85 rgb(108, 111, 133) hsl(233, 10%, 47%)
Overlay2 #7c7f93 rgb(124, 127, 147) hsl(232, 10%, 53%)
Overlay1 #8c8fa1 rgb(140, 143, 161) hsl(231, 10%, 59%)
Overlay0 #9ca0b0 rgb(156, 160, 176) hsl(228, 11%, 65%)
Surface2 #acb0be rgb(172, 176, 190) hsl(227, 12%, 71%)
Surface1 #bcc0cc rgb(188, 192, 204) hsl(225, 14%, 77%)
Surface0 #ccd0da rgb(204, 208, 218) hsl(223, 16%, 83%)
Base #eff1f5 rgb(239, 241, 245) hsl(220, 23%, 95%)
Mantle #e6e9ef rgb(230, 233, 239) hsl(220, 22%, 92%)
Crust #dce0e8 rgb(220, 224, 232) hsl(220, 21%, 89%)
"},
);
}
let mut colours = colours.trim().split('\n').map(|line| -> Colour {
let hex = line.split('\t').collect::<Vec<_>>()[1].trim();
from_hex(hex)
});
#[test]
fn validate_frappe_colours() {
validate_colours(
Flavour::Frappe.palette(),
indoc! {"
Rosewater #f2d5cf rgb(242, 213, 207) hsl(10, 57%, 88%)
Flamingo #eebebe rgb(238, 190, 190) hsl(0, 59%, 84%)
Pink #f4b8e4 rgb(244, 184, 228) hsl(316, 73%, 84%)
Mauve #ca9ee6 rgb(202, 158, 230) hsl(277, 59%, 76%)
Red #e78284 rgb(231, 130, 132) hsl(359, 68%, 71%)
Maroon #ea999c rgb(234, 153, 156) hsl(358, 66%, 76%)
Peach #ef9f76 rgb(239, 159, 118) hsl(20, 79%, 70%)
Yellow #e5c890 rgb(229, 200, 144) hsl(40, 62%, 73%)
Green #a6d189 rgb(166, 209, 137) hsl(96, 44%, 68%)
Teal #81c8be rgb(129, 200, 190) hsl(172, 39%, 65%)
Sky #99d1db rgb(153, 209, 219) hsl(189, 48%, 73%)
Sapphire #85c1dc rgb(133, 193, 220) hsl(199, 55%, 69%)
Blue #8caaee rgb(140, 170, 238) hsl(222, 74%, 74%)
Lavender #babbf1 rgb(186, 187, 241) hsl(239, 66%, 84%)
Text #c6d0f5 rgb(198, 208, 245) hsl(227, 70%, 87%)
Subtext1 #b5bfe2 rgb(181, 191, 226) hsl(227, 44%, 80%)
Subtext0 #a5adce rgb(165, 173, 206) hsl(228, 29%, 73%)
Overlay2 #949cbb rgb(148, 156, 187) hsl(228, 22%, 66%)
Overlay1 #838ba7 rgb(131, 139, 167) hsl(227, 17%, 58%)
Overlay0 #737994 rgb(115, 121, 148) hsl(229, 13%, 52%)
Surface2 #626880 rgb(98, 104, 128) hsl(228, 13%, 44%)
Surface1 #51576d rgb(81, 87, 109) hsl(227, 15%, 37%)
Surface0 #414559 rgb(65, 69, 89) hsl(230, 16%, 30%)
Base #303446 rgb(48, 52, 70) hsl(229, 19%, 23%)
Mantle #292c3c rgb(41, 44, 60) hsl(231, 19%, 20%)
Crust #232634 rgb(35, 38, 52) hsl(229, 20%, 17%)
"},
);
}
let mut next_colour = || {
colours
.next()
.expect("ran out of colours, check paste format")
};
#[test]
fn validate_macchiato_colours() {
validate_colours(
Flavour::Macchiato.palette(),
indoc! {"
Rosewater #f4dbd6 rgb(244, 219, 214) hsl(10, 58%, 90%)
Flamingo #f0c6c6 rgb(240, 198, 198) hsl(0, 58%, 86%)
Pink #f5bde6 rgb(245, 189, 230) hsl(316, 74%, 85%)
Mauve #c6a0f6 rgb(198, 160, 246) hsl(267, 83%, 80%)
Red #ed8796 rgb(237, 135, 150) hsl(351, 74%, 73%)
Maroon #ee99a0 rgb(238, 153, 160) hsl(355, 71%, 77%)
Peach #f5a97f rgb(245, 169, 127) hsl(21, 86%, 73%)
Yellow #eed49f rgb(238, 212, 159) hsl(40, 70%, 78%)
Green #a6da95 rgb(166, 218, 149) hsl(105, 48%, 72%)
Teal #8bd5ca rgb(139, 213, 202) hsl(171, 47%, 69%)
Sky #91d7e3 rgb(145, 215, 227) hsl(189, 59%, 73%)
Sapphire #7dc4e4 rgb(125, 196, 228) hsl(199, 66%, 69%)
Blue #8aadf4 rgb(138, 173, 244) hsl(220, 83%, 75%)
Lavender #b7bdf8 rgb(183, 189, 248) hsl(234, 82%, 85%)
Text #cad3f5 rgb(202, 211, 245) hsl(227, 68%, 88%)
Subtext1 #b8c0e0 rgb(184, 192, 224) hsl(228, 39%, 80%)
Subtext0 #a5adcb rgb(165, 173, 203) hsl(227, 27%, 72%)
Overlay2 #939ab7 rgb(147, 154, 183) hsl(228, 20%, 65%)
Overlay1 #8087a2 rgb(128, 135, 162) hsl(228, 15%, 57%)
Overlay0 #6e738d rgb(110, 115, 141) hsl(230, 12%, 49%)
Surface2 #5b6078 rgb(91, 96, 120) hsl(230, 14%, 41%)
Surface1 #494d64 rgb(73, 77, 100) hsl(231, 16%, 34%)
Surface0 #363a4f rgb(54, 58, 79) hsl(230, 19%, 26%)
Base #24273a rgb(36, 39, 58) hsl(232, 23%, 18%)
Mantle #1e2030 rgb(30, 32, 48) hsl(233, 23%, 15%)
Crust #181926 rgb(24, 25, 38) hsl(236, 23%, 12%)
"},
);
}
assert_eq!(next_colour(), flavour.rosewater);
assert_eq!(next_colour(), flavour.flamingo);
assert_eq!(next_colour(), flavour.pink);
assert_eq!(next_colour(), flavour.mauve);
assert_eq!(next_colour(), flavour.red);
assert_eq!(next_colour(), flavour.maroon);
assert_eq!(next_colour(), flavour.peach);
assert_eq!(next_colour(), flavour.yellow);
assert_eq!(next_colour(), flavour.green);
assert_eq!(next_colour(), flavour.teal);
assert_eq!(next_colour(), flavour.sky);
assert_eq!(next_colour(), flavour.sapphire);
assert_eq!(next_colour(), flavour.blue);
assert_eq!(next_colour(), flavour.lavender);
assert_eq!(next_colour(), flavour.text);
assert_eq!(next_colour(), flavour.subtext1);
assert_eq!(next_colour(), flavour.subtext0);
assert_eq!(next_colour(), flavour.overlay2);
assert_eq!(next_colour(), flavour.overlay1);
assert_eq!(next_colour(), flavour.overlay0);
assert_eq!(next_colour(), flavour.surface2);
assert_eq!(next_colour(), flavour.surface1);
assert_eq!(next_colour(), flavour.surface0);
assert_eq!(next_colour(), flavour.base);
assert_eq!(next_colour(), flavour.mantle);
assert_eq!(next_colour(), flavour.crust);
#[test]
fn validate_mocha_colours() {
validate_colours(
Flavour::Mocha.palette(),
indoc! {"
Rosewater #f5e0dc rgb(245, 224, 220) hsl(10, 56%, 91%)
Flamingo #f2cdcd rgb(242, 205, 205) hsl(0, 59%, 88%)
Pink #f5c2e7 rgb(245, 194, 231) hsl(316, 72%, 86%)
Mauve #cba6f7 rgb(203, 166, 247) hsl(267, 84%, 81%)
Red #f38ba8 rgb(243, 139, 168) hsl(343, 81%, 75%)
Maroon #eba0ac rgb(235, 160, 172) hsl(350, 65%, 77%)
Peach #fab387 rgb(250, 179, 135) hsl(23, 92%, 75%)
Yellow #f9e2af rgb(249, 226, 175) hsl(41, 86%, 83%)
Green #a6e3a1 rgb(166, 227, 161) hsl(115, 54%, 76%)
Teal #94e2d5 rgb(148, 226, 213) hsl(170, 57%, 73%)
Sky #89dceb rgb(137, 220, 235) hsl(189, 71%, 73%)
Sapphire #74c7ec rgb(116, 199, 236) hsl(199, 76%, 69%)
Blue #89b4fa rgb(137, 180, 250) hsl(217, 92%, 76%)
Lavender #b4befe rgb(180, 190, 254) hsl(232, 97%, 85%)
Text #cdd6f4 rgb(205, 214, 244) hsl(226, 64%, 88%)
Subtext1 #bac2de rgb(186, 194, 222) hsl(227, 35%, 80%)
Subtext0 #a6adc8 rgb(166, 173, 200) hsl(228, 24%, 72%)
Overlay2 #9399b2 rgb(147, 153, 178) hsl(228, 17%, 64%)
Overlay1 #7f849c rgb(127, 132, 156) hsl(230, 13%, 55%)
Overlay0 #6c7086 rgb(108, 112, 134) hsl(231, 11%, 47%)
Surface2 #585b70 rgb(88, 91, 112) hsl(233, 12%, 39%)
Surface1 #45475a rgb(69, 71, 90) hsl(234, 13%, 31%)
Surface0 #313244 rgb(49, 50, 68) hsl(237, 16%, 23%)
Base #1e1e2e rgb(30, 30, 46) hsl(240, 21%, 15%)
Mantle #181825 rgb(24, 24, 37) hsl(240, 21%, 12%)
Crust #11111b rgb(17, 17, 27) hsl(240, 23%, 9%)
"},
);
}
}

View file

@ -1,74 +0,0 @@
use crate::{Colour, Flavour};
/// Frappe flavoured Catppuccin.
pub const FRAPPE: Flavour = Flavour {
name: "frappe",
rosewater: Colour(242, 213, 207),
flamingo: Colour(238, 190, 190),
pink: Colour(244, 184, 228),
mauve: Colour(202, 158, 230),
red: Colour(231, 130, 132),
maroon: Colour(234, 153, 156),
peach: Colour(239, 159, 118),
yellow: Colour(229, 200, 144),
green: Colour(166, 209, 137),
teal: Colour(129, 200, 190),
sky: Colour(153, 209, 219),
sapphire: Colour(133, 193, 220),
blue: Colour(140, 170, 238),
lavender: Colour(186, 187, 241),
text: Colour(198, 208, 245),
subtext1: Colour(181, 191, 226),
subtext0: Colour(165, 173, 206),
overlay2: Colour(148, 156, 187),
overlay1: Colour(131, 139, 167),
overlay0: Colour(115, 121, 148),
surface2: Colour(98, 104, 128),
surface1: Colour(81, 87, 109),
surface0: Colour(65, 69, 89),
base: Colour(48, 52, 70),
mantle: Colour(41, 44, 60),
crust: Colour(35, 38, 52),
};
#[cfg(test)]
mod tests {
use super::FRAPPE;
use crate::flavour::validate_colours;
use indoc::indoc;
#[test]
fn validate_frappe_colours() {
validate_colours(
FRAPPE,
indoc! {"
Rosewater #f2d5cf rgb(242, 213, 207) hsl(10, 57%, 88%)
Flamingo #eebebe rgb(238, 190, 190) hsl(0, 59%, 84%)
Pink #f4b8e4 rgb(244, 184, 228) hsl(316, 73%, 84%)
Mauve #ca9ee6 rgb(202, 158, 230) hsl(277, 59%, 76%)
Red #e78284 rgb(231, 130, 132) hsl(359, 68%, 71%)
Maroon #ea999c rgb(234, 153, 156) hsl(358, 66%, 76%)
Peach #ef9f76 rgb(239, 159, 118) hsl(20, 79%, 70%)
Yellow #e5c890 rgb(229, 200, 144) hsl(40, 62%, 73%)
Green #a6d189 rgb(166, 209, 137) hsl(96, 44%, 68%)
Teal #81c8be rgb(129, 200, 190) hsl(172, 39%, 65%)
Sky #99d1db rgb(153, 209, 219) hsl(189, 48%, 73%)
Sapphire #85c1dc rgb(133, 193, 220) hsl(199, 55%, 69%)
Blue #8caaee rgb(140, 170, 238) hsl(222, 74%, 74%)
Lavender #babbf1 rgb(186, 187, 241) hsl(239, 66%, 84%)
Text #c6d0f5 rgb(198, 208, 245) hsl(227, 70%, 87%)
Subtext1 #b5bfe2 rgb(181, 191, 226) hsl(227, 44%, 80%)
Subtext0 #a5adce rgb(165, 173, 206) hsl(228, 29%, 73%)
Overlay2 #949cbb rgb(148, 156, 187) hsl(228, 22%, 66%)
Overlay1 #838ba7 rgb(131, 139, 167) hsl(227, 17%, 58%)
Overlay0 #737994 rgb(115, 121, 148) hsl(229, 13%, 52%)
Surface2 #626880 rgb(98, 104, 128) hsl(228, 13%, 44%)
Surface1 #51576d rgb(81, 87, 109) hsl(227, 15%, 37%)
Surface0 #414559 rgb(65, 69, 89) hsl(230, 16%, 30%)
Base #303446 rgb(48, 52, 70) hsl(229, 19%, 23%)
Mantle #292c3c rgb(41, 44, 60) hsl(231, 19%, 20%)
Crust #232634 rgb(35, 38, 52) hsl(229, 20%, 17%)
"},
);
}
}

View file

@ -1,74 +0,0 @@
use crate::{flavour::Flavour, Colour};
/// Latte flavoured Catppuccin.
pub const LATTE: Flavour = Flavour {
name: "latte",
rosewater: Colour(220, 138, 120),
flamingo: Colour(221, 120, 120),
pink: Colour(234, 118, 203),
mauve: Colour(136, 57, 239),
red: Colour(210, 15, 57),
maroon: Colour(230, 69, 83),
peach: Colour(254, 100, 11),
yellow: Colour(223, 142, 29),
green: Colour(64, 160, 43),
teal: Colour(23, 146, 153),
sky: Colour(4, 165, 229),
sapphire: Colour(32, 159, 181),
blue: Colour(30, 102, 245),
lavender: Colour(114, 135, 253),
text: Colour(76, 79, 105),
subtext1: Colour(92, 95, 119),
subtext0: Colour(108, 111, 133),
overlay2: Colour(124, 127, 147),
overlay1: Colour(140, 143, 161),
overlay0: Colour(156, 160, 176),
surface2: Colour(172, 176, 190),
surface1: Colour(188, 192, 204),
surface0: Colour(204, 208, 218),
base: Colour(239, 241, 245),
mantle: Colour(230, 233, 239),
crust: Colour(220, 224, 232),
};
#[cfg(test)]
mod tests {
use super::LATTE;
use crate::flavour::validate_colours;
use indoc::indoc;
#[test]
fn validate_latte_colours() {
validate_colours(
LATTE,
indoc! {"
Rosewater #dc8a78 rgb(220, 138, 120) hsl(11, 59%, 67%)
Flamingo #dd7878 rgb(221, 120, 120) hsl(0, 60%, 67%)
Pink #ea76cb rgb(234, 118, 203) hsl(316, 73%, 69%)
Mauve #8839ef rgb(136, 57, 239) hsl(266, 85%, 58%)
Red #d20f39 rgb(210, 15, 57) hsl(347, 87%, 44%)
Maroon #e64553 rgb(230, 69, 83) hsl(355, 76%, 59%)
Peach #fe640b rgb(254, 100, 11) hsl(22, 99%, 52%)
Yellow #df8e1d rgb(223, 142, 29) hsl(35, 77%, 49%)
Green #40a02b rgb(64, 160, 43) hsl(109, 58%, 40%)
Teal #179299 rgb(23, 146, 153) hsl(183, 74%, 35%)
Sky #04a5e5 rgb(4, 165, 229) hsl(197, 97%, 46%)
Sapphire #209fb5 rgb(32, 159, 181) hsl(189, 70%, 42%)
Blue #1e66f5 rgb(30, 102, 245) hsl(220, 91%, 54%)
Lavender #7287fd rgb(114, 135, 253) hsl(231, 97%, 72%)
Text #4c4f69 rgb(76, 79, 105) hsl(234, 16%, 35%)
Subtext1 #5c5f77 rgb(92, 95, 119) hsl(233, 13%, 41%)
Subtext0 #6c6f85 rgb(108, 111, 133) hsl(233, 10%, 47%)
Overlay2 #7c7f93 rgb(124, 127, 147) hsl(232, 10%, 53%)
Overlay1 #8c8fa1 rgb(140, 143, 161) hsl(231, 10%, 59%)
Overlay0 #9ca0b0 rgb(156, 160, 176) hsl(228, 11%, 65%)
Surface2 #acb0be rgb(172, 176, 190) hsl(227, 12%, 71%)
Surface1 #bcc0cc rgb(188, 192, 204) hsl(225, 14%, 77%)
Surface0 #ccd0da rgb(204, 208, 218) hsl(223, 16%, 83%)
Base #eff1f5 rgb(239, 241, 245) hsl(220, 23%, 95%)
Mantle #e6e9ef rgb(230, 233, 239) hsl(220, 22%, 92%)
Crust #dce0e8 rgb(220, 224, 232) hsl(220, 21%, 89%)
"},
);
}
}

View file

@ -12,7 +12,7 @@
//! # Example
//!
//! ```rust
//! use catppuccin::MOCHA;
//! use catppuccin::Flavour;
//!
//! struct Button {
//! text: String,
@ -22,7 +22,7 @@
//! fn confirm(text: String) -> Button {
//! Button {
//! text,
//! background_colour: MOCHA.green.hex(),
//! background_colour: Flavour::Mocha.palette().green.hex(),
//! }
//! }
//! ```
@ -55,38 +55,29 @@
mod colour;
pub use colour::Colour;
mod palette;
pub use palette::Palette;
mod flavour;
pub use flavour::Flavour;
mod latte;
pub use latte::LATTE;
mod frappe;
pub use frappe::FRAPPE;
mod macchiato;
pub use macchiato::MACCHIATO;
mod mocha;
pub use mocha::MOCHA;
/// Returns an iterator over the four delicious Catppuccin flavours.
pub fn flavours_iter() -> std::array::IntoIter<Flavour, 4> {
[LATTE, FRAPPE, MACCHIATO, MOCHA].into_iter()
[Flavour::Latte, Flavour::Frappe, Flavour::Macchiato, Flavour::Mocha].into_iter()
}
#[cfg(test)]
mod tests {
use super::{flavours_iter, FRAPPE, LATTE, MACCHIATO, MOCHA};
use super::{flavours_iter, Flavour};
/// Ensures flavours are iterated in the correct order.
#[test]
fn test_flavours_iter() {
let mut flavours = flavours_iter();
assert_eq!(flavours.next(), Some(LATTE));
assert_eq!(flavours.next(), Some(FRAPPE));
assert_eq!(flavours.next(), Some(MACCHIATO));
assert_eq!(flavours.next(), Some(MOCHA));
assert_eq!(flavours.next(), Some(Flavour::Latte));
assert_eq!(flavours.next(), Some(Flavour::Frappe));
assert_eq!(flavours.next(), Some(Flavour::Macchiato));
assert_eq!(flavours.next(), Some(Flavour::Mocha));
assert_eq!(flavours.next(), None);
}
@ -94,33 +85,34 @@ mod tests {
#[test]
fn test_colours_iter() {
for flavour in flavours_iter() {
let mut colours = flavour.iter();
assert_eq!(colours.next(), Some(&flavour.rosewater));
assert_eq!(colours.next(), Some(&flavour.flamingo));
assert_eq!(colours.next(), Some(&flavour.pink));
assert_eq!(colours.next(), Some(&flavour.mauve));
assert_eq!(colours.next(), Some(&flavour.red));
assert_eq!(colours.next(), Some(&flavour.maroon));
assert_eq!(colours.next(), Some(&flavour.peach));
assert_eq!(colours.next(), Some(&flavour.yellow));
assert_eq!(colours.next(), Some(&flavour.green));
assert_eq!(colours.next(), Some(&flavour.teal));
assert_eq!(colours.next(), Some(&flavour.sky));
assert_eq!(colours.next(), Some(&flavour.sapphire));
assert_eq!(colours.next(), Some(&flavour.blue));
assert_eq!(colours.next(), Some(&flavour.lavender));
assert_eq!(colours.next(), Some(&flavour.text));
assert_eq!(colours.next(), Some(&flavour.subtext1));
assert_eq!(colours.next(), Some(&flavour.subtext0));
assert_eq!(colours.next(), Some(&flavour.overlay2));
assert_eq!(colours.next(), Some(&flavour.overlay1));
assert_eq!(colours.next(), Some(&flavour.overlay0));
assert_eq!(colours.next(), Some(&flavour.surface2));
assert_eq!(colours.next(), Some(&flavour.surface1));
assert_eq!(colours.next(), Some(&flavour.surface0));
assert_eq!(colours.next(), Some(&flavour.base));
assert_eq!(colours.next(), Some(&flavour.mantle));
assert_eq!(colours.next(), Some(&flavour.crust));
let palette = flavour.palette();
let mut colours = palette.iter();
assert_eq!(colours.next(), Some(&palette.rosewater));
assert_eq!(colours.next(), Some(&palette.flamingo));
assert_eq!(colours.next(), Some(&palette.pink));
assert_eq!(colours.next(), Some(&palette.mauve));
assert_eq!(colours.next(), Some(&palette.red));
assert_eq!(colours.next(), Some(&palette.maroon));
assert_eq!(colours.next(), Some(&palette.peach));
assert_eq!(colours.next(), Some(&palette.yellow));
assert_eq!(colours.next(), Some(&palette.green));
assert_eq!(colours.next(), Some(&palette.teal));
assert_eq!(colours.next(), Some(&palette.sky));
assert_eq!(colours.next(), Some(&palette.sapphire));
assert_eq!(colours.next(), Some(&palette.blue));
assert_eq!(colours.next(), Some(&palette.lavender));
assert_eq!(colours.next(), Some(&palette.text));
assert_eq!(colours.next(), Some(&palette.subtext1));
assert_eq!(colours.next(), Some(&palette.subtext0));
assert_eq!(colours.next(), Some(&palette.overlay2));
assert_eq!(colours.next(), Some(&palette.overlay1));
assert_eq!(colours.next(), Some(&palette.overlay0));
assert_eq!(colours.next(), Some(&palette.surface2));
assert_eq!(colours.next(), Some(&palette.surface1));
assert_eq!(colours.next(), Some(&palette.surface0));
assert_eq!(colours.next(), Some(&palette.base));
assert_eq!(colours.next(), Some(&palette.mantle));
assert_eq!(colours.next(), Some(&palette.crust));
}
}
}

View file

@ -1,74 +0,0 @@
use crate::{Colour, Flavour};
/// Macchiato flavoured Catppuccin.
pub const MACCHIATO: Flavour = Flavour {
name: "macchiato",
rosewater: Colour(244, 219, 214),
flamingo: Colour(240, 198, 198),
pink: Colour(245, 189, 230),
mauve: Colour(198, 160, 246),
red: Colour(237, 135, 150),
maroon: Colour(238, 153, 160),
peach: Colour(245, 169, 127),
yellow: Colour(238, 212, 159),
green: Colour(166, 218, 149),
teal: Colour(139, 213, 202),
sky: Colour(145, 215, 227),
sapphire: Colour(125, 196, 228),
blue: Colour(138, 173, 244),
lavender: Colour(183, 189, 248),
text: Colour(202, 211, 245),
subtext1: Colour(184, 192, 224),
subtext0: Colour(165, 173, 203),
overlay2: Colour(147, 154, 183),
overlay1: Colour(128, 135, 162),
overlay0: Colour(110, 115, 141),
surface2: Colour(91, 96, 120),
surface1: Colour(73, 77, 100),
surface0: Colour(54, 58, 79),
base: Colour(36, 39, 58),
mantle: Colour(30, 32, 48),
crust: Colour(24, 25, 38),
};
#[cfg(test)]
mod tests {
use super::MACCHIATO;
use crate::flavour::validate_colours;
use indoc::indoc;
#[test]
fn validate_macchiato_colours() {
validate_colours(
MACCHIATO,
indoc! {"
Rosewater #f4dbd6 rgb(244, 219, 214) hsl(10, 58%, 90%)
Flamingo #f0c6c6 rgb(240, 198, 198) hsl(0, 58%, 86%)
Pink #f5bde6 rgb(245, 189, 230) hsl(316, 74%, 85%)
Mauve #c6a0f6 rgb(198, 160, 246) hsl(267, 83%, 80%)
Red #ed8796 rgb(237, 135, 150) hsl(351, 74%, 73%)
Maroon #ee99a0 rgb(238, 153, 160) hsl(355, 71%, 77%)
Peach #f5a97f rgb(245, 169, 127) hsl(21, 86%, 73%)
Yellow #eed49f rgb(238, 212, 159) hsl(40, 70%, 78%)
Green #a6da95 rgb(166, 218, 149) hsl(105, 48%, 72%)
Teal #8bd5ca rgb(139, 213, 202) hsl(171, 47%, 69%)
Sky #91d7e3 rgb(145, 215, 227) hsl(189, 59%, 73%)
Sapphire #7dc4e4 rgb(125, 196, 228) hsl(199, 66%, 69%)
Blue #8aadf4 rgb(138, 173, 244) hsl(220, 83%, 75%)
Lavender #b7bdf8 rgb(183, 189, 248) hsl(234, 82%, 85%)
Text #cad3f5 rgb(202, 211, 245) hsl(227, 68%, 88%)
Subtext1 #b8c0e0 rgb(184, 192, 224) hsl(228, 39%, 80%)
Subtext0 #a5adcb rgb(165, 173, 203) hsl(227, 27%, 72%)
Overlay2 #939ab7 rgb(147, 154, 183) hsl(228, 20%, 65%)
Overlay1 #8087a2 rgb(128, 135, 162) hsl(228, 15%, 57%)
Overlay0 #6e738d rgb(110, 115, 141) hsl(230, 12%, 49%)
Surface2 #5b6078 rgb(91, 96, 120) hsl(230, 14%, 41%)
Surface1 #494d64 rgb(73, 77, 100) hsl(231, 16%, 34%)
Surface0 #363a4f rgb(54, 58, 79) hsl(230, 19%, 26%)
Base #24273a rgb(36, 39, 58) hsl(232, 23%, 18%)
Mantle #1e2030 rgb(30, 32, 48) hsl(233, 23%, 15%)
Crust #181926 rgb(24, 25, 38) hsl(236, 23%, 12%)
"},
);
}
}

View file

@ -1,74 +0,0 @@
use crate::{Colour, Flavour};
/// Mocha flavoured Catppuccin.
pub const MOCHA: Flavour = Flavour {
name: "mocha",
rosewater: Colour(245, 224, 220),
flamingo: Colour(242, 205, 205),
pink: Colour(245, 194, 231),
mauve: Colour(203, 166, 247),
red: Colour(243, 139, 168),
maroon: Colour(235, 160, 172),
peach: Colour(250, 179, 135),
yellow: Colour(249, 226, 175),
green: Colour(166, 227, 161),
teal: Colour(148, 226, 213),
sky: Colour(137, 220, 235),
sapphire: Colour(116, 199, 236),
blue: Colour(137, 180, 250),
lavender: Colour(180, 190, 254),
text: Colour(205, 214, 244),
subtext1: Colour(186, 194, 222),
subtext0: Colour(166, 173, 200),
overlay2: Colour(147, 153, 178),
overlay1: Colour(127, 132, 156),
overlay0: Colour(108, 112, 134),
surface2: Colour(88, 91, 112),
surface1: Colour(69, 71, 90),
surface0: Colour(49, 50, 68),
base: Colour(30, 30, 46),
mantle: Colour(24, 24, 37),
crust: Colour(17, 17, 27),
};
#[cfg(test)]
mod tests {
use super::MOCHA;
use crate::flavour::validate_colours;
use indoc::indoc;
#[test]
fn validate_mocha_colours() {
validate_colours(
MOCHA,
indoc! {"
Rosewater #f5e0dc rgb(245, 224, 220) hsl(10, 56%, 91%)
Flamingo #f2cdcd rgb(242, 205, 205) hsl(0, 59%, 88%)
Pink #f5c2e7 rgb(245, 194, 231) hsl(316, 72%, 86%)
Mauve #cba6f7 rgb(203, 166, 247) hsl(267, 84%, 81%)
Red #f38ba8 rgb(243, 139, 168) hsl(343, 81%, 75%)
Maroon #eba0ac rgb(235, 160, 172) hsl(350, 65%, 77%)
Peach #fab387 rgb(250, 179, 135) hsl(23, 92%, 75%)
Yellow #f9e2af rgb(249, 226, 175) hsl(41, 86%, 83%)
Green #a6e3a1 rgb(166, 227, 161) hsl(115, 54%, 76%)
Teal #94e2d5 rgb(148, 226, 213) hsl(170, 57%, 73%)
Sky #89dceb rgb(137, 220, 235) hsl(189, 71%, 73%)
Sapphire #74c7ec rgb(116, 199, 236) hsl(199, 76%, 69%)
Blue #89b4fa rgb(137, 180, 250) hsl(217, 92%, 76%)
Lavender #b4befe rgb(180, 190, 254) hsl(232, 97%, 85%)
Text #cdd6f4 rgb(205, 214, 244) hsl(226, 64%, 88%)
Subtext1 #bac2de rgb(186, 194, 222) hsl(227, 35%, 80%)
Subtext0 #a6adc8 rgb(166, 173, 200) hsl(228, 24%, 72%)
Overlay2 #9399b2 rgb(147, 153, 178) hsl(228, 17%, 64%)
Overlay1 #7f849c rgb(127, 132, 156) hsl(230, 13%, 55%)
Overlay0 #6c7086 rgb(108, 112, 134) hsl(231, 11%, 47%)
Surface2 #585b70 rgb(88, 91, 112) hsl(233, 12%, 39%)
Surface1 #45475a rgb(69, 71, 90) hsl(234, 13%, 31%)
Surface0 #313244 rgb(49, 50, 68) hsl(237, 16%, 23%)
Base #1e1e2e rgb(30, 30, 46) hsl(240, 21%, 15%)
Mantle #181825 rgb(24, 24, 37) hsl(240, 21%, 12%)
Crust #11111b rgb(17, 17, 27) hsl(240, 23%, 9%)
"},
);
}
}

125
rust/src/palette.rs Normal file
View file

@ -0,0 +1,125 @@
use crate::Colour;
/// Contains the colour options for a flavour of Catppuccin.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Palette {
pub rosewater: Colour,
pub flamingo: Colour,
pub pink: Colour,
pub mauve: Colour,
pub red: Colour,
pub maroon: Colour,
pub peach: Colour,
pub yellow: Colour,
pub green: Colour,
pub teal: Colour,
pub sky: Colour,
pub sapphire: Colour,
pub blue: Colour,
pub lavender: Colour,
pub text: Colour,
pub subtext1: Colour,
pub subtext0: Colour,
pub overlay2: Colour,
pub overlay1: Colour,
pub overlay0: Colour,
pub surface2: Colour,
pub surface1: Colour,
pub surface0: Colour,
pub base: Colour,
pub mantle: Colour,
pub crust: Colour,
}
impl Palette {
/// Returns an iterator over the colours in the flavour.
pub fn iter(&self) -> std::array::IntoIter<&Colour, 26> {
[
&self.rosewater,
&self.flamingo,
&self.pink,
&self.mauve,
&self.red,
&self.maroon,
&self.peach,
&self.yellow,
&self.green,
&self.teal,
&self.sky,
&self.sapphire,
&self.blue,
&self.lavender,
&self.text,
&self.subtext1,
&self.subtext0,
&self.overlay2,
&self.overlay1,
&self.overlay0,
&self.surface2,
&self.surface1,
&self.surface0,
&self.base,
&self.mantle,
&self.crust,
]
.into_iter()
}
}
/// Given a colour table taken from the main catppuccin readme, validate each
/// colour in the given flavour implementation.
/// Copy the table in question from the following URL:
/// https://github.com/catppuccin/catppuccin#-palettes
#[cfg(test)]
pub(crate) fn validate_colours(flavour: Palette, colours: &str) {
fn from_hex(hex: &str) -> Colour {
let hex = hex.strip_prefix('#').unwrap_or(hex);
let hex = i32::from_str_radix(hex, 16).expect(&format!(
"failed to parse hex string: {hex} (check paste format)"
));
Colour(
((hex & 0x00FF0000) >> 16) as u8,
((hex & 0x0000FF00) >> 8) as u8,
(hex & 0x000000FF) as u8,
)
}
let mut colours = colours.trim().split('\n').map(|line| -> Colour {
let hex = line.split('\t').collect::<Vec<_>>()[1].trim();
from_hex(hex)
});
let mut next_colour = || {
colours
.next()
.expect("ran out of colours, check paste format")
};
assert_eq!(next_colour(), flavour.rosewater);
assert_eq!(next_colour(), flavour.flamingo);
assert_eq!(next_colour(), flavour.pink);
assert_eq!(next_colour(), flavour.mauve);
assert_eq!(next_colour(), flavour.red);
assert_eq!(next_colour(), flavour.maroon);
assert_eq!(next_colour(), flavour.peach);
assert_eq!(next_colour(), flavour.yellow);
assert_eq!(next_colour(), flavour.green);
assert_eq!(next_colour(), flavour.teal);
assert_eq!(next_colour(), flavour.sky);
assert_eq!(next_colour(), flavour.sapphire);
assert_eq!(next_colour(), flavour.blue);
assert_eq!(next_colour(), flavour.lavender);
assert_eq!(next_colour(), flavour.text);
assert_eq!(next_colour(), flavour.subtext1);
assert_eq!(next_colour(), flavour.subtext0);
assert_eq!(next_colour(), flavour.overlay2);
assert_eq!(next_colour(), flavour.overlay1);
assert_eq!(next_colour(), flavour.overlay0);
assert_eq!(next_colour(), flavour.surface2);
assert_eq!(next_colour(), flavour.surface1);
assert_eq!(next_colour(), flavour.surface0);
assert_eq!(next_colour(), flavour.base);
assert_eq!(next_colour(), flavour.mantle);
assert_eq!(next_colour(), flavour.crust);
}