forked from libre-chip/fayalite
117 lines
2.7 KiB
Rust
117 lines
2.7 KiB
Rust
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// See Notices.txt for copyright information
|
|
|
|
use std::{
|
|
fmt::{self, Write as _},
|
|
marker::PhantomData,
|
|
};
|
|
|
|
struct IndentState {
|
|
indent: usize,
|
|
need_indent: bool,
|
|
buf: String,
|
|
}
|
|
|
|
thread_local! {
|
|
static INDENT_STATE: std::cell::RefCell<IndentState> = const {
|
|
std::cell::RefCell::new(IndentState {
|
|
indent: 0,
|
|
need_indent: true,
|
|
buf: String::new(),
|
|
})
|
|
};
|
|
}
|
|
|
|
struct IndentedOut;
|
|
|
|
impl fmt::Write for IndentedOut {
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
INDENT_STATE.with_borrow_mut(|state| {
|
|
let IndentState {
|
|
indent,
|
|
need_indent,
|
|
buf,
|
|
} = state;
|
|
buf.clear();
|
|
for ch in s.chars() {
|
|
if ch == '\n' {
|
|
*need_indent = true;
|
|
} else {
|
|
if *need_indent {
|
|
*need_indent = false;
|
|
for _ in 0..*indent {
|
|
buf.push_str(" ");
|
|
}
|
|
}
|
|
}
|
|
buf.push(ch)
|
|
}
|
|
std::print!("{buf}");
|
|
});
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub(crate) struct PushIndent(PhantomData<*const ()>);
|
|
|
|
impl Drop for PushIndent {
|
|
fn drop(&mut self) {
|
|
let _ = INDENT_STATE.try_with(|state| state.borrow_mut().indent -= 1);
|
|
}
|
|
}
|
|
|
|
impl PushIndent {
|
|
#[allow(unused)]
|
|
pub(crate) fn new() -> Self {
|
|
INDENT_STATE.with_borrow_mut(|state| state.indent += 1);
|
|
Self(PhantomData)
|
|
}
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub(crate) fn indented_print_fmt<const LN: bool>(args: fmt::Arguments<'_>) {
|
|
if LN {
|
|
writeln!(IndentedOut, "{args}").expect("writing can't fail")
|
|
} else {
|
|
IndentedOut.write_fmt(args).expect("writing can't fail")
|
|
}
|
|
}
|
|
|
|
#[allow(unused)]
|
|
macro_rules! indented_print {
|
|
($($args:tt)*) => {
|
|
$crate::util::indented_print::indented_print_fmt::<false>($crate::__std::format_args!($($args)*))
|
|
};
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub(crate) use indented_print;
|
|
|
|
#[allow(unused)]
|
|
macro_rules! indented_println {
|
|
($($args:tt)*) => {
|
|
$crate::util::indented_print::indented_print_fmt::<true>($crate::__std::format_args!($($args)*))
|
|
};
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub(crate) use indented_println;
|
|
|
|
#[allow(unused)]
|
|
macro_rules! indented_dbg {
|
|
($expr:expr) => {{
|
|
let v = $expr;
|
|
$crate::util::indented_print::indented_println!(
|
|
"[{}:{}:{}] {} = {v:#?}",
|
|
file!(),
|
|
line!(),
|
|
column!(),
|
|
stringify!($expr),
|
|
);
|
|
v
|
|
}};
|
|
}
|
|
|
|
#[allow(unused)]
|
|
pub(crate) use indented_dbg;
|