use crate::ArcStr;
use std::fmt::Write;
const N: usize = 10;
#[derive(Debug)]
pub struct CodeFormatter<'a, F> {
f: &'a mut F,
level: usize,
indentation_lut: [ArcStr; N],
}
impl<F: Write> Write for CodeFormatter<'_, F> {
#[inline]
fn write_str(&mut self, s: &str) -> std::fmt::Result {
write!(
self.f,
"{}",
s.replace(
'\n',
format!(
"\n{}",
if self.level >= N {
&self.indentation_lut[N - 1]
} else {
&self.indentation_lut[self.level]
}
)
.as_str()
)
)
}
}
impl<'a, T: Write> CodeFormatter<'a, T> {
#[inline]
pub fn new<S: Into<ArcStr>>(f: &'a mut T, indentation: S) -> Self {
let indentation: ArcStr = indentation.into();
Self {
f,
level: 0,
indentation_lut: [
indentation.repeat(0).into(),
indentation.repeat(1).into(),
indentation.repeat(2).into(),
indentation.repeat(3).into(),
indentation.repeat(4).into(),
indentation.repeat(5).into(),
indentation.repeat(6).into(),
indentation.repeat(7).into(),
indentation.repeat(8).into(),
indentation.repeat(9).into(),
],
}
}
#[inline]
pub fn set_level(&mut self, level: usize) {
self.level = level;
}
#[inline]
pub fn indent(&mut self, inc: usize) {
self.level = self.level.saturating_add(inc);
}
#[inline]
pub fn dedent(&mut self, inc: usize) {
self.level = self.level.saturating_sub(inc);
}
}