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_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 #[rust_analyzer::completions(ignore_flyimport)]
179 fn $name(&self) -> styles::$ty<'_, Self> {
180 styles::$ty(self)
181 }
182 )*
183 };
184}
185
186const _: () = (); // workaround for syntax highlighting bug
187
188macro_rules! color_methods {
189 ($(
190 #[$fg_meta:meta] #[$bg_meta:meta] $color:ident $fg_method:ident $bg_method:ident
191 ),* $(,)?) => {
192 $(
193 #[$fg_meta]
194 #[must_use]
195 #[inline(always)]
196 #[rust_analyzer::completions(ignore_flyimport)]
197 fn $fg_method(&self) -> FgColorDisplay<'_, colors::$color, Self> {
198 FgColorDisplay(self, PhantomData)
199 }
200
201 #[$bg_meta]
202 #[must_use]
203 #[inline(always)]
204 #[rust_analyzer::completions(ignore_flyimport)]
205 fn $bg_method(&self) -> BgColorDisplay<'_, colors::$color, Self> {
206 BgColorDisplay(self, PhantomData)
207 }
208 )*
209 };
210}
211
212const _: () = (); // workaround for syntax highlighting bug
213
214/// Extension trait for colorizing a type which implements any std formatter
215/// ([`Display`](core::fmt::Display), [`Debug`](core::fmt::Debug), [`UpperHex`](core::fmt::UpperHex),
216/// etc.)
217///
218/// ## Example
219///
220/// ```rust
221/// use owo_colors::OwoColorize;
222///
223/// println!("My number is {:#x}!", 10.green());
224/// println!("My number is not {}!", 4.on_red());
225/// ```
226///
227/// ## How to decide which method to use
228///
229/// **Do you have a specific color you want to use?**
230///
231/// Use the specific color's method, such as [`blue`](OwoColorize::blue) or
232/// [`on_green`](OwoColorize::on_green).
233///
234///
235/// **Do you want your colors configurable via generics?**
236///
237/// Use [`fg`](OwoColorize::fg) and [`bg`](OwoColorize::bg) to make it compile-time configurable.
238///
239///
240/// **Do you need to pick a color at runtime?**
241///
242/// Use the [`color`](OwoColorize::color), [`on_color`](OwoColorize::on_color),
243/// [`truecolor`](OwoColorize::truecolor) or [`on_truecolor`](OwoColorize::on_truecolor).
244///
245/// **Do you need some other text modifier?**
246///
247/// * [`bold`](OwoColorize::bold)
248/// * [`dimmed`](OwoColorize::dimmed)
249/// * [`italic`](OwoColorize::italic)
250/// * [`underline`](OwoColorize::underline)
251/// * [`blink`](OwoColorize::blink)
252/// * [`blink_fast`](OwoColorize::blink_fast)
253/// * [`reversed`](OwoColorize::reversed)
254/// * [`hidden`](OwoColorize::hidden)
255/// * [`strikethrough`](OwoColorize::strikethrough)
256///
257/// **Do you want it to only display colors if it's a terminal?**
258///
259/// 1. Enable the `supports-colors` feature
260/// 2. Colorize inside [`if_supports_color`](OwoColorize::if_supports_color)
261///
262/// **Do you need to store a set of colors/effects to apply to multiple things?**
263///
264/// Use [`style`](OwoColorize::style) to apply a [`Style`].
265#[rust_analyzer::completions(ignore_flyimport_methods)]
266pub trait OwoColorize: Sized {
267 // Implementation note: even though the "OwoColorize: Sized" condition _can_ be dropped, we
268 // currently don't do that for API compatibility reasons.
269 //
270 // For example, currently, calling `OwoColorize::fg` on a &str results in a type signature of
271 // `FgColorDisplay<'_, C, &str>`. Dropping the "OwoColorize: Sized" condition would result in a
272 // type signature of `FgColorDisplay<'_, C, str>`, which is a visible change.
273 //
274 // If we ever do a breaking change to owo-colors in the future, this would be a good candidate.
275
276 /// Set the foreground color generically
277 ///
278 /// ```rust
279 /// use owo_colors::{OwoColorize, colors::*};
280 ///
281 /// println!("{}", "red foreground".fg::<Red>());
282 /// ```
283 #[must_use]
284 #[inline(always)]
285 #[rust_analyzer::completions(ignore_flyimport)]
286 fn fg<C: Color>(&self) -> FgColorDisplay<'_, C, Self> {
287 FgColorDisplay(self, PhantomData)
288 }
289
290 /// Set the background color generically.
291 ///
292 /// ```rust
293 /// use owo_colors::{OwoColorize, colors::*};
294 ///
295 /// println!("{}", "black background".bg::<Black>());
296 /// ```
297 #[must_use]
298 #[inline(always)]
299 #[rust_analyzer::completions(ignore_flyimport)]
300 fn bg<C: Color>(&self) -> BgColorDisplay<'_, C, Self> {
301 BgColorDisplay(self, PhantomData)
302 }
303
304 color_methods! {
305 /// Change the foreground color to black
306 /// Change the background color to black
307 Black black on_black,
308 /// Change the foreground color to red
309 /// Change the background color to red
310 Red red on_red,
311 /// Change the foreground color to green
312 /// Change the background color to green
313 Green green on_green,
314 /// Change the foreground color to yellow
315 /// Change the background color to yellow
316 Yellow yellow on_yellow,
317 /// Change the foreground color to blue
318 /// Change the background color to blue
319 Blue blue on_blue,
320 /// Change the foreground color to magenta
321 /// Change the background color to magenta
322 Magenta magenta on_magenta,
323 /// Change the foreground color to purple
324 /// Change the background color to purple
325 Magenta purple on_purple,
326 /// Change the foreground color to cyan
327 /// Change the background color to cyan
328 Cyan cyan on_cyan,
329 /// Change the foreground color to white
330 /// Change the background color to white
331 White white on_white,
332
333 /// Change the foreground color to the terminal default
334 /// Change the background color to the terminal default
335 Default default_color on_default_color,
336
337 /// Change the foreground color to bright black
338 /// Change the background color to bright black
339 BrightBlack bright_black on_bright_black,
340 /// Change the foreground color to bright red
341 /// Change the background color to bright red
342 BrightRed bright_red on_bright_red,
343 /// Change the foreground color to bright green
344 /// Change the background color to bright green
345 BrightGreen bright_green on_bright_green,
346 /// Change the foreground color to bright yellow
347 /// Change the background color to bright yellow
348 BrightYellow bright_yellow on_bright_yellow,
349 /// Change the foreground color to bright blue
350 /// Change the background color to bright blue
351 BrightBlue bright_blue on_bright_blue,
352 /// Change the foreground color to bright magenta
353 /// Change the background color to bright magenta
354 BrightMagenta bright_magenta on_bright_magenta,
355 /// Change the foreground color to bright purple
356 /// Change the background color to bright purple
357 BrightMagenta bright_purple on_bright_purple,
358 /// Change the foreground color to bright cyan
359 /// Change the background color to bright cyan
360 BrightCyan bright_cyan on_bright_cyan,
361 /// Change the foreground color to bright white
362 /// Change the background color to bright white
363 BrightWhite bright_white on_bright_white,
364 }
365
366 style_methods! {
367 /// Make the text bold
368 bold BoldDisplay,
369 /// Make the text dim
370 dimmed DimDisplay,
371 /// Make the text italicized
372 italic ItalicDisplay,
373 /// Make the text underlined
374 underline UnderlineDisplay,
375 /// Make the text blink
376 blink BlinkDisplay,
377 /// Make the text blink (but fast!)
378 blink_fast BlinkFastDisplay,
379 /// Swap the foreground and background colors
380 reversed ReversedDisplay,
381 /// Hide the text
382 hidden HiddenDisplay,
383 /// Cross out the text
384 strikethrough StrikeThroughDisplay,
385 }
386
387 /// Set the foreground color at runtime. Only use if you do not know which color will be used at
388 /// compile-time. If the color is constant, use either [`OwoColorize::fg`] or
389 /// a color-specific method, such as [`OwoColorize::green`],
390 ///
391 /// ```rust
392 /// use owo_colors::{OwoColorize, AnsiColors};
393 ///
394 /// println!("{}", "green".color(AnsiColors::Green));
395 /// ```
396 #[must_use]
397 #[inline(always)]
398 #[rust_analyzer::completions(ignore_flyimport)]
399 fn color<Color: DynColor>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self> {
400 FgDynColorDisplay(self, color)
401 }
402
403 /// Set the background color at runtime. Only use if you do not know what color to use at
404 /// compile-time. If the color is constant, use either [`OwoColorize::bg`] or
405 /// a color-specific method, such as [`OwoColorize::on_yellow`],
406 ///
407 /// ```rust
408 /// use owo_colors::{OwoColorize, AnsiColors};
409 ///
410 /// println!("{}", "yellow background".on_color(AnsiColors::BrightYellow));
411 /// ```
412 #[must_use]
413 #[inline(always)]
414 #[rust_analyzer::completions(ignore_flyimport)]
415 fn on_color<Color: DynColor>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self> {
416 BgDynColorDisplay(self, color)
417 }
418
419 /// Set the foreground color to a specific RGB value.
420 #[must_use]
421 #[rust_analyzer::completions(ignore_flyimport)]
422 fn fg_rgb<const R: u8, const G: u8, const B: u8>(
423 &self,
424 ) -> FgColorDisplay<'_, colors::CustomColor<R, G, B>, Self> {
425 FgColorDisplay(self, PhantomData)
426 }
427
428 /// Set the background color to a specific RGB value.
429 #[must_use]
430 #[rust_analyzer::completions(ignore_flyimport)]
431 fn bg_rgb<const R: u8, const G: u8, const B: u8>(
432 &self,
433 ) -> BgColorDisplay<'_, colors::CustomColor<R, G, B>, Self> {
434 BgColorDisplay(self, PhantomData)
435 }
436
437 /// Sets the foreground color to an RGB value.
438 #[must_use]
439 #[inline(always)]
440 #[rust_analyzer::completions(ignore_flyimport)]
441 fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self> {
442 FgDynColorDisplay(self, Rgb(r, g, b))
443 }
444
445 /// Sets the background color to an RGB value.
446 #[must_use]
447 #[inline(always)]
448 #[rust_analyzer::completions(ignore_flyimport)]
449 fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self> {
450 BgDynColorDisplay(self, Rgb(r, g, b))
451 }
452
453 /// Apply a runtime-determined style
454 #[must_use]
455 #[rust_analyzer::completions(ignore_flyimport)]
456 fn style(&self, style: Style) -> Styled<&Self> {
457 style.style(self)
458 }
459
460 /// Apply a given transformation function to all formatters if the given stream
461 /// supports at least basic ANSI colors, allowing you to conditionally apply
462 /// given styles/colors.
463 ///
464 /// Requires the `supports-colors` feature.
465 ///
466 /// ```rust
467 /// use owo_colors::{Stream, OwoColorize};
468 ///
469 /// println!(
470 /// "{}",
471 /// "woah! error! if this terminal supports colors, it's blue"
472 /// .if_supports_color(Stream::Stdout, |text| text.bright_blue())
473 /// );
474 /// ```
475 ///
476 /// This function also accepts `supports_color` version 2's `Stream`, and also the deprecated
477 /// `supports_color` version 1's `Stream`.
478 ///
479 /// ```rust
480 /// use owo_colors::OwoColorize;
481 /// #[cfg(feature = "supports-colors")]
482 /// use supports_color::Stream;
483 ///
484 /// println!(
485 /// "{}",
486 /// "woah! error! if this terminal supports colors, it's blue"
487 /// .if_supports_color(Stream::Stdout, |text| text.bright_blue())
488 /// );
489 #[must_use]
490 #[cfg(feature = "supports-colors")]
491 #[rust_analyzer::completions(ignore_flyimport)]
492 fn if_supports_color<'a, Out, ApplyFn>(
493 &'a self,
494 stream: impl Into<Stream>,
495 apply: ApplyFn,
496 ) -> SupportsColorsDisplay<'a, Self, Out, ApplyFn>
497 where
498 ApplyFn: Fn(&'a Self) -> Out,
499 {
500 SupportsColorsDisplay(self, apply, stream.into())
501 }
502}
503
504#[cfg(feature = "supports-colors")]
505mod supports_colors;
506
507#[cfg(feature = "supports-colors")]
508pub use {
509 overrides::{set_override, unset_override, with_override},
510 supports_colors::{Stream, SupportsColorsDisplay},
511};
512
513pub use colors::{
514 ansi_colors::AnsiColors, css::dynamic::CssColors, dynamic::Rgb, xterm::dynamic::XtermColors,
515};
516
517// TODO: figure out some wait to only implement for fmt::Display | fmt::Debug | ...
518impl<D> OwoColorize for D {}
519
520pub use {
521 combo::{ComboColorDisplay, ComboDynColorDisplay},
522 dyn_colors::*,
523 dyn_styles::*,
524};
525
526/// Module for drop-in [`colored`](https://docs.rs/colored) support to aid in porting code from
527/// [`colored`](https://docs.rs/colored) to owo-colors.
528///
529/// Just replace:
530///
531/// ```rust
532/// # mod colored {}
533/// use colored::*;
534/// ```
535///
536/// with
537///
538/// ```rust
539/// use owo_colors::colored::*;
540/// ```
541pub mod colored {
542 pub use crate::AnsiColors as Color;
543 pub use crate::OwoColorize;
544
545 /// A couple of functions to enable and disable coloring similarly to `colored`
546 #[cfg(feature = "supports-colors")]
547 pub mod control {
548 pub use crate::{set_override, unset_override};
549 }
550}
551
552pub use styled_list::StyledList;
553#[cfg(feature = "alloc")]
554pub use styled_list::StyledVec;
555
556#[cfg(test)]
557mod tests;