use core::fmt;
use crate::style::*;
use crate::{Styled, WithLink, WithoutLink};
macro_rules! impl_fmt_styled {
($($trait:path)*) => {
$(
impl<T: $trait> $trait for Styled<T, WithoutLink> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write_style(f, self.style)?;
self.value.fmt(f)?;
f.write_str("\x1b[0m")
}
}
)*
};
}
macro_rules! impl_fmt_styled_link {
($($trait:path)*) => {
$(
impl<T: $trait, Uri: fmt::Display> $trait for Styled<T, WithLink<Uri>> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("\x1b]8;;")?;
self.link.0.fmt(f)?;
f.write_str("\x1b\\")?;
self.value.fmt(f)?;
f.write_str("\x1b]8;;\x1b\\")
}
}
)*
};
}
impl_fmt_styled!(
fmt::Display
fmt::Octal
fmt::LowerHex
fmt::UpperHex
fmt::Pointer
fmt::Binary
fmt::LowerExp
fmt::UpperExp
);
impl_fmt_styled_link!(
fmt::Display
fmt::Octal
fmt::LowerHex
fmt::UpperHex
fmt::Pointer
fmt::Binary
fmt::LowerExp
fmt::UpperExp
);
impl fmt::Display for Style {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write_style(f, *self)
}
}
fn write_style(f: &mut fmt::Formatter, style: Style) -> fmt::Result {
f.write_str("\x1b[0")?;
write_fg_color(f, style.fg)?;
write_bg_color(f, style.bg)?;
write_underline_color(f, style.underline)?;
write_attributes(f, style.attributes)?;
f.write_str("m")
}
fn write_underline_color(f: &mut fmt::Formatter, color: Color) -> fmt::Result {
use fmt::Display;
match color {
Color::Default => Ok(()),
Color::Basic(color) => match color {
BasicColor::Black => f.write_str(";58;5;0"),
BasicColor::Red => f.write_str(";58;5;1"),
BasicColor::Green => f.write_str(";58;5;2"),
BasicColor::Yellow => f.write_str(";58;5;3"),
BasicColor::Blue => f.write_str(";58;5;4"),
BasicColor::Magenta => f.write_str(";58;5;5"),
BasicColor::Cyan => f.write_str(";58;5;6"),
BasicColor::White => f.write_str(";58;5;7"),
BasicColor::BrightBlack => f.write_str(";58;5;8"),
BasicColor::BrightRed => f.write_str(";58;5;9"),
BasicColor::BrightGreen => f.write_str(";58;5;10"),
BasicColor::BrightYellow => f.write_str(";58;5;11"),
BasicColor::BrightBlue => f.write_str(";58;5;12"),
BasicColor::BrightMagenta => f.write_str(";58;5;13"),
BasicColor::BrightCyan => f.write_str(";58;5;14"),
BasicColor::BrightWhite => f.write_str(";58;5;15"),
},
Color::Extended(i) => {
f.write_str(";58;5;")?;
i.fmt(f)
}
Color::Rgb(r, g, b) => {
f.write_str(";58;2;")?;
r.fmt(f)?;
f.write_str(";")?;
g.fmt(f)?;
f.write_str(";")?;
b.fmt(f)
}
}
}
macro_rules! impl_write_color {
($name:ident $prefix:literal $bright_prefix:literal) => {
#[inline]
fn $name(f: &mut fmt::Formatter, color: Color) -> fmt::Result {
use fmt::Display;
match color {
Color::Default => Ok(()),
Color::Basic(color) => match color {
BasicColor::Black => f.write_str(concat!(";", $prefix, "0")),
BasicColor::Red => f.write_str(concat!(";", $prefix, "1")),
BasicColor::Green => f.write_str(concat!(";", $prefix, "2")),
BasicColor::Yellow => f.write_str(concat!(";", $prefix, "3")),
BasicColor::Blue => f.write_str(concat!(";", $prefix, "4")),
BasicColor::Magenta => f.write_str(concat!(";", $prefix, "5")),
BasicColor::Cyan => f.write_str(concat!(";", $prefix, "6")),
BasicColor::White => f.write_str(concat!(";", $prefix, "7")),
BasicColor::BrightBlack => f.write_str(concat!(";", $bright_prefix, "0")),
BasicColor::BrightRed => f.write_str(concat!(";", $bright_prefix, "1")),
BasicColor::BrightGreen => f.write_str(concat!(";", $bright_prefix, "2")),
BasicColor::BrightYellow => f.write_str(concat!(";", $bright_prefix, "3")),
BasicColor::BrightBlue => f.write_str(concat!(";", $bright_prefix, "4")),
BasicColor::BrightMagenta => f.write_str(concat!(";", $bright_prefix, "5")),
BasicColor::BrightCyan => f.write_str(concat!(";", $bright_prefix, "6")),
BasicColor::BrightWhite => f.write_str(concat!(";", $bright_prefix, "7")),
},
Color::Extended(i) => {
f.write_str(concat!(";", $prefix, "8;5;"))?;
i.fmt(f)
}
Color::Rgb(r, g, b) => {
f.write_str(concat!(";", $prefix, "8;2;"))?;
r.fmt(f)?;
f.write_str(";")?;
g.fmt(f)?;
f.write_str(";")?;
b.fmt(f)
}
}
}
};
}
impl_write_color!(write_fg_color "3" "9");
impl_write_color!(write_bg_color "4" "10");
fn write_attributes(f: &mut fmt::Formatter, attributes: Attributes) -> fmt::Result {
f.write_str(ATTRIBUTE_LOOKUP[attributes.into_u8() as usize])
}
const ATTRIBUTE_LOOKUP: [&str; 256] = [
"",
";1",
";2",
";2;1",
";3",
";3;1",
";3;2",
";3;2;1",
";4",
";4;1",
";4;2",
";4;2;1",
";4;3",
";4;3;1",
";4;3;2",
";4;3;2;1",
";5",
";5;1",
";5;2",
";5;2;1",
";5;3",
";5;3;1",
";5;3;2",
";5;3;2;1",
";5;4",
";5;4;1",
";5;4;2",
";5;4;2;1",
";5;4;3",
";5;4;3;1",
";5;4;3;2",
";5;4;3;2;1",
";7",
";7;1",
";7;2",
";7;2;1",
";7;3",
";7;3;1",
";7;3;2",
";7;3;2;1",
";7;4",
";7;4;1",
";7;4;2",
";7;4;2;1",
";7;4;3",
";7;4;3;1",
";7;4;3;2",
";7;4;3;2;1",
";7;5",
";7;5;1",
";7;5;2",
";7;5;2;1",
";7;5;3",
";7;5;3;1",
";7;5;3;2",
";7;5;3;2;1",
";7;5;4",
";7;5;4;1",
";7;5;4;2",
";7;5;4;2;1",
";7;5;4;3",
";7;5;4;3;1",
";7;5;4;3;2",
";7;5;4;3;2;1",
";8",
";8;1",
";8;2",
";8;2;1",
";8;3",
";8;3;1",
";8;3;2",
";8;3;2;1",
";8;4",
";8;4;1",
";8;4;2",
";8;4;2;1",
";8;4;3",
";8;4;3;1",
";8;4;3;2",
";8;4;3;2;1",
";8;5",
";8;5;1",
";8;5;2",
";8;5;2;1",
";8;5;3",
";8;5;3;1",
";8;5;3;2",
";8;5;3;2;1",
";8;5;4",
";8;5;4;1",
";8;5;4;2",
";8;5;4;2;1",
";8;5;4;3",
";8;5;4;3;1",
";8;5;4;3;2",
";8;5;4;3;2;1",
";8;7",
";8;7;1",
";8;7;2",
";8;7;2;1",
";8;7;3",
";8;7;3;1",
";8;7;3;2",
";8;7;3;2;1",
";8;7;4",
";8;7;4;1",
";8;7;4;2",
";8;7;4;2;1",
";8;7;4;3",
";8;7;4;3;1",
";8;7;4;3;2",
";8;7;4;3;2;1",
";8;7;5",
";8;7;5;1",
";8;7;5;2",
";8;7;5;2;1",
";8;7;5;3",
";8;7;5;3;1",
";8;7;5;3;2",
";8;7;5;3;2;1",
";8;7;5;4",
";8;7;5;4;1",
";8;7;5;4;2",
";8;7;5;4;2;1",
";8;7;5;4;3",
";8;7;5;4;3;1",
";8;7;5;4;3;2",
";8;7;5;4;3;2;1",
";9",
";9;1",
";9;2",
";9;2;1",
";9;3",
";9;3;1",
";9;3;2",
";9;3;2;1",
";9;4",
";9;4;1",
";9;4;2",
";9;4;2;1",
";9;4;3",
";9;4;3;1",
";9;4;3;2",
";9;4;3;2;1",
";9;5",
";9;5;1",
";9;5;2",
";9;5;2;1",
";9;5;3",
";9;5;3;1",
";9;5;3;2",
";9;5;3;2;1",
";9;5;4",
";9;5;4;1",
";9;5;4;2",
";9;5;4;2;1",
";9;5;4;3",
";9;5;4;3;1",
";9;5;4;3;2",
";9;5;4;3;2;1",
";9;7",
";9;7;1",
";9;7;2",
";9;7;2;1",
";9;7;3",
";9;7;3;1",
";9;7;3;2",
";9;7;3;2;1",
";9;7;4",
";9;7;4;1",
";9;7;4;2",
";9;7;4;2;1",
";9;7;4;3",
";9;7;4;3;1",
";9;7;4;3;2",
";9;7;4;3;2;1",
";9;7;5",
";9;7;5;1",
";9;7;5;2",
";9;7;5;2;1",
";9;7;5;3",
";9;7;5;3;1",
";9;7;5;3;2",
";9;7;5;3;2;1",
";9;7;5;4",
";9;7;5;4;1",
";9;7;5;4;2",
";9;7;5;4;2;1",
";9;7;5;4;3",
";9;7;5;4;3;1",
";9;7;5;4;3;2",
";9;7;5;4;3;2;1",
";9;8",
";9;8;1",
";9;8;2",
";9;8;2;1",
";9;8;3",
";9;8;3;1",
";9;8;3;2",
";9;8;3;2;1",
";9;8;4",
";9;8;4;1",
";9;8;4;2",
";9;8;4;2;1",
";9;8;4;3",
";9;8;4;3;1",
";9;8;4;3;2",
";9;8;4;3;2;1",
";9;8;5",
";9;8;5;1",
";9;8;5;2",
";9;8;5;2;1",
";9;8;5;3",
";9;8;5;3;1",
";9;8;5;3;2",
";9;8;5;3;2;1",
";9;8;5;4",
";9;8;5;4;1",
";9;8;5;4;2",
";9;8;5;4;2;1",
";9;8;5;4;3",
";9;8;5;4;3;1",
";9;8;5;4;3;2",
";9;8;5;4;3;2;1",
";9;8;7",
";9;8;7;1",
";9;8;7;2",
";9;8;7;2;1",
";9;8;7;3",
";9;8;7;3;1",
";9;8;7;3;2",
";9;8;7;3;2;1",
";9;8;7;4",
";9;8;7;4;1",
";9;8;7;4;2",
";9;8;7;4;2;1",
";9;8;7;4;3",
";9;8;7;4;3;1",
";9;8;7;4;3;2",
";9;8;7;4;3;2;1",
";9;8;7;5",
";9;8;7;5;1",
";9;8;7;5;2",
";9;8;7;5;2;1",
";9;8;7;5;3",
";9;8;7;5;3;1",
";9;8;7;5;3;2",
";9;8;7;5;3;2;1",
";9;8;7;5;4",
";9;8;7;5;4;1",
";9;8;7;5;4;2",
";9;8;7;5;4;2;1",
";9;8;7;5;4;3",
";9;8;7;5;4;3;1",
";9;8;7;5;4;3;2",
";9;8;7;5;4;3;2;1",
];