ansiconst
Contents
Ansi Constants
A library for declaring nestable ANSI styles in const context.
Motivation
The primary motivation of this crate is to provide the ability to use ANSI colors/effects in command-line programs by identifying them semantically rather than literally.
For example, when calling println!, instead of applying the style
Green, Bold to the output, it has more semantic meaning to apply
a style named Subheading that, when rendered (or "formatted" in Rust),
produces the output that activates the Green, Bold styling.
Furthermore, semantic styles should be nestable, like styling frameworks such as HTML's CSS. For example, it should be possible to nest text styled with a name like Manufacturer inside text styled with a name like Product Details and have the literal styles that these semantic styles translate to applied automatically. The nested style's attributes should temporarily layer on top of, or maybe replace, the parent style's attributes as appropriate.
The second key motivation of this crate is to support the above at
compile-time. I.e. define semantic styles as const, and then use
them with minimal overhead throughout a command-line program.
There are other crates that provide terminal-styling functionality, but none appear to fully support the use-case outlined above. The API provided by this crate in support of this use-case is presented in the following section.
Key Features
Compile-Time
Declare ANSI codes as const. This means the compiler will inline them
wherever they are used, potentially improving runtime performance.
Examples
use ;
// Define styles as Ansi structs:
const HEADING_ANSI: Ansi = ansi!;
const SUBHEADING_ANSI: Ansi = ansi!;
const RESET_ANSI: Ansi = ansi!;
assert_eq!;
assert_eq!;
assert_eq!;
// Or, define styles as ANSI codes:
const HEADING_CODE: &str = ansi_code!;
const SUBHEADING_CODE: &str = ansi_code!;
const RESET_CODE: &str = ansi_code!;
assert_eq!;
assert_eq!;
assert_eq!;
Small
Ansi instances are designed to be as small as possible. For example, Effects
are represented internally using bit flags rather than simple bools.
For this reason, the use of 8-bit and RGB colors
is gated behind feature flags, because supporting them means Ansi instances
must be ever so slightly bigger. Consider the memory sizes:
| Type | Bytes |
|---|---|
Ansi |
6 |
Ansi feature="color256" |
8 |
Ansi feature="rgb" |
12 |
&'static str |
16 |
Simple Macros
Apply ANSI codes using macros:
styled!creates ANSI-styled values without interpolation (e.g.&'static str,u8).styled_format!,styled_format_args!are analogous toformat!,format_args!except that they create ANSI-styled results.styled_write!,styled_writeln!are analogous towrite!,writeln!except that they write ANSI-styled output.paint!,paintln!,epaint!,epaintln!are analogous toprint!,println!,eprint!,eprintln!except that they print ANSI-styled output.
Examples
use ;
use ;
// Notice how "Red" and "Bold" are automatically available inside the macros.
let pet = "cat";
let age = 5;
let string1 = styled!.to_string;
let string2 = styled_format!.to_string;
let string3 = styled_format_args!.to_string;
assert_eq!;
assert_eq!;
assert_eq!;
// Print "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to stdout and stderr:
paintln! ;
epaintln!;
// Write "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to a writer:
use Write;
let mut buffer = Stringnew;
styled_writeln!.unwrap;
assert_eq!;
Effortless Nesting
Nesting of ANSI codes is automatically handled, and uses the minimum ANSI code sequences when transitioning between nesting levels.
Additionally, nested ANSI codes can be effectively disabled by setting an
important modifier on the outer Ansi's attributes.
This works similarly to HTML's CSS !important
rule, in that an inner normal attribute is ignored if the same outer attribute
is important.
Furthermore, nested Ansis can prevent automatic inheriting of the style attributes
of enclosing Ansis by explicitly resetting them using only.
Finally, nested Ansis can be disabled entirely with no_ansi.
Examples
use ;
const INNER: = styled!;
const INNER_ONLY: = styled!;
const INNER_IMPORTANT: = styled!;
// Example 1: blended styles
assert_eq!;
// Example 2: inner style only
assert_eq!;
// Example 3: outer style only + important
assert_eq!;
// Example 4: both important
assert_eq!;
Note: automatic handling of nested styles is achieved by storing the last-applied
ANSI style in a thread_local! static variable, and therefore this library
requires std. See Styled<T> and StyledString for details.
Examples
use ;
const HEADING: Ansi = ansi!;
const SUBHEADING: Ansi = ansi!;
const STRONG: Ansi = ansi!;
const STRONGER: Ansi = ansi!;
const STRONGEST: Ansi = ansi!;
// Styling with paintln!
paintln!;
paintln!;
paintln!;
paintln!;
// Styling with println!
println!;
println!;
Upgrading from v0.1.x
Required actions due to breaking changes:
- Rename
ansiconst::Colourtoansiconst::Color, or omit this import entirely, since color names (e.g.Red) are now automatically available inside API macros. - Rename
features = ["ansi256"]tofeatures = ["color256"]insideCargo.toml. - Rename
Colour::Ansi256(n)toColor::num(n). - Rename
Colour::Rgb(r,g,b)toColor::rgb(r,g,b). - Rename
Color::Unspecified,Effect::UnspecifiedtoAnsi::empty(). - Rename
Effect::NotBoldtoEffect::Bold.not()(same for other effects). - Rename
styled_format!(...)tostyled_format!(...).to_string()orstyled_format_args!(...).to_string().
Version History
Licence
MIT