// SPDX-FileCopyrightText: 2020-2021 Robin Krahl // SPDX-License-Identifier: Apache-2.0 or MIT fn render(f: F) -> String where F: Fn(&mut Vec) -> Result<(), E>, E: std::fmt::Debug, { let mut v = Vec::new(); f(&mut v).expect("Failed to render string"); String::from_utf8(v).expect("Output is invalid UTF-8") } fn assert_output(expected: &[&str], actual: &str) { if !expected.contains(&actual) { let mut msg = "Unexpected output:\n expected one of:\n".to_owned(); for s in expected { msg.push_str(&format!(" {:?}\n", s)); } msg.push_str(" found:\n"); msg.push_str(&format!(" {:?}", actual)); panic!("{}", msg); } } macro_rules! test_cases { ([$input:expr; $output:expr] $( $( #[$attr:meta] )* $name:ident, )+) => { $( #[test] $( #[$attr] )* fn $name() { let input = $input; let expected_output = $output; let output = crate::render(|v| text_style::$name::render(v, &input)); crate::assert_output(expected_output, &output); } )* }; } mod bold { const OUTPUT: &[&'static str] = &["\x1b[1mtest\x1b[0m", "\x1b[1mtest\x1b[m"]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").bold() } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::utils::markup; let input = input(); let output = markup::StyledString::styled("test", cursive::theme::Effect::Bold); assert_eq!(output, markup::StyledString::from(input)); } #[test] fn genpdf() { use genpdf::style; let input = input(); let output = style::StyledStr::from(input.clone()); assert_eq!(output.s, input.s); assert!(output.style.is_bold()); } } mod italic { const OUTPUT: &[&'static str] = &["\x1b[3mtest\x1b[0m", "\x1b[3mtest\x1b[m"]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").italic() } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::utils::markup; let input = input(); let output = markup::StyledString::styled("test", cursive::theme::Effect::Italic); assert_eq!(output, markup::StyledString::from(input)); } #[test] fn genpdf() { use genpdf::style; let input = input(); let output = style::StyledStr::from(input.clone()); assert_eq!(output.s, input.s); assert!(output.style.is_italic()); } } mod underline { const OUTPUT: &[&'static str] = &["\x1b[4mtest\x1b[0m", "\x1b[4mtest\x1b[m"]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").underline() } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::utils::markup; let input = input(); let output = markup::StyledString::styled("test", cursive::theme::Effect::Underline); assert_eq!(output, markup::StyledString::from(input)); } } mod strikethrough { const OUTPUT: &[&'static str] = &["\x1b[9mtest\x1b[0m", "\x1b[9mtest\x1b[m"]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").strikethrough() } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::utils::markup; let input = input(); let output = markup::StyledString::styled("test", cursive::theme::Effect::Strikethrough); assert_eq!(output, markup::StyledString::from(input)); } } mod fg { const OUTPUT: &[&'static str] = &[ "\x1b[31mtest\x1b[39m", "\x1b[31mtest\x1b[0m", "\x1b[31mtest\x1b[m", "\x1b[38;5;1mtest\x1b[39m", "\x1b[38;5;1mtest\x1b[0m", "\x1b[38;5;1mtest\x1b[m", ]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").with(text_style::AnsiColor::Red.dark()) } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::{theme, utils::markup}; let input = input(); let output = markup::StyledString::styled( "test", theme::ColorStyle::new( theme::Color::Dark(theme::BaseColor::Red), theme::ColorType::InheritParent, ), ); assert_eq!(output, markup::StyledString::from(input)); } #[test] fn genpdf() { use genpdf::style; let input = input(); let output = style::StyledStr::from(input.clone()); assert_eq!(output.s, input.s); assert_eq!(output.style.color(), Some(style::Color::Rgb(170, 0, 0))); } } mod bg { const OUTPUT: &[&'static str] = &[ "\x1b[41mtest\x1b[49m", "\x1b[41mtest\x1b[0m", "\x1b[41mtest\x1b[m", "\x1b[48;5;1mtest\x1b[49m", "\x1b[48;5;1mtest\x1b[0m", "\x1b[48;5;1mtest\x1b[m", ]; fn input() -> text_style::StyledStr<'static> { text_style::StyledStr::plain("test").on(text_style::AnsiColor::Red.dark()) } test_cases! { [input(); OUTPUT] ansi_term, crossterm, termion, } #[test] fn cursive() { use cursive::{theme, utils::markup}; let input = input(); let output = markup::StyledString::styled( "test", theme::ColorStyle::new( theme::ColorType::InheritParent, theme::Color::Dark(theme::BaseColor::Red), ), ); assert_eq!(output, markup::StyledString::from(input)); } }