fayalite/crates/fayalite/src/util/indented_print.rs

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;