use std::fmt;
pub use crate::ast::module::ItemId;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Style {
Keyword,
Type,
Name,
Literal,
Comment,
Punctuation,
Default,
}
pub trait Printer {
fn write_str(&mut self, s: &str);
fn newline(&mut self, offset: Option<usize>);
fn push_style(&mut self, style: Style);
fn pop_style(&mut self);
fn begin_xref(&mut self, xref: ItemId);
fn end_xref(&mut self);
fn indent(&mut self);
fn dedent(&mut self);
}
pub struct PlainTextPrinter {
output: String,
indent_level: usize,
at_line_start: bool,
}
impl PlainTextPrinter {
pub fn new() -> Self {
PlainTextPrinter {
output: String::new(),
indent_level: 0,
at_line_start: true,
}
}
pub fn output(&self) -> &str {
&self.output
}
pub fn into_output(self) -> String {
self.output
}
fn write_indent(&mut self) {
if self.at_line_start {
let capped = self.indent_level.min(50);
for _ in 0..capped {
self.output.push_str(" ");
}
self.at_line_start = false;
}
}
}
impl Default for PlainTextPrinter {
fn default() -> Self {
Self::new()
}
}
impl Printer for PlainTextPrinter {
fn write_str(&mut self, s: &str) {
self.write_indent();
self.output.push_str(s);
}
fn newline(&mut self, _offset: Option<usize>) {
self.output.push('\n');
self.at_line_start = true;
}
fn push_style(&mut self, _style: Style) {}
fn pop_style(&mut self) {}
fn begin_xref(&mut self, _xref: ItemId) {}
fn end_xref(&mut self) {}
fn indent(&mut self) {
self.indent_level += 1;
}
fn dedent(&mut self) {
self.indent_level = self.indent_level.saturating_sub(1);
}
}
impl fmt::Write for PlainTextPrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
Printer::write_str(self, s);
Ok(())
}
}