use core::{
cell::Cell,
fmt::{self, Display, Formatter},
};
use crate::{Literator, fmt::repeat};
pub struct InlineBlock<I, Open, Delim, Close> {
iter: Cell<Option<I>>,
open: Open,
delim: Delim,
close: Close,
}
impl<I, Open, Delim, Close> InlineBlock<I, Open, Delim, Close>
where
I: Literator,
Open: Display,
Delim: Display,
Close: Display,
{
pub(super) fn new(iter: I, open: Open, delim: Delim, close: Close) -> Self {
InlineBlock {
iter: Cell::new(Some(iter)),
open,
delim,
close,
}
}
pub(crate) fn do_fmt<F>(&self, f: &mut Formatter, fmt_item: F) -> fmt::Result
where
F: Fn(&I::Item, &mut Formatter) -> fmt::Result,
{
let Self {
iter,
open,
delim,
close,
} = self;
let Some(mut iter) = iter.take() else {
return Ok(());
};
write!(f, "{open}")?;
if let Some(first) = iter.next() {
f.write_str(" ")?;
fmt_item(&first, f)?;
for item in iter {
write!(f, "{delim}")?;
fmt_item(&item, f)?;
}
f.write_str(" ")?;
}
write!(f, "{close}")
}
}
impl<I, Open, Delim, Close> Clone for InlineBlock<I, Open, Delim, Close>
where
I: Copy,
Open: Clone,
Delim: Clone,
Close: Clone,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
open: self.open.clone(),
delim: self.delim.clone(),
close: self.close.clone(),
}
}
}
pub struct IndentedBlock<I, Open, Close, Indentation, Newline> {
iter: Cell<Option<I>>,
open: Open,
close: Close,
indentation: Indentation,
newline: Newline,
inner_level: usize,
}
impl<I, Open, Close, Indentation, Newline> IndentedBlock<I, Open, Close, Indentation, Newline>
where
I: Iterator,
Open: Display,
Close: Display,
Indentation: Display,
Newline: Display,
{
pub(super) fn new(
iter: I,
open: Open,
close: Close,
indentation: Indentation,
newline: Newline,
inner_level: usize,
) -> Self {
Self {
iter: Cell::new(Some(iter)),
open,
close,
indentation,
newline,
inner_level,
}
}
pub(crate) fn do_fmt<F>(&self, f: &mut Formatter, fmt_item: F) -> fmt::Result
where
F: Fn(&I::Item, &mut Formatter) -> fmt::Result,
{
let Self {
iter,
open,
close,
indentation,
newline,
inner_level,
} = self;
let Some(mut iter) = iter.take() else {
return Ok(());
};
write!(f, "{open}")?;
if let Some(first) = iter.next() {
let item_ident = repeat(indentation, *inner_level);
write!(f, "{newline}{item_ident}")?;
fmt_item(&first, f)?;
write!(f, "{newline}")?;
for item in iter {
write!(f, "{item_ident}")?;
fmt_item(&item, f)?;
write!(f, "{newline}")?;
}
write!(f, "{}", repeat(indentation, (*inner_level).max(1) - 1))?;
}
write!(f, "{close}")
}
}
impl<I, Open, Close, Indentation, Newline> Clone
for IndentedBlock<I, Open, Close, Indentation, Newline>
where
I: Copy,
Open: Clone,
Close: Clone,
Indentation: Clone,
Newline: Clone,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
open: self.open.clone(),
close: self.close.clone(),
indentation: self.indentation.clone(),
newline: self.newline.clone(),
inner_level: self.inner_level.clone(),
}
}
}