in src/content/lines.rs [471:576]
fn test_colored_from_multiline_string() {
// Lots of little things we check in here, including that we persist state
// across lines, that we only change the state that is requested to be changed,
// that we control fg/bg properly, that we parse different ansi formats, etc.
let test_string = format!(
"This is a string
That has both {blue}8 bit blue {blue2}(in both formats)
in it,{reset} as well as {high_blue}256 color blue,
{reset}and {rgb_blue}RGB blue as well.{reset} It resets to the
console default at the end.
It can do {rgb_blue}{bg_blue}background colors, {blue}foreground colors,
{bold}colored, and {reset}normal {bold}bold,{remove_bold} and it
strips out {bs}invalid control sequences",
blue = "\x1b[34m",
blue2 = "\x1b[38;5;4m",
high_blue = "\x1b[38;5;20m",
rgb_blue = "\x1b[38;2;0;0;238m",
bg_blue = "\x1b[44m",
reset = "\x1b[0m",
bold = "\x1b[1m",
remove_bold = "\x1b[22m",
bs = "\x1b[D"
);
let default = ContentStyle::default();
// Both 34m and 38;5;4m parse to the same thing, so no need for blue2
let blue = ContentStyle {
foreground_color: Some(Color::AnsiValue(4)),
..Default::default()
};
let high_blue = ContentStyle {
foreground_color: Some(Color::AnsiValue(20)),
..Default::default()
};
let rgb_blue = ContentStyle {
foreground_color: Some(Color::from((0, 0, 238))),
..Default::default()
};
let bg_blue = ContentStyle {
background_color: Some(Color::AnsiValue(4)),
..Default::default()
};
let rgb_blue_and_bg_blue = ContentStyle {
foreground_color: rgb_blue.foreground_color,
background_color: bg_blue.background_color,
..Default::default()
};
let blue_and_bg_blue = ContentStyle {
foreground_color: blue.foreground_color,
background_color: bg_blue.background_color,
..Default::default()
};
let blue_and_bg_blue_bold = ContentStyle {
foreground_color: blue.foreground_color,
background_color: bg_blue.background_color,
attributes: Attributes::from(Attribute::Bold),
};
let bold = ContentStyle {
attributes: Attributes::from(Attribute::Bold),
..Default::default()
};
let expected = vec![
vec![StyledContent::new(default, "This is a string")],
vec![
StyledContent::new(default, "That has both "),
StyledContent::new(blue, "8 bit blue "),
StyledContent::new(blue, "(in both formats)"),
],
vec![
StyledContent::new(blue, "in it,"),
StyledContent::new(default, " as well as "),
StyledContent::new(high_blue, "256 color blue,"),
],
vec![
StyledContent::new(default, "and "),
StyledContent::new(rgb_blue, "RGB blue as well."),
StyledContent::new(default, " It resets to the"),
],
vec![StyledContent::new(default, "console default at the end.")],
vec![
StyledContent::new(default, "It can do "),
StyledContent::new(rgb_blue_and_bg_blue, "background colors, "),
StyledContent::new(blue_and_bg_blue, "foreground colors,"),
],
vec![
StyledContent::new(blue_and_bg_blue_bold, "colored, and "),
StyledContent::new(default, "normal "),
StyledContent::new(bold, "bold,"),
StyledContent::new(default, " and it"),
],
vec![StyledContent::new(
default,
"strips out invalid control sequences",
)],
];
let expected: Lines = expected.into_map(|spans| {
Line(spans.map(|sc| {
Span::new_styled_lossy(StyledContent::new(*sc.style(), (*sc.content()).to_owned()))
}))
});
let lines = colored_lines_from_multiline_string(&test_string);
assert_eq!(expected, lines);
}