Crate ansiconst

Crate ansiconst 

Source
Expand description

§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 ansiconst::{Ansi, ansi, ansi_code};

// Define styles as Ansi structs:
const    HEADING_ANSI: Ansi = ansi!(Green, Bold, Underline);
const SUBHEADING_ANSI: Ansi = ansi!(Blue, Italic);
const      RESET_ANSI: Ansi = ansi!(Ansi::reset());

assert_eq!(   HEADING_ANSI.to_string(), "\x1B[1;4;32m");
assert_eq!(SUBHEADING_ANSI.to_string(), "\x1B[3;34m");
assert_eq!(     RESET_ANSI.to_string(), "\x1B[0m");

// Or, define styles as ANSI codes:
const    HEADING_CODE: &str = ansi_code!(Green, Bold, Underline);
const SUBHEADING_CODE: &str = ansi_code!(Blue, Italic);
const      RESET_CODE: &str = ansi_code!(Ansi::reset());

assert_eq!(               HEADING_CODE, "\x1B[1;4;32m");
assert_eq!(            SUBHEADING_CODE, "\x1B[3;34m");
assert_eq!(                 RESET_CODE, "\x1B[0m");

§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:

TypeBytes
Ansi6
Ansi feature="color256"8
Ansi feature="rgb"12
&'static str16

§Simple Macros

Apply ANSI codes using macros:

§Examples
use ansiconst::{styled, styled_format, styled_format_args, styled_writeln};
use ansiconst::{paintln, epaintln};

// Notice how "Red" and "Bold" are automatically available inside the macros.
let pet = "cat";
let age = 5;
let string1 =             styled!(Red, Bold, "My cat is 5 years old").to_string();
let string2 =      styled_format!(Red, Bold, "My {} is {} years old", pet, age).to_string();
let string3 = styled_format_args!(Red, Bold, "My {} is {} years old", pet, age).to_string();

assert_eq!(string1, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");
assert_eq!(string2, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");
assert_eq!(string3, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");

// Print "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to stdout and stderr:
paintln! (Red, Bold, "My {} is {} years old", pet, age);
epaintln!(Red, Bold, "My {} is {} years old", pet, age);

// Write "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to a writer:
use std::fmt::Write;
let mut buffer = String::new();
styled_writeln!(&mut buffer, Red, Bold, "My {} is {} years old", pet, age).unwrap();
assert_eq!(buffer, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n");

§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 ansiconst::{Styled, styled, styled_format_args};

const INNER:           Styled<&str> = styled!(Underline,             "Inner");
const INNER_ONLY:      Styled<&str> = styled!(Underline.only(),      "Inner");
const INNER_IMPORTANT: Styled<&str> = styled!(Underline.important(), "Inner");

// Example 1: blended styles
assert_eq!(
    styled_format_args!(Bold, "Bold {INNER} Bold again").to_string(),
    // "Inner" is both Bold and Underline
    "\x1B[1mBold \x1B[4mInner\x1B[24m Bold again\x1B[22m"
);

// Example 2: inner style only
assert_eq!(
    styled_format_args!(Bold, "Bold {INNER_ONLY} Bold again").to_string(),
    // "Inner" is not Bold, only Underline, due to inner's .only()
    "\x1B[1mBold \x1B[22;4mInner\x1B[24;1m Bold again\x1B[22m"
);

// Example 3: outer style only + important
assert_eq!(
    styled_format_args!(Bold.only().important(), "Bold {INNER_ONLY} Bold again").to_string(),
    // Entire string is Bold, nested Underline was ignored due to .only().important()
    "\x1B[0;1mBold Inner Bold again\x1B[22m"
);

// Example 4: both important
assert_eq!(
    styled_format_args!(Bold.only().important(), "Bold {INNER_IMPORTANT} Bold again").to_string(),
    // "Inner" is Bold and Underline, due to inner's .important()
    "\x1B[0;1mBold \x1B[4mInner\x1B[24m Bold again\x1B[22m"
);

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 ansiconst::{Ansi, ansi, paintln, styled_format_args};

const HEADING:    Ansi = ansi!(Green, Bold, Underline);
const SUBHEADING: Ansi = ansi!(Cyan, Italic);
const STRONG:     Ansi = ansi!(Yellow, Bold);
const STRONGER:   Ansi = ansi!(Blink);
const STRONGEST:  Ansi = ansi!(Purple, Bold.not());

// Styling with paintln!
paintln!(HEADING,    "The Book of Rust");
paintln!();
paintln!(SUBHEADING, "Chapter 1");
paintln!();

// Styling with println!
println!("This sentence shows how {} as you would expect.",
    styled_format_args!(STRONG, "styles can be {}, and they combine",
        styled_format_args!(STRONGER, "nested to {} depths",
            styled_format_args!(STRONGEST, "arbitrary")
        )
    )
);
println!("This sentence shows another {} colors/effects.",
    styled_format_args!(Green, Italic, "way of styling {} i.e. with inline",
        styled_format_args!(Yellow, Bold, "your text,")
    )
);

§Upgrading from v0.1.x

Required actions due to breaking changes:

Modules§

introspect
Obtain the properties of an Ansi.
io
Set default ANSI styles for writers and handles.

Macros§

ansi
Creates an ANSI style as an Ansi const.
ansi_code
Creates an ANSI style as a &'static str.
epaint
Like eprint! except with ANSI-styled output.
epaintln
Like eprintln! except with ANSI-styled output.
paint
Like print! except with ANSI-styled output.
paintln
Like println! except with ANSI-styled output.
styled
Creates an ANSI-styled value.
styled_format
Like format! except creates an ANSI StyledString.
styled_format_args
Like format_args! except creates ANSI-styled Arguments.
styled_write
Like write! except with ANSI-styled output.
styled_writeln
Like writeln! except with ANSI-styled output.

Structs§

Ansi
Represents an arbitrary combination of ANSI Effects and foreground/background Colors.
ColorReset
Represents the reset Color code (SGR parameters: foreground 39, background 49)
Styled
Associates a Display target with an Ansi style, such that formatting produces the result of formatting the target with the style’s ANSI codes wrapped around it.
StyledString
A String containing Ansi styles, which can be overridden.

Enums§

Color
Represents the control sequences, named Select Graphic Rendition (SGR), that are used to set foreground and background colors on ANSI terminals.
Coloree
Represents the parts of an ANSI terminal that can have a color applied.
Effect
Represents the control sequences, named Select Graphic Rendition (SGR), that are used to enable various effects (e.g. italic) on ANSI terminals.