owo_colors/
lib.rs

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