use crate::{color::Color, papergrid::util::string_width};
#[cfg_attr(docsrs, doc(cfg(feature = "color")))]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Symbol {
c: char,
color: Option<Color>,
}
impl Symbol {
pub const fn new(c: char, color: Option<Color>) -> Self {
Self { c, color }
}
pub fn ansi(s: impl AsRef<str>) -> Option<Self> {
let s = s.as_ref();
let mut chars = s.chars();
let c = chars.next();
let no_other_chars = chars.next().is_none();
drop(chars);
match c {
Some(c) if no_other_chars => return Some(Self::new(c, None)),
_ => (),
}
if string_width(s) != 1 {
return None;
}
let (c, start, end) = get_ansi_secuences(s)?;
if start.is_empty() && end.is_empty() {
return Some(Self::new(c, None));
}
Some(Self::new(c, Some(Color::new(start, end))))
}
pub const fn from_char(c: char) -> Self {
Self::new(c, None)
}
pub const fn c(&self) -> char {
self.c
}
pub fn color(&self) -> Option<&Color> {
self.color.as_ref()
}
}
impl Default for Symbol {
fn default() -> Self {
Self::from_char(char::default())
}
}
impl From<char> for Symbol {
fn from(c: char) -> Self {
Self::from_char(c)
}
}
fn get_ansi_secuences(s: &str) -> Option<(char, String, String)> {
let mut original = ansi_str::get_blocks(s);
let block = original.next()?;
let c = block.text().chars().next()?;
let start = block.start().to_string();
let end = block.end().to_string();
Some((c, start, end))
}