1 | #[allow (unused_imports)] |
2 | use crate::{ |
3 | AnsiColors, BgDynColorDisplay, CssColors, DynColor, FgDynColorDisplay, Rgb, XtermColors, |
4 | }; |
5 | use core::fmt; |
6 | |
7 | /// An enum describing runtime-configurable colors which can be displayed using [`FgDynColorDisplay`](FgDynColorDisplay) |
8 | /// or [`BgDynColorDisplay`](BgDynColorDisplay), allowing for multiple types of colors to be used |
9 | /// at runtime. |
10 | #[allow (missing_docs)] |
11 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
12 | pub enum DynColors { |
13 | Ansi(AnsiColors), |
14 | Css(CssColors), |
15 | Xterm(XtermColors), |
16 | Rgb(u8, u8, u8), |
17 | } |
18 | |
19 | impl DynColor for DynColors { |
20 | fn fmt_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
21 | match self { |
22 | DynColors::Ansi(ansi) => ansi.fmt_ansi_fg(f), |
23 | DynColors::Css(css) => css.fmt_ansi_fg(f), |
24 | DynColors::Xterm(xterm) => xterm.fmt_ansi_fg(f), |
25 | &DynColors::Rgb(r, g, b) => Rgb(r, g, b).fmt_ansi_fg(f), |
26 | } |
27 | } |
28 | |
29 | fn fmt_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
30 | match self { |
31 | DynColors::Ansi(ansi) => ansi.fmt_ansi_bg(f), |
32 | DynColors::Css(css) => css.fmt_ansi_bg(f), |
33 | DynColors::Xterm(xterm) => xterm.fmt_ansi_bg(f), |
34 | &DynColors::Rgb(r, g, b) => Rgb(r, g, b).fmt_ansi_bg(f), |
35 | } |
36 | } |
37 | |
38 | fn fmt_raw_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
39 | match self { |
40 | DynColors::Ansi(ansi) => ansi.fmt_raw_ansi_fg(f), |
41 | DynColors::Css(css) => css.fmt_raw_ansi_fg(f), |
42 | DynColors::Xterm(xterm) => xterm.fmt_raw_ansi_fg(f), |
43 | &DynColors::Rgb(r, g, b) => Rgb(r, g, b).fmt_raw_ansi_fg(f), |
44 | } |
45 | } |
46 | |
47 | fn fmt_raw_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
48 | match self { |
49 | DynColors::Ansi(ansi) => ansi.fmt_raw_ansi_bg(f), |
50 | DynColors::Css(css) => css.fmt_raw_ansi_bg(f), |
51 | DynColors::Xterm(xterm) => xterm.fmt_raw_ansi_bg(f), |
52 | &DynColors::Rgb(r, g, b) => Rgb(r, g, b).fmt_raw_ansi_bg(f), |
53 | } |
54 | } |
55 | |
56 | #[doc (hidden)] |
57 | fn get_dyncolors_fg(&self) -> crate::DynColors { |
58 | *self |
59 | } |
60 | |
61 | #[doc (hidden)] |
62 | fn get_dyncolors_bg(&self) -> crate::DynColors { |
63 | *self |
64 | } |
65 | } |
66 | |
67 | /// An error for when the color can not be parsed from a string at runtime |
68 | #[derive (Debug)] |
69 | pub struct ParseColorError; |
70 | |
71 | impl core::str::FromStr for DynColors { |
72 | type Err = ParseColorError; |
73 | |
74 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
75 | if s.chars().next().ok_or(ParseColorError)? == '#' { |
76 | match s.len() { |
77 | 4 => { |
78 | // TODO |
79 | Err(ParseColorError) |
80 | } |
81 | 7 => Ok(Self::Rgb( |
82 | u8::from_str_radix(&s[1..3], 16).or(Err(ParseColorError))?, |
83 | u8::from_str_radix(&s[3..5], 16).or(Err(ParseColorError))?, |
84 | u8::from_str_radix(&s[5..7], 16).or(Err(ParseColorError))?, |
85 | )), |
86 | _ => Err(ParseColorError), |
87 | } |
88 | } else { |
89 | let ansi = match s { |
90 | "black" => AnsiColors::Black, |
91 | "red" => AnsiColors::Red, |
92 | "green" => AnsiColors::Green, |
93 | "yellow" => AnsiColors::Yellow, |
94 | "blue" => AnsiColors::Blue, |
95 | "magenta" => AnsiColors::Magenta, |
96 | "purple" => AnsiColors::Magenta, |
97 | "cyan" => AnsiColors::Cyan, |
98 | "white" => AnsiColors::White, |
99 | "bright black" => AnsiColors::BrightBlack, |
100 | "bright red" => AnsiColors::BrightRed, |
101 | "bright green" => AnsiColors::BrightGreen, |
102 | "bright yellow" => AnsiColors::BrightYellow, |
103 | "bright blue" => AnsiColors::BrightBlue, |
104 | "bright magenta" => AnsiColors::BrightMagenta, |
105 | "bright cyan" => AnsiColors::BrightCyan, |
106 | "bright white" => AnsiColors::BrightWhite, |
107 | _ => return Err(ParseColorError), |
108 | }; |
109 | |
110 | Ok(Self::Ansi(ansi)) |
111 | } |
112 | } |
113 | } |
114 | |