1use core::fmt;
2
3use gramatika::{DebugLisp, Span, Spanned, Substr, Token as _};
4
5use crate::{token::Token, utils::join_substrs};
6
7pub struct Text(pub Substr, pub Span);
8
9impl Text {
10 pub fn content(&self) -> &str {
11 self.0.as_str()
12 }
13
14 pub fn append(&mut self, token: Token) {
15 self.0 = join_substrs(&self.0, &token.lexeme());
16 self.1 = self.1.through(token.span());
17 }
18
19 pub fn concat(mut self, token: Token) -> Self {
20 self.0 = join_substrs(&self.0, &token.lexeme());
21 self.1 = self.1.through(token.span());
22 self
23 }
24}
25
26impl From<Token> for Text {
27 fn from(value: Token) -> Self {
28 Self(value.lexeme(), value.span())
29 }
30}
31
32impl Spanned for Text {
33 fn span(&self) -> Span {
34 self.1
35 }
36}
37
38impl DebugLisp for Text {
39 fn fmt(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
40 let span = self.span();
41
42 if span.end.line > span.start.line && f.alternate() {
43 writeln!(f, r#"(Text """"#)?;
44 for (idx, line) in self.0.lines().enumerate() {
45 writeln!(
46 f,
47 "{}{:>4} | {line}",
48 gramatika::debug::INDENT.repeat(indent),
49 span.start.line + idx + 1,
50 )?;
51 }
52 write!(f, r#"{}""")"#, gramatika::debug::INDENT.repeat(indent))?;
53 } else if f.alternate() {
54 writeln!(f, r#"(Text"#)?;
55 writeln!(
56 f,
57 r#"{}`{}` ({span:?})"#,
58 gramatika::debug::INDENT.repeat(indent + 1),
59 self.content(),
60 )?;
61 write!(f, "{})", gramatika::debug::INDENT.repeat(indent))?;
62 } else {
63 write!(f, r#"(Text `{}` ({span:?}))"#, self.content())?;
64 }
65
66 Ok(())
67 }
68}
69
70impl fmt::Debug for Text {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 DebugLisp::fmt(self, f, 0)
73 }
74}
75
76impl fmt::Display for Text {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 write!(f, "{}", self.content())
79 }
80}