yansi/lib.rs
1#![doc(html_root_url = "https://docs.rs/yansi/0.6.0-dev")]
2
3//! A dead simple ANSI terminal color painting library.
4//!
5//! # Usage
6//!
7//! Usage is best illustrated via a quick example:
8//!
9//! ```rust
10//! use yansi::{Paint, Color};
11//!
12//! println!("Testing, {}, {}, {}!",
13//! Paint::red(1),
14//! Paint::green(2).bold().underline(),
15//! Paint::blue("3").bg(Color::White).italic());
16//! ```
17//!
18//! ## Paint
19//!
20//! The main entry point into this library is the [`Paint`] type. `Paint`
21//! encapsulates a value of any type that implements the [`Display`] or
22//! [`Debug`] trait. When a `Paint` is `Display`ed or `Debug`ed, the appropriate
23//! ANSI escape characters are emitted before and after the wrapped type's `fmt`
24//! implementation.
25//!
26//! `Paint` can be constructed via [a myriad of methods]. In addition to these
27//! constructors, you can also use the [`color.paint()`](Color::paint()) method
28//! on a given [`Color`] value to construct a `Paint` type. Both of these
29//! approaches are shown below:
30//!
31//! ```rust
32//! use yansi::Paint;
33//! use yansi::Color::Red;
34//!
35//! println!("I'm {}!", Paint::red("red").bold());
36//! println!("I'm also {}!", Red.paint("red").bold());
37//! ```
38//! [`Display`]: ::std::fmt::Display
39//! [`Debug`]: ::std::fmt::Debug
40//! [a myriad of methods]: struct.Paint.html#unstyled-constructors
41//!
42//! ## Styling
43//!
44//! Modifications to the styling of an item can be made via [a number of
45//! chainable methods] on `Paint`.
46//!
47//! ```rust
48//! use yansi::Paint;
49//!
50//! Paint::new("hi").underline().invert().italic().dimmed().bold();
51//! ```
52//!
53//! Styling can also be created independently from a `Paint` structure via the
54//! [`Style`] structure. This allows common styling to be stored and reused. A
55//! `Style` can be applied via the [`style.paint()`] method or the
56//! [`paint.with_style()`] method:
57//!
58//! ```rust
59//! use yansi::{Paint, Color, Style};
60//!
61//! // A bold, itatlic style with red foreground.
62//! let alert = Style::new(Color::Red).bold().italic();
63//!
64//! // Using `style.paint()`; this is preferred.
65//! println!("Alert! {}", alert.paint("This is serious business!"));
66//! println!("Hi! {}", alert.underline().paint("Super serious!"));
67//!
68//! // Using `paint.with_style()`.
69//! println!("Alert! {}", Paint::new("Yet another.").with_style(alert));
70//! ```
71//!
72//! [a number of chainable methods]: struct.Paint.html#setters
73//! [`style.paint()`]: Style::paint()
74//! [`paint.with_style()`]: Paint::with_style()
75//!
76//! # Disabling
77//!
78//! Painting can be disabled globally via the [`Paint::disable()`] method. When
79//! painting is disabled, the `Display` and `Debug` implementations for `Paint`
80//! will emit the `Display` or `Debug` of the contained object and nothing else.
81//! Painting can be reenabled via the [`Paint::enable()`] method.
82//!
83//! One potential use of this feature is to allow users to control color ouput
84//! via an environment variable. For instance, to disable coloring if the
85//! `CLICOLOR` variable is set to `0`, you might write:
86//!
87//! ```rust
88//! # { if false { // we don't actually want to disable coloring
89//! use yansi::Paint;
90//!
91//! if let Ok(true) = std::env::var("CLICOLOR").map(|v| v == "0") {
92//! Paint::disable();
93//! }
94//! # } }
95//! ```
96//!
97//! ## Masking
98//!
99//! Items can be arbitrarily _masked_. When an item is masked and painting is
100//! disabled, the `Display` and `Debug` implementations of `Paint` write
101//! nothing. This allows you to selectively omit output when painting is
102//! disabled. Values can be masked using the [`Paint::masked()`] constructor
103//! or [`paint.mask()`] and [`style.mask()`] style setters.
104//!
105//! [`paint.mask()`]: Paint::mask()
106//! [`style.mask()`]: Style::mask()
107//!
108//! One use for this feature is to print certain characters only when painting
109//! is enabled. For instance, you might wish to emit the 🎨 emoji when
110//! coloring is enabled but not otherwise. This can be accomplished by masking
111//! the emoji:
112//!
113//! ```rust
114//! use yansi::Paint;
115//!
116//! println!("I like colors!{}", Paint::masked(" 🎨"));
117//! ```
118//!
119//! This will print "I like colors! 🎨" when painting is enabled and "I like
120//! colors!" when painting is disabled.
121//!
122//! ## Wrapping
123//!
124//! Styling can be set to _wrap_ existing styles using either the
125//! [`Paint::wrapping()`] constructor or the [`paint.wrap()`] and
126//! [`style.wrap()`] style setters. When a style is _wrapping_, all color
127//! resets written out by the internal item's `Display` or `Debug`
128//! implementation are set to the styling of the wrapping style itself. In other
129//! words, the "default" style of the wrapped item is modified to be the
130//! wrapping style. This allows for easy wrapping of other colored text. Without
131//! this feature, the console would reset styling to the terminal's default
132//! style instead of the wrapping style.
133//!
134//! [`paint.wrap()`]: Paint::wrap()
135//! [`style.wrap()`]: Style::wrap()
136//!
137//! One use for this feature is to ensure that styling is consistently set
138//! across items that may already be styled, such as when logging.
139//!
140//! ```rust
141//! use yansi::{Paint, Color};
142//!
143//! let inner = format!("{} and {}", Paint::red("Stop"), Paint::green("Go"));
144//! println!("Hey! {}", Paint::wrapping(inner).fg(Color::Blue));
145//! ```
146//!
147//! This will print 'Hey!' unstyled, "Stop" in red, "and" in blue, and "Go" in
148//! green. Without wrapping, "and" would be unstyled as `Paint::red()` resets
149//! the style after printing the internal item.
150//!
151//! # Windows
152//!
153//! Coloring is supported on Windows beginning with the Windows 10 anniversary
154//! update. Since this update, Windows consoles support ANSI escape sequences.
155//! This support, however, must be explicitly enabled. `yansi` provides the
156//! [`Paint::enable_windows_ascii()`] method to enable ASCII support on Windows
157//! consoles when available.
158//!
159//! ```rust
160//! use yansi::Paint;
161//!
162//! // Enable ASCII escape sequence support on Windows consoles.
163//! Paint::enable_windows_ascii();
164//! ```
165//!
166//! You may wish to disable coloring on unsupported Windows consoles to avoid
167//! emitting unrecognized ASCII escape sequences:
168//!
169//! ```rust
170//! use yansi::Paint;
171//!
172//! if cfg!(windows) && !Paint::enable_windows_ascii() {
173//! Paint::disable();
174//! }
175//! ```
176//!
177//! [`Paint::enable_windows_ascii()`]: Paint::enable_windows_ascii()
178//!
179//! # Why?
180//!
181//! Several terminal coloring libraries exist ([`ansi_term`], [`colored`],
182//! [`term_painter`], to name a few), begging the question: why yet another?
183//! Here are a few reasons:
184//!
185//! * This library is _much_ simpler: there are three types!
186//! * Unlike [`ansi_term`] or [`colored`], _any_ type implementing `Display`
187//! or `Debug` can be stylized, not only strings.
188//! * Styling can be enabled and disabled globally, on the fly.
189//! * Arbitrary items can be [_masked_] for selective disabling.
190//! * Styling can [_wrap_] any arbitrarily styled item.
191//! * Typically only one type needs to be imported: [`Paint`].
192//! * Zero dependencies. It really is simple.
193//! * The name `yansi` is pretty short.
194//!
195//! All that being said, this library borrows API ideas from the three libraries
196//! as well as implementation details from [`ansi_term`].
197//!
198//! [`ansi_term`]: https://crates.io/crates/ansi_term
199//! [`colored`]: https://crates.io/crates/colored
200//! [`term_painter`]: https://crates.io/crates/term-painter
201//! [_masked_]: #masking
202//! [_wrap_]: #wrapping
203
204#[macro_use] mod macros;
205
206#[cfg(test)] mod tests;
207mod windows;
208mod paint;
209mod style;
210mod color;
211
212pub use color::Color;
213pub use style::Style;
214pub use paint::Paint;