Expand description
This crate provides macros for ergonomically wrapping text in ANSI control sequences with SGR (“Select Graphic Rendition”) parameters. These parameters are used to color text, as well as apply styling such as italics and underlining. Extensive information on the specific sequences is available on the Wikipedia page for ANSI escape codes.
§Modes
There are three “output modes” to every macro in this crate: Literal,
Format, and String. These determine the output type of the macro, and
whether it can be called in const
contexts. Additionally, there are
also three “reversion modes”: Single, Total, and None. These determine
what is to be done at the end of a macro call — the formatting state
that should be reverted.
§Output Modes
The simplest output mode is Literal Mode. A string literal must be supplied,
and all formatting is applied directly, at compile-time. The output of
a Literal Mode macro invocation is a string literal, suitable for the
value of a const
, or as input to compile-time macros (such as
concat!
or another SGR macro).
use sgr_macros::*;
let green: &'static str = green!("Green Text");
assert_eq!(green, "\x1B[32mGreen Text\x1B[39m");
let bold: &'static str = sgr_bold!(green!("Bold Green Text"));
assert_eq!(bold, "\x1B[1m\x1B[32mBold Green Text\x1B[39m\x1B[22m");
let concat: &'static str = concat!(sgr_bold!("Bold Text"), ", Normal Text");
assert_eq!(concat, "\x1B[1mBold Text\x1B[22m, Normal Text");
The second mode is Format Mode. An invocation in this mode will resolve to a
call to format_args!
. This will return Arguments
suitable as
input to formatting macros such as format!
, println!
, and
write!
. This mode is enabled by placing a %
sigil at the beginning
of the call. After the sigil, a template literal may be provided.
use sgr_macros::*;
fn lights(number: &str) -> String {
format!("There are {} lights.", sgr_uline!(% number))
}
let text: String = lights("five");
assert_eq!(text, "There are \x1B[4mfive\x1B[24m lights.");
fn lights_alt(number: &str) -> String {
format!("There are {}.", sgr_italic!(%"{} lights", number))
}
let text: String = lights_alt("four");
assert_eq!(text, "There are \x1B[3mfour lights\x1B[23m.");
The third mode is String Mode. An invocation in this mode will resolve to a
call to format!
, returning a fully-formed heap-allocated String
.
This mode is enabled with a @
sigil at the beginning of the call, and
it may also be provided a template literal.
use sgr_macros::*;
fn status(ok: bool, msg: &str) -> String {
if ok {
blue_bright!(@ msg)
} else {
red!(@"ERROR: {}", msg)
}
}
let text: String = status(true, "Success.");
assert_eq!(text, "\x1B[94mSuccess.\x1B[99m");
let text: String = status(false, "System is on fire.");
assert_eq!(text, "\x1B[31mERROR: System is on fire.\x1B[39m");
If the “const” Cargo Feature is enabled, a fourth mode is available: Const
Format Mode. An invocation in this mode will resolve to a call to
const_format::formatcp!
, returning a static string slice. This
output is NOT a string literal, however, and is not suitable as input to
concat!
. This mode is enabled with a #
sigil at the beginning of
the call.
#[cfg(feature = "const")] {
use sgr_macros::*;
const TEXT: &'static str = sgr_italic!(#*,
"italic {r} {} {b}",
green!(! "green"),
b = blue!(! "blue"),
r = red!(! "red"),
);
assert_eq!(
TEXT,
"\x1B[3mitalic \x1B[31mred \x1B[32mgreen \x1B[34mblue\x1B[m",
);
}
§Reversion Modes
By default, the result of every macro in this crate will end with another
control sequence that undoes whatever formatting was set at the start.
For example, the sgr_bold!
macro will emit a control sequence to
set bold intensity, the input parameters to the macro, and then a second
control sequence to set normal intensity. Similarly, all coloring macros
will set the default text color when they end.
Some styles share a revert sequence, meaning that they cannot be safely nested; The end of the inner style will also revert the outer style. This is true of the following groups of macros:
sgr_bold!
andsgr_faint!
sgr_blink!
andsgr_blink2!
sgr_super!
andsgr_sub!
- All color macros (basic, indexed, and RGB) that do not end in
*_bg
. - All color macros (basic, indexed, and RGB) that do end in
*_bg
.
To control the behavior of revert sequences, there are two more sigils: !
to prevent reverting any formatting, and *
to revert all
formatting. Like the Output Mode sigils, these are placed at the
beginning of a macro call. If an output sigil and a revert sigil are
both used, the output sigil must be placed first (e.g. @*
or %!
).
use sgr_macros::*;
assert_eq!(
// Here, several layered formatting codes are applied, and then cleared
// individually. This uses a considerable number of bytes compared
// to how it might be done manually.
sgr_bold!(sgr_italic!(sgr_uline!("WHAM"))),
"\x1B[1m\x1B[3m\x1B[4mWHAM\x1B[24m\x1B[23m\x1B[22m",
);
assert_eq!(
// One way to address this is to specify that `sgr_uline!` and
// `sgr_italic!` should NOT revert, and that `sgr_bold!` should
// revert ALL formatting.
sgr_bold!(* sgr_italic!(! sgr_uline!(! "WHAM"))),
"\x1B[1m\x1B[3m\x1B[4mWHAM\x1B[m",
);
assert_eq!(
// Here, the color is reset to default twice: Once at the end of Blue,
// and again at the end of (Not) Red.
red!(@ "Red, {}, (Not) Red", blue!("Blue")),
"\x1B[31mRed, \x1B[34mBlue\x1B[39m, (Not) Red\x1B[39m",
);
assert_eq!(
// Here, the color is not reset at the end of Blue, resulting in its
// blue formatting spilling out to the end of the string. This sort
// of conflict cannot be solved at compilation while using multiple
// macros, so it is best to avoid nesting colors whenever possible.
red!(@ "Red, {}, Still Blue", blue!(! "Blue")),
"\x1B[31mRed, \x1B[34mBlue, Still Blue\x1B[39m",
);
A comma is accepted, but not required, after sigils. This may be helpful for clarity, or in a case of a dereferenced or inverted argument:
let text: &&str = &"Doubly-Referenced String";
assert_eq!(
sgr_macros::sgr_bold!(@**text), // Very unclear.
"\x1B[1mDoubly-Referenced String\x1B[m",
);
assert_eq!(
sgr_macros::sgr_bold!(@*, *text), // Much clearer.
"\x1B[1mDoubly-Referenced String\x1B[m",
);
let mask: u8 = 0b01001001;
assert_eq!(
sgr_macros::sgr_uline!(@!!mask), // Very unclear.
"\x1B[4m182",
);
assert_eq!(
sgr_macros::sgr_uline!(@!, !mask), // Much clearer.
"\x1B[4m182",
);
§Macros
§Basic Color
There are eight fundamental colors supported by SGR: Black, red, green, yellow, blue, magenta, cyan, and white. Each of these 8 colors has a “bright” variant, leading to 16 named colors. In addition, each of these 16 named colors has two macros: One for foreground color, and one for background color.
This results in 32 basic color macros; Four macros for each of the eight fundamental colors.
assert_eq!(
sgr_macros::cyan!("Bright Cyan Text"),
"\x1B[36mBright Cyan Text\x1B[39m",
);
assert_eq!(
sgr_macros::cyan_bg!("Text on Bright Cyan"),
"\x1B[46mText on Bright Cyan\x1B[49m",
);
assert_eq!(
sgr_macros::cyan_bright!("Bright Cyan Text"),
"\x1B[96mBright Cyan Text\x1B[99m",
);
assert_eq!(
sgr_macros::cyan_bright_bg!("Text on Bright Cyan"),
"\x1B[106mText on Bright Cyan\x1B[109m",
);
§Indexed Color
Two macros are provided for 8-bit SGR color codes: color_256!
and
color_256_bg!
. These macros use all the same mode sigils as detailed
above, but the first argument of the macro must be an 8-bit
integer, specifying the color index, followed by a semicolon.
assert_eq!(
sgr_macros::color_256!(173; "Orange Text"),
"\x1B[38;5;173mOrange Text\x1B[39m",
);
assert_eq!(
sgr_macros::color_256_bg!(173; "Text on Orange"),
"\x1B[48;5;173mText on Orange\x1B[49m",
);
assert_eq!(
sgr_macros::color_256_bg!(173; *, "Text on Orange"),
"\x1B[48;5;173mText on Orange\x1B[m",
);
§RGB Color
Two macros are provided for 24-bit SGR color codes: color_rgb!
and
color_rgb_bg!
. These macros use all the same mode sigils as detailed
above, but the first argument of the macro must be an RGB
color value followed by a semicolon.
assert_eq!(
sgr_macros::color_rgb!(0x420311; "Maroon Text"),
"\x1B[38;2;66;3;17mMaroon Text\x1B[39m",
);
assert_eq!(
sgr_macros::color_rgb_bg!(0x420311; "Text on Maroon"),
"\x1B[48;2;66;3;17mText on Maroon\x1B[49m",
);
For more information on the RGB color specification, see the documentation
on the color_rgb!
macro.
§Style
Eleven macros are provided for various “styles” of text. These typically do not alter text color, but some aspects, such as text intensity, may be implemented by a terminal as changing color brightness or vividness.
Macros§
- black
- Color the enclosed text black.
- black_
bg - Put the enclosed text on a black background.
- black_
bright - Color the enclosed text bright black (grey).
- black_
bright_ bg - Put the enclosed text on a bright black (grey) background.
- blue
- Color the enclosed text blue.
- blue_bg
- Put the enclosed text on a blue background.
- blue_
bright - Color the enclosed text bright blue.
- blue_
bright_ bg - Put the enclosed text on a bright blue background.
- color_
256 - Color text with an 8-bit indexed color value.
- color_
256_ bg - Color the background with an 8-bit indexed color value.
- color_
rgb - Color text with a 24-bit RGB value.
- color_
rgb_ bg - Color the background with a 24-bit RGB value.
- cyan
- Color the enclosed text cyan.
- cyan_bg
- Put the enclosed text on a cyan background.
- cyan_
bright - Color the enclosed text bright cyan.
- cyan_
bright_ bg - Put the enclosed text on a bright cyan background.
- green
- Color the enclosed text green.
- green_
bg - Put the enclosed text on a green background.
- green_
bright - Color the enclosed text bright green.
- green_
bright_ bg - Put the enclosed text on a bright green background.
- magenta
- Color the enclosed text magenta.
- magenta_
bg - Put the enclosed text on a magenta background.
- magenta_
bright - Color the enclosed text bright magenta.
- magenta_
bright_ bg - Put the enclosed text on a bright magenta background.
- red
- Color the enclosed text red.
- red_bg
- Put the enclosed text on a red background.
- red_
bright - Color the enclosed text bright red.
- red_
bright_ bg - Put the enclosed text on a bright red background.
- sgr_
blink - Blink text slowly.
- sgr_
blink2 - Blink text quickly. Not widely supported.
- sgr_
bold - Make text bold or more intense.
- sgr_
conceal - Make text invisible. Not widely supported.
- sgr_
faint - Make text faint or less intense.
- sgr_
invert - Invert foreground and background colors.
- sgr_
italic - Make text italic.
- sgr_
strike - Show text with a horizontal strike, crossing it out.
- sgr_sub
- Subscript. Not widely supported.
- sgr_
super - Superscript. Not widely supported.
- sgr_
uline - Underline text.
- white
- Color the enclosed text white.
- white_
bg - Put the enclosed text on a white background.
- white_
bright - Color the enclosed text bright white.
- white_
bright_ bg - Put the enclosed text on a bright white background.
- yellow
- Color the enclosed text yellow.
- yellow_
bg - Put the enclosed text on a yellow background.
- yellow_
bright - Color the enclosed text bright yellow.
- yellow_
bright_ bg - Put the enclosed text on a bright yellow background.