use core::fmt;
use gramatika::{DebugLisp, Span, Spanned, Substr, Token as _};
use crate::{token::Token, utils::join_substrs};
pub struct Text(pub Substr, pub Span);
impl Text {
pub fn content(&self) -> &str {
self.0.as_str()
}
pub fn append(&mut self, token: Token) {
self.0 = join_substrs(&self.0, &token.lexeme());
self.1 = self.1.through(token.span());
}
pub fn concat(mut self, token: Token) -> Self {
self.0 = join_substrs(&self.0, &token.lexeme());
self.1 = self.1.through(token.span());
self
}
}
impl From<Token> for Text {
fn from(value: Token) -> Self {
Self(value.lexeme(), value.span())
}
}
impl Spanned for Text {
fn span(&self) -> Span {
self.1
}
}
impl DebugLisp for Text {
fn fmt(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
let span = self.span();
if span.end.line > span.start.line && f.alternate() {
writeln!(f, r#"(Text """"#)?;
for (idx, line) in self.0.lines().enumerate() {
writeln!(
f,
"{}{:>4} | {line}",
gramatika::debug::INDENT.repeat(indent),
span.start.line + idx + 1,
)?;
}
write!(f, r#"{}""")"#, gramatika::debug::INDENT.repeat(indent))?;
} else if f.alternate() {
writeln!(f, r#"(Text"#)?;
writeln!(
f,
r#"{}`{}` ({span:?})"#,
gramatika::debug::INDENT.repeat(indent + 1),
self.content(),
)?;
write!(f, "{})", gramatika::debug::INDENT.repeat(indent))?;
} else {
write!(f, r#"(Text `{}` ({span:?}))"#, self.content())?;
}
Ok(())
}
}
impl fmt::Debug for Text {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
DebugLisp::fmt(self, f, 0)
}
}
impl fmt::Display for Text {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.content())
}
}