Expand description
§Pretty 🌸 Pretty
Prettypretty brings 2020s color science to 1970 terminals.
This version of the API documentation covers both Rust and Python
interfaces. You can find a version without Python integration, with the pyffi
feature disabled, on Docs.rs.
The user guide provides a
comprehensive overview and several deep dives covering both languages. There
also are the type
stubs
and API documentation
for Python as well as the shared source
repository, Rust
crate, and Python
package.
§1. Overview
Prettypretty’s main abstractions are:
Color
implements high-resolution colors by combining aColorSpace
with threeFloat
coordinates. Its methods expose much of prettypretty’s functionality, including conversion between color spaces, interpolation between colors, calculation of perceptual contrast, as well as gamut testing, clipping, and mapping.- The
termco
module offers a choice of terminal-specific color formatsAnsiColor
,EmbeddedRgb
,GrayGradient
,EightBitColor
,Rgb
, as well as the wrapperColorant
. - The
style
module defines terminalStyle
s as a textFormatUpdate
combined with foreground and backgroundColorant
s. It also definesLayer
to distinguish between the two colors andFidelity
to represent a terminal’s styling capabilities. Translator
implements translation between color formats. To ensure high quality results, its preferred algorithms leverage the perceptually uniform Oklab/Oklch color space. For conversion to the 16 ANSI colors, it also reqires the terminal’s current colorTheme
.- The optional
gamut
andspectrum
submodules enable the traversal of color space gamuts and the human visual gamut, respectively. The plot.py and viz3d.py scripts leverage the additional functionality for generating helpful color visualizations.
§2. One-Two-Three: Styles!
Prettypretty’s three-step workflow for awesome terminal styles works like this.
§i. Assemble Your Styles
First, assemble your application’s styles by modifying the empty
Style::default()
.
// 1. Assemble application styles
let chic = Style::default()
.bold()
.underlined()
.with_foreground(Rgb::new(215, 40, 39));
Style::with_foreground
and
Style::with_background
accept any of
prettypretty’s color representations, i.e.,
AnsiColor
, EmbeddedRgb
,
GrayGradient
,
EightBitColor
, Rgb
or
high-resolution Color
.
§ii. Adjust Your Styles
Second, determine the terminal’s current color theme with
Theme::query
and its color support with
Fidelity::from_environment
.
// 2a. Determine terminal's color support and theme
let options = Options::with_log();
let (has_tty, theme) = match Connection::with_options(options) {
Ok(tty) => (true, Theme::query(&tty)?),
Err(_) => (false, VGA_COLORS),
};
let fidelity = Fidelity::from_environment(has_tty);
Use the theme
to instantiate a Translator
, which
specializes in complex color conversions and then adjust your application’s
styles to the current color theme and fidelity.
Style::cap
puts a cap on styles with the help of
Translator::cap
, which takes care of colors.
// 2b. Actually adjust styles
let translator = Translator::new(OkVersion::Revised, theme);
let effective_chic = &chic.cap(fidelity, &translator);
§iii. Apply Your Styles
Third, to apply a style, just write its display. To undo the style again, just write the negation’s display.
// 3. Apply and revert styles
println!("{}Wow!{}", effective_chic, -effective_chic);
And the terminal exclaims:
🎉
§3. Optional Features
Prettypretty supports four feature flags:
f64
selects the eponymous type as floating point typeFloat
andu64
asBits
instead off32
asFloat
andu32
asBits
. This feature is enabled by default.tty
controlsTheme::query
and its implementation with the prettytty terminal crate. This feature is enabled by default.gamut
controls support for tracing the boundaries of color spaces (mod gamut
,ColorSpace::gamut
) and the human visual gamut (mod spectrum
). This feature is disabled by default.pyffi
controls prettypretty’s Python integration through PyO3. This feature is disabled by default.
Prettypretty’s Python extension module is built with
Maturin, PyO3’s dedicated build tool. Since Python
packages typically come with “batteries included,” the gamut
feature is
also enabled when building the Python extension module. However, the tty
feature is disabled, and prettypretty’s Python package includes its own
terminal abstraction.
Throughout the API documentation, items that are only available in Rust are
decorated with Rust only!.
Items that are only available in Python are decorated with Python only!.
Similarly, items only available with the tty
feature are decorated with TTY only! and items only available with the gamut
feature are decorated with Gamut only!.
§4. Acknowledgements
Implementing prettypretty’s color support was a breeze. In part, that was because I had been toying with different approaches to terminal styling for a while and knew what I wanted to build. In part, that was because I benefitted from Lea Verou’s and Chris Lilley’s work on the Color.js library and CSS Color 4 specification. Prettypretty directly reuses Color.js’ formulae for conversion between color spaces and implements several CSS Color 4 algorithms. Thank you! 🌸
Modules§
- Utility module with prettypretty’s errors.
- Optional module implementing the traversal of RGB gamut boundaries with
ColorSpace::gamut
. - Optional module implementing the traversal of the human visual gamut.
- Terminal-specific text fromatting and styles.
- Terminal color representations.
- Utility module implementing terminal color themes.
Macros§
- Test macro for asserting the equality of floating point numbers.
- Test macro for asserting the equality of colors.
- Create a new sRGB color from 24-bit integer coordinates.
Structs§
- A high-resolution color object.
- Helper struct returned by
Color::interpolate
. - A color translator.
Enums§
- The enumeration of supported color spaces.
- A choice of strategy for interpolating hues.
- A choice of Oklab versions.
Functions§
- Determine whether the two floats are close enough to be considered equal. Python only!
Type Aliases§
Float
’s bits.- The floating point type in use.