1 | //! Color types for used for being generic over the color |
2 | use crate::{BgColorDisplay, BgDynColorDisplay, FgColorDisplay, FgDynColorDisplay}; |
3 | use core::fmt; |
4 | |
5 | macro_rules! colors { |
6 | ($( |
7 | $color:ident $fg:literal $bg:literal |
8 | ),* $(,)?) => { |
9 | |
10 | pub(crate) mod ansi_colors { |
11 | use core::fmt; |
12 | |
13 | #[allow(unused_imports)] |
14 | use crate::OwoColorize; |
15 | |
16 | /// Available standard ANSI colors for use with [`OwoColorize::color`](OwoColorize::color) |
17 | /// or [`OwoColorize::on_color`](OwoColorize::on_color) |
18 | #[allow(missing_docs)] |
19 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
20 | pub enum AnsiColors { |
21 | $( |
22 | $color, |
23 | )* |
24 | } |
25 | |
26 | impl crate::DynColor for AnsiColors { |
27 | fn fmt_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
28 | let color = match self { |
29 | $( |
30 | AnsiColors::$color => concat!(" \x1b[" , stringify!($fg), "m" ), |
31 | )* |
32 | }; |
33 | |
34 | write!(f, "{}" , color) |
35 | } |
36 | |
37 | fn fmt_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
38 | let color = match self { |
39 | $( |
40 | AnsiColors::$color => concat!(" \x1b[" , stringify!($bg), "m" ), |
41 | )* |
42 | }; |
43 | |
44 | write!(f, "{}" , color) |
45 | } |
46 | |
47 | fn fmt_raw_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
48 | let color = match self { |
49 | $( |
50 | AnsiColors::$color => stringify!($fg), |
51 | )* |
52 | }; |
53 | |
54 | f.write_str(color) |
55 | } |
56 | |
57 | fn fmt_raw_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
58 | let color = match self { |
59 | $( |
60 | AnsiColors::$color => stringify!($bg), |
61 | )* |
62 | }; |
63 | |
64 | f.write_str(color) |
65 | } |
66 | |
67 | #[doc(hidden)] |
68 | fn get_dyncolors_fg(&self) -> crate::DynColors { |
69 | crate::DynColors::Ansi(*self) |
70 | } |
71 | |
72 | #[doc(hidden)] |
73 | fn get_dyncolors_bg(&self) -> crate::DynColors { |
74 | crate::DynColors::Ansi(*self) |
75 | } |
76 | } |
77 | } |
78 | |
79 | $( |
80 | /// A color for use with [`OwoColorize`](crate::OwoColorize)'s `fg` and `bg` methods. |
81 | pub struct $color; |
82 | |
83 | impl crate::Color for $color { |
84 | const ANSI_FG: &'static str = concat!(" \x1b[" , stringify!($fg), "m" ); |
85 | const ANSI_BG: &'static str = concat!(" \x1b[" , stringify!($bg), "m" ); |
86 | |
87 | const RAW_ANSI_FG: &'static str = stringify!($fg); |
88 | const RAW_ANSI_BG: &'static str = stringify!($bg); |
89 | |
90 | #[doc(hidden)] |
91 | type DynEquivelant = ansi_colors::AnsiColors; |
92 | |
93 | #[doc(hidden)] |
94 | const DYN_EQUIVELANT: Self::DynEquivelant = ansi_colors::AnsiColors::$color; |
95 | |
96 | #[doc(hidden)] |
97 | fn into_dyncolors() -> crate::DynColors { |
98 | crate::DynColors::Ansi(ansi_colors::AnsiColors::$color) |
99 | } |
100 | } |
101 | )* |
102 | |
103 | }; |
104 | } |
105 | |
106 | colors! { |
107 | Black 30 40, |
108 | Red 31 41, |
109 | Green 32 42, |
110 | Yellow 33 43, |
111 | Blue 34 44, |
112 | Magenta 35 45, |
113 | Cyan 36 46, |
114 | White 37 47, |
115 | Default 39 49, |
116 | |
117 | BrightBlack 90 100, |
118 | BrightRed 91 101, |
119 | BrightGreen 92 102, |
120 | BrightYellow 93 103, |
121 | BrightBlue 94 104, |
122 | BrightMagenta 95 105, |
123 | BrightCyan 96 106, |
124 | BrightWhite 97 107, |
125 | } |
126 | |
127 | macro_rules! impl_fmt_for { |
128 | ($($trait:path),* $(,)?) => { |
129 | $( |
130 | impl<'a, Color: crate::Color, T: $trait> $trait for FgColorDisplay<'a, Color, T> { |
131 | #[inline(always)] |
132 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
133 | f.write_str(Color::ANSI_FG)?; |
134 | <T as $trait>::fmt(&self.0, f)?; |
135 | f.write_str(" \x1b[39m" ) |
136 | } |
137 | } |
138 | |
139 | impl<'a, Color: crate::Color, T: $trait> $trait for BgColorDisplay<'a, Color, T> { |
140 | #[inline(always)] |
141 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
142 | f.write_str(Color::ANSI_BG)?; |
143 | <T as $trait>::fmt(&self.0, f)?; |
144 | f.write_str(" \x1b[49m" ) |
145 | } |
146 | } |
147 | )* |
148 | }; |
149 | } |
150 | |
151 | impl_fmt_for! { |
152 | fmt::Display, |
153 | fmt::Debug, |
154 | fmt::UpperHex, |
155 | fmt::LowerHex, |
156 | fmt::Binary, |
157 | fmt::UpperExp, |
158 | fmt::LowerExp, |
159 | fmt::Octal, |
160 | fmt::Pointer, |
161 | } |
162 | |
163 | macro_rules! impl_fmt_for_dyn { |
164 | ($($trait:path),* $(,)?) => { |
165 | $( |
166 | impl<'a, Color: crate::DynColor, T: $trait> $trait for FgDynColorDisplay<'a, Color, T> { |
167 | #[inline(always)] |
168 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
169 | (self.1).fmt_ansi_fg(f)?; |
170 | <T as $trait>::fmt(&self.0, f)?; |
171 | f.write_str(" \x1b[39m" ) |
172 | } |
173 | } |
174 | |
175 | impl<'a, Color: crate::DynColor, T: $trait> $trait for BgDynColorDisplay<'a, Color, T> { |
176 | #[inline(always)] |
177 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
178 | (self.1).fmt_ansi_bg(f)?; |
179 | <T as $trait>::fmt(&self.0, f)?; |
180 | f.write_str(" \x1b[49m" ) |
181 | } |
182 | } |
183 | )* |
184 | }; |
185 | } |
186 | |
187 | impl_fmt_for_dyn! { |
188 | fmt::Display, |
189 | fmt::Debug, |
190 | fmt::UpperHex, |
191 | fmt::LowerHex, |
192 | fmt::Binary, |
193 | fmt::UpperExp, |
194 | fmt::LowerExp, |
195 | fmt::Octal, |
196 | fmt::Pointer, |
197 | } |
198 | |
199 | /// CSS named colors. Not as widely supported as standard ANSI as it relies on 48bit color support. |
200 | /// |
201 | /// Reference: <https://www.w3schools.com/cssref/css_colors.asp> |
202 | /// Reference: <https://developer.mozilla.org/en-US/docs/Web/CSS/color_value> |
203 | pub mod css; |
204 | /// XTerm 256-bit colors. Not as widely supported as standard ANSI but contains 240 more colors. |
205 | pub mod xterm; |
206 | |
207 | mod custom; |
208 | |
209 | pub use custom::CustomColor; |
210 | |
211 | pub(crate) mod dynamic; |
212 | |