base16_palettes/
lib.rs

1//! This crate contains representations of all of the major
2//! [Base16](https://github.com/chriskempson/base16-schemes-source?tab=readme-ov-file) themes.
3//! Color representation is split into two parts, the universal base 16 color and the palette. A
4//! color is represented by a [`Base16Color`], which is then rendered into either a RGB tuple of
5//! `u8`s or into a hex string.
6//!
7//! Each collection of themes is gated by a feature flag to minimize the number of palettes you
8//! have to compile.
9//!
10//! Lastly, this crate is fully `no_std`.
11
12#![no_std]
13#![warn(rust_2018_idioms)]
14#![deny(
15    missing_debug_implementations,
16    rustdoc::broken_intra_doc_links,
17    unreachable_pub,
18    unreachable_patterns,
19    unused,
20    unused_results,
21    unused_qualifications,
22    while_true,
23    trivial_casts,
24    trivial_bounds,
25    trivial_numeric_casts,
26    unconditional_panic,
27    clippy::all
28)]
29
30pub mod palettes;
31
32use enum_dispatch::enum_dispatch;
33use palettes::*;
34
35/// A palette is used to render a [`Base16Color`] into RBG values or a hex string.
36#[enum_dispatch(Base16Palette)]
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum Palette {
39    DefaultPalette,
40    #[cfg(feature = "apprentice")]
41    ApprenticePalette,
42    #[cfg(feature = "atelier")]
43    AtelierPalette,
44    #[cfg(feature = "atlas")]
45    AtlasPalette,
46    #[cfg(feature = "black_metal")]
47    BlackMetalPalette,
48    #[cfg(feature = "brogrammer")]
49    BrogrammerPalette,
50    #[cfg(feature = "brush_trees")]
51    BrushTreesPalette,
52    #[cfg(feature = "circus")]
53    CircusPalette,
54    #[cfg(feature = "classic")]
55    ClassicPalette,
56    #[cfg(feature = "codeschool")]
57    CodeschoolPalette,
58    #[cfg(feature = "colors")]
59    ColorsPalette,
60    #[cfg(feature = "cupertino")]
61    CupertinoPalette,
62    #[cfg(feature = "danqing")]
63    DanqingPalette,
64    #[cfg(feature = "darcula")]
65    DarculaPalette,
66    #[cfg(feature = "darkviolet")]
67    DarkvioletPalette,
68    #[cfg(feature = "dracula")]
69    DraculaPalette,
70    #[cfg(feature = "equilibrium")]
71    EquilibriumPalette,
72    #[cfg(feature = "espresso")]
73    EspressoPalette,
74    #[cfg(feature = "eva")]
75    EvaPalette,
76    #[cfg(feature = "framer")]
77    FramerPalette,
78    #[cfg(feature = "fruit_soda")]
79    FruitSodaPalette,
80    #[cfg(feature = "gigavolt")]
81    GigavoltPalette,
82    #[cfg(feature = "github")]
83    GithubPalette,
84    #[cfg(feature = "gruvbox")]
85    GruvboxPalette,
86    #[cfg(feature = "hardcore")]
87    HardcorePalette,
88    #[cfg(feature = "heetch")]
89    HeetchPalette,
90    #[cfg(feature = "helios")]
91    HeliosPalette,
92    #[cfg(feature = "horizon")]
93    HorizonPalette,
94    #[cfg(feature = "humanoid")]
95    HumanoidPalette,
96    #[cfg(feature = "icy")]
97    IcyPalette,
98    #[cfg(feature = "kimber")]
99    KimberPalette,
100    #[cfg(feature = "materia")]
101    MateriaPalette,
102    #[cfg(feature = "material")]
103    MaterialPalette,
104    #[cfg(feature = "material_vivid")]
105    MaterialVividPalette,
106    #[cfg(feature = "mellow")]
107    MellowPalette,
108    #[cfg(feature = "mexico_light")]
109    MexicoLightPalette,
110    #[cfg(feature = "nebula")]
111    NebulaPalette,
112    #[cfg(feature = "nord")]
113    NordPalette,
114    #[cfg(feature = "nova")]
115    NovaPalette,
116    #[cfg(feature = "one_light")]
117    OneLightPalette,
118    #[cfg(feature = "onedark")]
119    OnedarkPalette,
120    #[cfg(feature = "outrun")]
121    OutrunPalette,
122    #[cfg(feature = "papercolor")]
123    PapercolorPalette,
124    #[cfg(feature = "pasque")]
125    PasquePalette,
126    #[cfg(feature = "pinky")]
127    PinkyPalette,
128    #[cfg(feature = "porple")]
129    PorplePalette,
130    #[cfg(feature = "purpledream")]
131    PurpleDreamPalette,
132    #[cfg(feature = "qualia")]
133    QualiaPalette,
134    #[cfg(feature = "rebecca")]
135    RebeccaPalette,
136    #[cfg(feature = "rose_pine")]
137    RosePinePalette,
138    #[cfg(feature = "sagelight")]
139    SagelightPalette,
140    #[cfg(feature = "sakura")]
141    SakuraPalette,
142    #[cfg(feature = "sandcastle")]
143    SandcastlePalette,
144    #[cfg(feature = "shades_of_purple")]
145    ShadesOfPurplePalette,
146    #[cfg(feature = "silk")]
147    SilkPalette,
148    #[cfg(feature = "snazzy")]
149    SnazzyPalette,
150    #[cfg(feature = "solarflare")]
151    SolarflarePalette,
152    #[cfg(feature = "summercamp")]
153    SummercampPalette,
154    #[cfg(feature = "summerfruit")]
155    SummerfruitPalette,
156    #[cfg(feature = "synth_midnight")]
157    SynthMidnightPalette,
158    #[cfg(feature = "tender")]
159    TenderPalette,
160    #[cfg(feature = "twilight")]
161    TwilightPalette,
162    #[cfg(feature = "unikitty")]
163    UnikittyPalette,
164    #[cfg(feature = "vice")]
165    VicePalette,
166    #[cfg(feature = "windows")]
167    WindowsPalette,
168    #[cfg(feature = "woodland")]
169    WoodlandPalette,
170    #[cfg(feature = "xcode_dusk")]
171    XcodeDuskPalette,
172    #[cfg(feature = "zenburn")]
173    ZenburnPalette,
174}
175
176impl Default for Palette {
177    fn default() -> Self {
178        Self::DefaultPalette(DefaultPalette::default())
179    }
180}
181
182/// The universal representation of a Base16 color palette.
183#[derive(Debug, Clone, Copy, PartialEq, Eq)]
184pub enum Base16Color {
185    Shade(Base16Shade),
186    Accent(Base16Accent),
187}
188
189/// Every Base16 color palette contains 8 "shades". These are split between 4 "dark" and 4 "light"
190/// shades.
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub enum Base16Shade {
193    Dark(Shade),
194    Light(Shade),
195}
196
197/// Base16 shades are split into two 4-value gradients.
198#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum Shade {
200    Darkest,
201    Darker,
202    Lighter,
203    Lightest,
204}
205
206/// Every Base16 color palette contains 8 "accents".
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum Base16Accent {
209    Accent00,
210    Accent01,
211    Accent02,
212    Accent03,
213    Accent04,
214    Accent05,
215    Accent06,
216    Accent07,
217}
218
219impl Base16Color {
220    pub const fn index(self) -> u8 {
221        match self {
222            Base16Color::Shade(Base16Shade::Dark(Shade::Darkest)) => 0,
223            Base16Color::Shade(Base16Shade::Dark(Shade::Darker)) => 1,
224            Base16Color::Shade(Base16Shade::Dark(Shade::Lighter)) => 2,
225            Base16Color::Shade(Base16Shade::Dark(Shade::Lightest)) => 3,
226            Base16Color::Shade(Base16Shade::Light(Shade::Darkest)) => 4,
227            Base16Color::Shade(Base16Shade::Light(Shade::Darker)) => 5,
228            Base16Color::Shade(Base16Shade::Light(Shade::Lighter)) => 6,
229            Base16Color::Shade(Base16Shade::Light(Shade::Lightest)) => 7,
230            Base16Color::Accent(Base16Accent::Accent00) => 8,
231            Base16Color::Accent(Base16Accent::Accent01) => 9,
232            Base16Color::Accent(Base16Accent::Accent02) => 10,
233            Base16Color::Accent(Base16Accent::Accent03) => 11,
234            Base16Color::Accent(Base16Accent::Accent04) => 12,
235            Base16Color::Accent(Base16Accent::Accent05) => 13,
236            Base16Color::Accent(Base16Accent::Accent06) => 14,
237            Base16Color::Accent(Base16Accent::Accent07) => 15,
238        }
239    }
240
241    pub const fn from_index(i: u8) -> Self {
242        match i {
243            0 => Base16Color::Shade(Base16Shade::Dark(Shade::Darkest)),
244            1 => Base16Color::Shade(Base16Shade::Dark(Shade::Darker)),
245            2 => Base16Color::Shade(Base16Shade::Dark(Shade::Lighter)),
246            3 => Base16Color::Shade(Base16Shade::Dark(Shade::Lightest)),
247            4 => Base16Color::Shade(Base16Shade::Light(Shade::Darkest)),
248            5 => Base16Color::Shade(Base16Shade::Light(Shade::Darker)),
249            6 => Base16Color::Shade(Base16Shade::Light(Shade::Lighter)),
250            7 => Base16Color::Shade(Base16Shade::Light(Shade::Lightest)),
251            8 => Base16Color::Accent(Base16Accent::Accent00),
252            9 => Base16Color::Accent(Base16Accent::Accent01),
253            10 => Base16Color::Accent(Base16Accent::Accent02),
254            11 => Base16Color::Accent(Base16Accent::Accent03),
255            12 => Base16Color::Accent(Base16Accent::Accent04),
256            13 => Base16Color::Accent(Base16Accent::Accent05),
257            14 => Base16Color::Accent(Base16Accent::Accent06),
258            15 => Base16Color::Accent(Base16Accent::Accent07),
259            // Maybe use a default value?
260            _ => panic!("Unknown color code!"),
261        }
262    }
263}
264
265#[enum_dispatch]
266pub trait Base16Palette {
267    fn to_rgb(&self, color: Base16Color) -> (u8, u8, u8);
268    fn to_hex_str(&self, color: Base16Color) -> &'static str;
269}
270
271impl Base16Color {
272    pub const fn default_fg() -> Self {
273        Self::light_3()
274    }
275
276    pub const fn default_bg() -> Self {
277        Self::dark_2()
278    }
279
280    pub const fn dark_1() -> Self {
281        Self::Shade(Base16Shade::Dark(Shade::Darkest))
282    }
283
284    pub const fn dark_2() -> Self {
285        Self::Shade(Base16Shade::Dark(Shade::Darker))
286    }
287
288    pub const fn dark_3() -> Self {
289        Self::Shade(Base16Shade::Dark(Shade::Lighter))
290    }
291
292    pub const fn dark_4() -> Self {
293        Self::Shade(Base16Shade::Dark(Shade::Lightest))
294    }
295
296    pub const fn light_1() -> Self {
297        Self::Shade(Base16Shade::Light(Shade::Darkest))
298    }
299
300    pub const fn light_2() -> Self {
301        Self::Shade(Base16Shade::Light(Shade::Darker))
302    }
303
304    pub const fn light_3() -> Self {
305        Self::Shade(Base16Shade::Light(Shade::Lighter))
306    }
307
308    pub const fn light_4() -> Self {
309        Self::Shade(Base16Shade::Light(Shade::Lightest))
310    }
311}