use super::{
Span, TextError,
ansi::{self, ParseMode},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Line {
spans: Vec<Span>,
}
impl Line {
pub fn from_plain(content: impl Into<String>) -> Result<Self, TextError> {
let content = content.into();
let spans = if content.is_empty() {
Vec::new()
} else {
vec![Span::plain(content)?]
};
Ok(Self { spans })
}
pub fn from_raw_lossy(content: impl AsRef<str>) -> Result<Self, TextError> {
single_line(ansi::parse_text(content.as_ref(), ParseMode::Raw)?)
}
pub fn from_ansi(content: impl AsRef<str>) -> Result<Self, TextError> {
single_line(ansi::parse_text(content.as_ref(), ParseMode::Ansi)?)
}
pub fn from_spans(spans: Vec<Span>) -> Self {
Self { spans }
}
pub fn spans(&self) -> &[Span] {
&self.spans
}
pub(crate) fn into_spans(self) -> Vec<Span> {
self.spans
}
pub fn plain_content(&self) -> String {
let content_len = self.spans.iter().map(|span| span.content().len()).sum();
let mut content = String::with_capacity(content_len);
for span in &self.spans {
content.push_str(span.content());
}
content
}
pub fn display_width(&self) -> usize {
self.spans.iter().map(Span::display_width).sum()
}
}
fn single_line(lines: Vec<Line>) -> Result<Line, TextError> {
let [line] = lines.try_into().map_err(|_| TextError::MultipleLines)?;
Ok(line)
}