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;
516