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