use std::ops::Deref;
use tui::text::{Span as TuiSpan, Spans as TuiSpans};
use crate::style::Style;
#[derive(Default, Clone)]
pub struct Span {
pub text: String,
pub style: Style,
}
impl Span {
pub fn new<Str: Into<String>, Sty: Into<Style>>(text: Str, style: Sty) -> Self {
Self {
text: text.into(),
style: style.into(),
}
}
pub fn len(&self) -> usize {
self.text.len()
}
}
impl<S: Into<String>> From<S> for Span {
fn from(s: S) -> Self {
Self {
text: s.into(),
style: Style::default(),
}
}
}
impl<'a> From<&'a Span> for TuiSpan<'a> {
fn from(span: &'a Span) -> Self {
Self {
content: (&span.text).into(),
style: span.style.into(),
}
}
}
impl From<Span> for TuiSpan<'_> {
fn from(span: Span) -> Self {
Self {
content: span.text.into(),
style: span.style.into(),
}
}
}
#[derive(Default, Clone)]
pub struct Spans(pub Vec<Span>);
impl Spans {
pub fn new(spans: Vec<Span>) -> Self {
Self(spans)
}
pub fn len(&self) -> usize {
self.0.iter().map(|span| span.len()).sum()
}
}
impl<S: Into<Span>> From<S> for Spans {
fn from(s: S) -> Self {
Spans(vec![s.into()])
}
}
impl<'a> From<&'a Spans> for Spans {
fn from(spans: &'a Spans) -> Self {
spans.clone()
}
}
impl<'a> From<&'a Spans> for TuiSpans<'a> {
fn from(spans: &'a Spans) -> Self {
TuiSpans(spans.0.iter().map(TuiSpan::from).collect())
}
}
impl From<Spans> for TuiSpans<'_> {
fn from(spans: Spans) -> Self {
TuiSpans(spans.0.into_iter().map(TuiSpan::from).collect())
}
}
impl Deref for Spans {
type Target = Vec<Span>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone, Default)]
pub struct Lines(pub Vec<Spans>);
impl<S: Into<Spans>> From<S> for Lines {
fn from(spans: S) -> Self {
let mut expanded = Vec::new();
for span in spans.into().0 {
let lines: Vec<&str> = span.text.split('\n').collect();
expanded.push(Some(Span::new(lines[0], span.style)));
for line in &lines[1..] {
expanded.push(None);
expanded.push(Some(Span::new(*line, span.style)));
}
}
let split = expanded
.split(|span| span.is_none())
.map(|spans| Spans::new(spans.iter().flatten().cloned().collect::<Vec<Span>>()))
.collect();
Lines(split)
}
}