kxxt_owo_colors/lib.rs
1//! |**Quick Links**|[`OwoColorize`](OwoColorize)|[`Style`]|[`StyledList`]|[`github`](https://github.com/jam1garner/owo-colors)|
2//! |-|-|-|-|-|
3//!
4//! ---
5//!
6//! This crate provides [`OwoColorize`](OwoColorize), an extension trait for colorizing a
7//! given type.
8//!
9//! ## Example
10//!
11//! ```rust
12//! use owo_colors::OwoColorize;
13//!
14//! fn main() {
15//! // Foreground colors
16//! println!("My number is {:#x}!", 10.green());
17//! // Background colors
18//! println!("My number is not {}!", 4.on_red());
19//! }
20//! ```
21//!
22//! ## Generically color
23//!
24//! ```rust
25//! use owo_colors::OwoColorize;
26//! use owo_colors::colors::*;
27//!
28//! fn main() {
29//! // Generically color
30//! println!("My number might be {}!", 4.fg::<Black>().bg::<Yellow>());
31//! }
32//! ```
33//!
34//! ## Stylize
35//!
36//! ```rust
37//! use owo_colors::OwoColorize;
38//!
39//! println!("{}", "strikethrough".strikethrough());
40//! ```
41//!
42//! ## Only Style on Supported Terminals
43//!
44//! ```rust
45//! # #[cfg(feature = "supports-color")] {
46//! use owo_colors::{OwoColorize, Stream::Stdout};
47//!
48//! println!(
49//! "{}",
50//! "colored blue if a supported terminal"
51//! .if_supports_color(Stdout, |text| text.bright_blue())
52//! );
53//! # }
54//! ```
55//!
56//! Supports `NO_COLOR`/`FORCE_COLOR` environment variables, checks if it's a tty, checks
57//! if it's running in CI (and thus likely supports color), and checks which terminal is being
58//! used. (Note: requires `supports-colors` feature)
59//!
60//! ## Style Objects
61//!
62//! owo-colors also features the ability to create a [`Style`] object and use it to
63//! apply the same set of colors/effects to any number of things to display.
64//!
65//! ```rust
66//! use owo_colors::{OwoColorize, Style};
67//!
68//! let my_style = Style::new()
69//! .red()
70//! .on_white()
71//! .strikethrough();
72//!
73//! let text = "red text, white background, struck through";
74//! println!("{}", text.style(my_style));
75//! ```
76#![cfg_attr(all(not(test), not(feature = "global-colorized-control")), no_std)]
77#![cfg_attr(doc_cfg, feature(doc_cfg))]
78#![doc(html_logo_url = "https://jam1.re/img/rust_owo.svg")]
79#![warn(missing_docs)]
80
81pub mod colors;
82mod combo;
83#[cfg(feature = "global-colorized-control")]
84pub mod control;
85mod dyn_colors;
86mod dyn_styles;
87mod styled_list;
88pub mod styles;
89
90#[cfg(feature = "supports-colors")]
91mod overrides;
92
93#[cfg(feature = "supports-colors")]
94pub(crate) use overrides::OVERRIDE;
95
96use core::fmt;
97use core::marker::PhantomData;
98
99/// A trait for describing a type which can be used with [`FgColorDisplay`](FgColorDisplay) or
100/// [`BgColorDisplay`](BgColorDisplay)
101pub trait Color {
102 /// The ANSI format code for setting this color as the foreground
103 const ANSI_FG: &'static str;
104
105 /// The ANSI format code for setting this color as the background
106 const ANSI_BG: &'static str;
107
108 /// The raw ANSI format for settings this color as the foreground without the ANSI
109 /// delimiters ("\x1b" and "m")
110 const RAW_ANSI_FG: &'static str;
111
112 /// The raw ANSI format for settings this color as the background without the ANSI
113 /// delimiters ("\x1b" and "m")
114 const RAW_ANSI_BG: &'static str;
115
116 #[doc(hidden)]
117 type DynEquivalent: DynColor;
118
119 #[doc(hidden)]
120 const DYN_EQUIVALENT: Self::DynEquivalent;
121
122 #[doc(hidden)]
123 fn into_dyncolors() -> crate::DynColors;
124}
125
126/// A trait describing a runtime-configurable color which can displayed using [`FgDynColorDisplay`](FgDynColorDisplay)
127/// or [`BgDynColorDisplay`](BgDynColorDisplay). If your color will be known at compile time it
128/// is recommended you avoid this.
129pub trait DynColor {
130 /// A function to output a ANSI code to a formatter to set the foreground to this color
131 fn fmt_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
132 /// A function to output a ANSI code to a formatter to set the background to this color
133 fn fmt_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
134
135 /// A function to output a raw ANSI code to a formatter to set the foreground to this color,
136 /// but without including the ANSI delimiters.
137 fn fmt_raw_ansi_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
138
139 /// A function to output a raw ANSI code to a formatter to set the background to this color,
140 /// but without including the ANSI delimiters.
141 fn fmt_raw_ansi_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
142
143 #[doc(hidden)]
144 fn get_dyncolors_fg(&self) -> DynColors;
145 #[doc(hidden)]
146 fn get_dyncolors_bg(&self) -> DynColors;
147}
148
149/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
150/// with the addition of changing the foreground color. Recommended to be constructed using
151/// [`OwoColorize`](OwoColorize).
152#[repr(transparent)]
153pub struct FgColorDisplay<'a, C: Color, T>(&'a T, PhantomData<C>);
154
155/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
156/// with the addition of changing the background color. Recommended to be constructed using
157/// [`OwoColorize`](OwoColorize).
158#[repr(transparent)]
159pub struct BgColorDisplay<'a, C: Color, T>(&'a T, PhantomData<C>);
160
161/// Wrapper around a type which implements all the formatters the wrapped type does,
162/// with the addition of changing the foreground color. Is not recommended unless compile-time
163/// coloring is not an option.
164pub struct FgDynColorDisplay<'a, Color: DynColor, T>(&'a T, Color);
165
166/// Wrapper around a type which implements all the formatters the wrapped type does,
167/// with the addition of changing the background color. Is not recommended unless compile-time
168/// coloring is not an option.
169pub struct BgDynColorDisplay<'a, Color: DynColor, T>(&'a T, Color);
170
171macro_rules! style_methods {
172 ($(#[$meta:meta] $name:ident $ty:ident),* $(,)?) => {
173 $(
174 #[$meta]
175 #[must_use]
176 #[inline(always)]
177 fn $name(&self) -> styles::$ty<'_, Self> {
178 styles::$ty(self)
179 }
180 )*
181 };
182}
183
184const _: () = (); // workaround for syntax highlighting bug
185
186macro_rules! color_methods {
187 ($(
188 #[$fg_meta:meta] #[$bg_meta:meta] $color:ident $fg_method:ident $bg_method:ident
189 ),* $(,)?) => {
190 $(
191 #[$fg_meta]
192 #[must_use]
193 #[inline(always)]
194 fn $fg_method(&self) -> FgColorDisplay<'_, colors::$color, Self> {
195 FgColorDisplay(self, PhantomData)
196 }
197
198 #[$bg_meta]
199 #[must_use]
200 #[inline(always)]
201 fn $bg_method(&self) -> BgColorDisplay<'_, colors::$color, Self> {
202 BgColorDisplay(self, PhantomData)
203 }
204 )*
205 };
206}
207
208const _: () = (); // workaround for syntax highlighting bug
209
210/// Extension trait for colorizing a type which implements any std formatter
211/// ([`Display`](core::fmt::Display), [`Debug`](core::fmt::Debug), [`UpperHex`](core::fmt::UpperHex),
212/// etc.)
213///
214/// ## Example
215///
216/// ```rust
217/// use owo_colors::OwoColorize;
218///
219/// println!("My number is {:#x}!", 10.green());
220/// println!("My number is not {}!", 4.on_red());
221/// ```
222///
223/// ## How to decide which method to use
224///
225/// **Do you have a specific color you want to use?**
226///
227/// Use the specific color's method, such as [`blue`](OwoColorize::blue) or
228/// [`on_green`](OwoColorize::on_green).
229///
230///
231/// **Do you want your colors configurable via generics?**
232///
233/// Use [`fg`](OwoColorize::fg) and [`bg`](OwoColorize::bg) to make it compile-time configurable.
234///
235///
236/// **Do you need to pick a color at runtime?**
237///
238/// Use the [`color`](OwoColorize::color), [`on_color`](OwoColorize::on_color),
239/// [`truecolor`](OwoColorize::truecolor) or [`on_truecolor`](OwoColorize::on_truecolor).
240///
241/// **Do you need some other text modifier?**
242///
243/// * [`bold`](OwoColorize::bold)
244/// * [`dimmed`](OwoColorize::dimmed)
245/// * [`italic`](OwoColorize::italic)
246/// * [`underline`](OwoColorize::underline)
247/// * [`blink`](OwoColorize::blink)
248/// * [`blink_fast`](OwoColorize::blink_fast)
249/// * [`reversed`](OwoColorize::reversed)
250/// * [`hidden`](OwoColorize::hidden)
251/// * [`strikethrough`](OwoColorize::strikethrough)
252///
253/// **Do you want it to only display colors if it's a terminal?**
254///
255/// 1. Enable the `supports-colors` feature
256/// 2. Colorize inside [`if_supports_color`](OwoColorize::if_supports_color)
257///
258/// **Do you need to store a set of colors/effects to apply to multiple things?**
259///
260/// Use [`style`](OwoColorize::style) to apply a [`Style`]
261///
262pub trait OwoColorize: Sized {
263 /// Set the foreground color generically
264 ///
265 /// ```rust
266 /// use owo_colors::{OwoColorize, colors::*};
267 ///
268 /// println!("{}", "red foreground".fg::<Red>());
269 /// ```
270 #[must_use]
271 #[inline(always)]
272 fn fg<C: Color>(&self) -> FgColorDisplay<'_, C, Self> {
273 FgColorDisplay(self, PhantomData)
274 }
275
276 /// Set the background color generically.
277 ///
278 /// ```rust
279 /// use owo_colors::{OwoColorize, colors::*};
280 ///
281 /// println!("{}", "black background".bg::<Black>());
282 /// ```
283 #[must_use]
284 #[inline(always)]
285 fn bg<C: Color>(&self) -> BgColorDisplay<'_, C, Self> {
286 BgColorDisplay(self, PhantomData)
287 }
288
289 color_methods! {
290 /// Change the foreground color to black
291 /// Change the background color to black
292 Black black on_black,
293 /// Change the foreground color to red
294 /// Change the background color to red
295 Red red on_red,
296 /// Change the foreground color to green
297 /// Change the background color to green
298 Green green on_green,
299 /// Change the foreground color to yellow
300 /// Change the background color to yellow
301 Yellow yellow on_yellow,
302 /// Change the foreground color to blue
303 /// Change the background color to blue
304 Blue blue on_blue,
305 /// Change the foreground color to magenta
306 /// Change the background color to magenta
307 Magenta magenta on_magenta,
308 /// Change the foreground color to purple
309 /// Change the background color to purple
310 Magenta purple on_purple,
311 /// Change the foreground color to cyan
312 /// Change the background color to cyan
313 Cyan cyan on_cyan,
314 /// Change the foreground color to white
315 /// Change the background color to white
316 White white on_white,
317
318 /// Change the foreground color to the terminal default
319 /// Change the background color to the terminal default
320 Default default_color on_default_color,
321
322 /// Change the foreground color to bright black
323 /// Change the background color to bright black
324 BrightBlack bright_black on_bright_black,
325 /// Change the foreground color to bright red
326 /// Change the background color to bright red
327 BrightRed bright_red on_bright_red,
328 /// Change the foreground color to bright green
329 /// Change the background color to bright green
330 BrightGreen bright_green on_bright_green,
331 /// Change the foreground color to bright yellow
332 /// Change the background color to bright yellow
333 BrightYellow bright_yellow on_bright_yellow,
334 /// Change the foreground color to bright blue
335 /// Change the background color to bright blue
336 BrightBlue bright_blue on_bright_blue,
337 /// Change the foreground color to bright magenta
338 /// Change the background color to bright magenta
339 BrightMagenta bright_magenta on_bright_magenta,
340 /// Change the foreground color to bright purple
341 /// Change the background color to bright purple
342 BrightMagenta bright_purple on_bright_purple,
343 /// Change the foreground color to bright cyan
344 /// Change the background color to bright cyan
345 BrightCyan bright_cyan on_bright_cyan,
346 /// Change the foreground color to bright white
347 /// Change the background color to bright white
348 BrightWhite bright_white on_bright_white,
349 }
350
351 style_methods! {
352 /// Make the text bold
353 bold BoldDisplay,
354 /// Make the text dim
355 dimmed DimDisplay,
356 /// Make the text italicized
357 italic ItalicDisplay,
358 /// Make the text underlined
359 underline UnderlineDisplay,
360 /// Make the text blink
361 blink BlinkDisplay,
362 /// Make the text blink (but fast!)
363 blink_fast BlinkFastDisplay,
364 /// Swap the foreground and background colors
365 reversed ReversedDisplay,
366 /// Hide the text
367 hidden HiddenDisplay,
368 /// Cross out the text
369 strikethrough StrikeThroughDisplay,
370 }
371
372 /// Set the foreground color at runtime. Only use if you do not know which color will be used at
373 /// compile-time. If the color is constant, use either [`OwoColorize::fg`](OwoColorize::fg) or
374 /// a color-specific method, such as [`OwoColorize::green`](OwoColorize::green),
375 ///
376 /// ```rust
377 /// use owo_colors::{OwoColorize, AnsiColors};
378 ///
379 /// println!("{}", "green".color(AnsiColors::Green));
380 /// ```
381 #[must_use]
382 #[inline(always)]
383 fn color<Color: DynColor>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self> {
384 FgDynColorDisplay(self, color)
385 }
386
387 /// Set the background color at runtime. Only use if you do not know what color to use at
388 /// compile-time. If the color is constant, use either [`OwoColorize::bg`](OwoColorize::bg) or
389 /// a color-specific method, such as [`OwoColorize::on_yellow`](OwoColorize::on_yellow),
390 ///
391 /// ```rust
392 /// use owo_colors::{OwoColorize, AnsiColors};
393 ///
394 /// println!("{}", "yellow background".on_color(AnsiColors::BrightYellow));
395 /// ```
396 #[must_use]
397 #[inline(always)]
398 fn on_color<Color: DynColor>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self> {
399 BgDynColorDisplay(self, color)
400 }
401
402 /// Set the foreground color to a specific RGB value.
403 #[must_use]
404 fn fg_rgb<const R: u8, const G: u8, const B: u8>(
405 &self,
406 ) -> FgColorDisplay<'_, colors::CustomColor<R, G, B>, Self> {
407 FgColorDisplay(self, PhantomData)
408 }
409
410 /// Set the background color to a specific RGB value.
411 #[must_use]
412 fn bg_rgb<const R: u8, const G: u8, const B: u8>(
413 &self,
414 ) -> BgColorDisplay<'_, colors::CustomColor<R, G, B>, Self> {
415 BgColorDisplay(self, PhantomData)
416 }
417
418 /// Sets the foreground color to an RGB value.
419 #[must_use]
420 #[inline(always)]
421 fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self> {
422 FgDynColorDisplay(self, Rgb(r, g, b))
423 }
424
425 /// Sets the background color to an RGB value.
426 #[must_use]
427 #[inline(always)]
428 fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self> {
429 BgDynColorDisplay(self, Rgb(r, g, b))
430 }
431
432 /// Apply a runtime-determined style
433 #[must_use]
434 fn style(&self, style: Style) -> Styled<&Self> {
435 style.style(self)
436 }
437
438 /// Apply a given transformation function to all formatters if the given stream
439 /// supports at least basic ANSI colors, allowing you to conditionally apply
440 /// given styles/colors.
441 ///
442 /// Requires the `supports-colors` feature.
443 ///
444 /// ```rust
445 /// use owo_colors::{Stream, OwoColorize};
446 ///
447 /// println!(
448 /// "{}",
449 /// "woah! error! if this terminal supports colors, it's blue"
450 /// .if_supports_color(Stream::Stdout, |text| text.bright_blue())
451 /// );
452 /// ```
453 ///
454 /// This function also accepts `supports_color` version 2's `Stream`, and also the deprecated
455 /// `supports_color` version 1's `Stream`.
456 ///
457 /// ```rust
458 /// use owo_colors::OwoColorize;
459 /// #[cfg(feature = "supports-colors")]
460 /// use supports_color::Stream;
461 ///
462 /// println!(
463 /// "{}",
464 /// "woah! error! if this terminal supports colors, it's blue"
465 /// .if_supports_color(Stream::Stdout, |text| text.bright_blue())
466 /// );
467 #[must_use]
468 #[cfg(feature = "supports-colors")]
469 fn if_supports_color<'a, Out, ApplyFn>(
470 &'a self,
471 stream: impl Into<Stream>,
472 apply: ApplyFn,
473 ) -> SupportsColorsDisplay<'a, Self, Out, ApplyFn>
474 where
475 ApplyFn: Fn(&'a Self) -> Out,
476 {
477 SupportsColorsDisplay(self, apply, stream.into())
478 }
479}
480
481#[cfg(feature = "supports-colors")]
482mod supports_colors;
483
484#[cfg(feature = "supports-colors")]
485pub use {
486 overrides::{set_override, unset_override, with_override},
487 supports_colors::SupportsColorsDisplay,
488};
489
490#[cfg(feature = "supports-colors")]
491#[doc(no_inline)]
492pub use supports_colors::Stream;
493
494pub use colors::{
495 ansi_colors::AnsiColors, css::dynamic::CssColors, dynamic::Rgb, xterm::dynamic::XtermColors,
496};
497
498// TODO: figure out some wait to only implement for fmt::Display | fmt::Debug | ...
499impl<D: Sized> OwoColorize for D {}
500
501pub use {combo::ComboColorDisplay, dyn_colors::*, dyn_styles::*};
502
503/// Module for drop-in [`colored`](https://docs.rs/colored) support to aid in porting code from
504/// [`colored`](https://docs.rs/colored) to owo-colors.
505///
506/// Just replace:
507///
508/// ```rust
509/// # mod colored {}
510/// use colored::*;
511/// ```
512///
513/// with
514///
515/// ```rust
516/// use owo_colors::colored::*;
517/// ```
518pub mod colored {
519 pub use crate::AnsiColors as Color;
520 pub use crate::OwoColorize;
521
522 /// A couple of functions to enable and disable coloring similarly to `colored`
523 #[cfg(feature = "supports-colors")]
524 pub mod control {
525 pub use crate::{set_override, unset_override};
526 }
527}
528
529pub use styled_list::StyledList;
530#[cfg(feature = "alloc")]
531pub use styled_list::StyledVec;
532
533#[cfg(test)]
534mod tests;