use std::fmt::Display;
use anstyle::{Color, Style};
use crate::generator::{
Tag, TagConvertor,
helper::{FlattenableSpan, FlattenableStyle},
};
#[derive(Debug, Clone)]
pub struct StyledSpan<'a> {
style: Style,
text: &'a str,
}
impl<'a> StyledSpan<'a> {
pub fn new(style: Style, text: &'a str) -> Self {
Self { style, text }
}
pub fn style(&self) -> &Style {
&self.style
}
pub fn text(&self) -> &'a str {
self.text
}
}
impl Display for StyledSpan<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}{:#}", self.style, self.text, self.style)
}
}
#[derive(Debug, Clone)]
pub struct StyledText<'a> {
spans: Vec<StyledSpan<'a>>,
}
impl<'a> StyledText<'a> {
pub fn new(spans: Vec<StyledSpan<'a>>) -> Self {
Self { spans }
}
pub fn spans(&self) -> &[StyledSpan<'a>] {
&self.spans
}
}
impl Display for StyledText<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for span in &self.spans {
Display::fmt(span, f)?;
}
Ok(())
}
}
impl<'a> From<Vec<StyledSpan<'a>>> for StyledText<'a> {
fn from(spans: Vec<StyledSpan<'a>>) -> Self {
Self::new(spans)
}
}
impl<'a, C> From<Tag<'a, C>> for Style
where
C: TagConvertor<'a, Color = Color, Modifier = Style, Custom = Style>,
{
fn from(t: Tag<'a, C>) -> Self {
match t {
Tag::Fg(c) => Self::new().fg_color(Some(c)),
Tag::Bg(c) => Self::new().bg_color(Some(c)),
Tag::Modifier(s) | Tag::Custom(s) => s,
}
}
}
impl FlattenableStyle for Style {
fn patch(self, other: Self) -> Self {
Self::new()
.fg_color(other.get_fg_color().or(self.get_fg_color()))
.bg_color(other.get_bg_color().or(self.get_bg_color()))
.effects(self.get_effects() | other.get_effects())
}
}
impl<'a> FlattenableSpan<'a, Style> for StyledSpan<'a> {
fn with_style(s: &'a str, style: Option<Style>) -> Self {
Self::new(style.unwrap_or_default(), s)
}
}