use std::marker::PhantomData;
use crate::syntax::{Blocks, Comments, Literals};
pub struct Code<L> {
out: String,
depth: usize,
lang: PhantomData<L>,
}
impl<L: Blocks + Comments + Literals> Code<L> {
pub fn new() -> Self {
Self::starting(String::new())
}
pub fn starting(text: impl Into<String>) -> Self {
Self {
out: text.into(),
depth: 0,
lang: PhantomData,
}
}
pub fn str(&self, text: &str) -> String {
L::string(text)
}
pub fn line(&mut self, text: impl AsRef<str>) -> &mut Self {
for _ in 0..self.depth {
self.out.push_str(L::INDENT);
}
self.out.push_str(text.as_ref());
self.out.push('\n');
self
}
pub fn blank(&mut self) -> &mut Self {
self.out.push('\n');
self
}
pub fn doc(&mut self, text: impl AsRef<str>) -> &mut Self {
self.line(L::doc(text.as_ref()))
}
pub fn open(&mut self, head: impl AsRef<str>) -> &mut Self {
self.line(L::open(head.as_ref()));
self.depth += 1;
self
}
pub fn close(&mut self, tail: &str) -> &mut Self {
self.depth = self.depth.saturating_sub(1);
self.line(L::close(tail))
}
pub fn finish(self) -> String {
self.out
}
}
impl<L: Blocks + Comments + Literals> Default for Code<L> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests;