use core::fmt::{self, Display};
use crate::{ansi, mode::Stream, Effect, OptionalColor, Style, StyledValue};
impl<T, F, B, U> StyledValue<T, F, B, U> {
#[inline]
pub const fn new(value: T, style: Style<F, B, U>, stream: Option<Stream>) -> Self {
Self {
value,
style,
stream,
}
}
}
macro_rules! AnsiColorMethods {
(
($(#[$fg:meta] #[$bg:meta] $color:ident $fun:ident $into_fun:ident $on_fun:ident $into_on_fun:ident)*)
($(#[$doc:meta] $effect:ident $effect_fun:ident $into_effect_fun:ident)*)
) => {
pub trait Colorize {
#[inline]
fn into_style(self) -> StyledValue<Self>
where
Self: Sized,
{
StyledValue {
value: self,
style: Style::new(),
stream: None,
}
}
#[inline]
fn style(&self) -> StyledValue<&Self> {
StyledValue {
value: self,
style: Style::new(),
stream: None
}
}
#[inline]
fn into_style_with<F, B, U>(self, style: Style<F, B, U>) -> StyledValue<Self, F, B, U>
where
Self: Sized,
{
StyledValue {
value: self,
style,
stream: None,
}
}
#[inline]
fn style_with<F, B, U>(&self, style: Style<F, B, U>) -> StyledValue<&Self, F, B, U> {
StyledValue {
value: self,
style,
stream: None,
}
}
#[inline]
fn fg<C>(&self, color: C) -> StyledValue<&Self, C> {
self.style().fg(color)
}
#[inline]
fn into_fg<C>(self, color: C) -> StyledValue<Self, C> where Self: Sized {
self.into_style().fg(color)
}
#[inline]
fn bg<C>(&self, color: C) -> StyledValue<&Self, crate::NoColor, C> {
self.style().bg(color)
}
#[inline]
fn into_bg<C>(self, color: C) -> StyledValue<Self, crate::NoColor, C> where Self: Sized {
self.into_style().bg(color)
}
#[inline]
fn underline_color<C>(&self, color: C) -> StyledValue<&Self, crate::NoColor, crate::NoColor, C> {
self.style().underline_color(color)
}
#[inline]
fn into_underline_color<C>(self, color: C) -> StyledValue<Self, crate::NoColor, crate::NoColor, C> where Self: Sized {
self.into_style().underline_color(color)
}
$(#[$fg] #[inline] fn $fun(&self) -> StyledValue<&Self, ansi::$color> {
self.style().$fun()
})*
$(#[$bg] #[inline] fn $on_fun(&self) -> StyledValue<&Self, crate::NoColor, ansi::$color> {
self.style().$on_fun()
})*
$(#[$fg] #[inline] fn $into_fun(self) -> StyledValue<Self, ansi::$color> where Self: Sized{
self.into_style().$fun()
})*
$(#[$bg] #[inline] fn $into_on_fun(self) -> StyledValue<Self, crate::NoColor, ansi::$color> where Self: Sized {
self.into_style().$on_fun()
})*
$(#[$doc] #[inline] fn $effect_fun(&self) -> StyledValue<&Self> {
self.style().$effect_fun()
})*
$(#[$doc] #[inline] fn $into_effect_fun(self) -> StyledValue<Self> where Self: Sized {
self.into_style().$effect_fun()
})*
}
impl<T, F: OptionalColor, B: OptionalColor, U: OptionalColor> StyledValue<T, F, B, U> {
#[inline]
pub const fn style(&self) -> StyledValue<&Self> {
StyledValue {
value: self,
style: Style::new(),
stream: None,
}
}
#[inline]
pub const fn into_style(self) -> StyledValue<Self> {
StyledValue {
value: self,
style: Style::new(),
stream: None,
}
}
#[inline]
pub fn fg<C>(self, color: C) -> StyledValue<T, C, B, U> {
StyledValue {
value: self.value,
style: self.style.fg(color),
stream: self.stream,
}
}
#[inline]
pub fn bg<C>(self, color: C) -> StyledValue<T, F, C, U> {
StyledValue {
value: self.value,
style: self.style.bg(color),
stream: self.stream,
}
}
#[inline]
pub fn underline_color<C>(self, color: C) -> StyledValue<T ,F, B, C> {
StyledValue {
value: self.value,
style: self.style.underline_color(color),
stream: self.stream,
}
}
$(#[inline] #[$fg] pub fn $fun(self) -> StyledValue<T, ansi::$color, B, U> {
self.fg(ansi::$color)
})*
$(#[inline] #[$bg] pub fn $on_fun(self) -> StyledValue<T, F, ansi::$color, U> {
self.bg(ansi::$color)
})*
$(#[inline] #[$doc] pub fn $effect_fun(self) -> StyledValue<T, F, B, U> {
StyledValue {
value: self.value,
style: self.style.with(Effect::$effect),
stream: self.stream,
}
})*
#[inline]
pub const fn stream(mut self, stream: Stream) -> Self {
self.stream = Some(stream);
self
}
#[inline]
pub const fn stream_opt(mut self, stream: Option<Stream>) -> Self {
self.stream = stream;
self
}
}
const fn _all_effects_accounted_for(e: Effect) {
match e {
$(Effect::$effect => (),)*
}
}
};
}
AnsiColorMethods! {
(
Black black into_black on_black into_on_black
Red red into_red on_red into_on_red
Green green into_green on_green into_on_green
Yellow yellow into_yellow on_yellow into_on_yellow
Blue blue into_blue on_blue into_on_blue
Magenta magenta into_magenta on_magenta into_on_magenta
Cyan cyan into_cyan on_cyan into_on_cyan
White white into_white on_white into_on_white
BrightBlack bright_black into_bright_black on_bright_black into_on_bright_black
BrightRed bright_red into_bright_red on_bright_red into_on_bright_red
BrightGreen bright_green into_bright_green on_bright_green into_on_bright_green
BrightYellow bright_yellow into_bright_yellow on_bright_yellow into_on_bright_yellow
BrightBlue bright_blue into_bright_blue on_bright_blue into_on_bright_blue
BrightMagenta bright_magenta into_bright_magenta on_bright_magenta into_on_bright_magenta
BrightCyan bright_cyan into_bright_cyan on_bright_cyan into_on_bright_cyan
BrightWhite bright_white into_bright_white on_bright_white into_on_bright_white
)
(
Bold bold into_bold
Dimmed dimmed into_dimmed
Italic italics into_italics
Underline underline into_underline
DoubleUnderline double_underline into_double_underline
Blink blink into_blink
BlinkFast blink_fast into_blink_fast
Reversed reverse into_reverse
Hidden hide into_hide
Strikethrough strikethrough into_strikethrough
Overline overline into_overline
SuperScript superscript into_superscript
SubScript subscript into_subscript
)
}
impl<T, F: OptionalColor, B: OptionalColor, U: OptionalColor> StyledValue<T, F, B, U> {
#[inline]
pub fn fmt_with(
&self,
fmt: &mut fmt::Formatter<'_>,
f: impl FnOnce(&T, &mut fmt::Formatter<'_>) -> fmt::Result,
) -> fmt::Result {
let use_colors = self.style.should_color(self.stream);
if use_colors {
self.style.apply().fmt(fmt)?;
}
f(&self.value, fmt)?;
if use_colors {
self.style.clear().fmt(fmt)?;
}
Ok(())
}
}
macro_rules! fmt_impl {
($name:ident) => {
impl<T: fmt::$name, F: OptionalColor, B: OptionalColor, U: OptionalColor> fmt::$name
for StyledValue<T, F, B, U>
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.fmt_with(f, fmt::$name::fmt)
}
}
};
}
fmt_impl!(Display);
fmt_impl!(Debug);
fmt_impl!(Binary);
fmt_impl!(Octal);
fmt_impl!(Pointer);
fmt_impl!(LowerExp);
fmt_impl!(UpperExp);
fmt_impl!(LowerHex);
fmt_impl!(UpperHex);