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;