mod document;
mod print;
#[cfg(test)]
mod tests;
use alloc::string::String;
use core::fmt;
pub use self::document::{concat, const_text, display, flatten, indent, nl, split, text, Document};
pub trait PrettyPrint {
fn render(&self) -> Document;
fn to_pretty_string(&self) -> String {
format!("{:width$}", Prettier(self), width = 80)
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
let doc = self.render();
let width = f.width().unwrap_or(80);
print::pretty_print(&doc, width, f)
}
}
impl fmt::Display for dyn PrettyPrint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self, f)
}
}
#[macro_export]
macro_rules! pretty_via_display {
($name:ty) => {
impl $crate::prettier::PrettyPrint for $name {
fn render(&self) -> $crate::prettier::Document {
$crate::prettier::display(*self)
}
}
};
}
#[macro_export]
macro_rules! pretty_via_to_string {
($name:ty) => {
impl $crate::prettier::PrettyPrint for $name {
fn render(&self) -> $crate::prettier::Document {
$crate::prettier::text(&**self)
}
}
};
}
pretty_via_display!(bool);
pretty_via_display!(u8);
pretty_via_display!(i8);
pretty_via_display!(u16);
pretty_via_display!(i16);
pretty_via_display!(u32);
pretty_via_display!(i32);
pretty_via_display!(u64);
pretty_via_display!(i64);
pretty_via_display!(u128);
pretty_via_display!(i128);
pretty_via_display!(usize);
pretty_via_display!(isize);
pretty_via_display!(core::num::NonZeroU8);
pretty_via_display!(core::num::NonZeroI8);
pretty_via_display!(core::num::NonZeroU16);
pretty_via_display!(core::num::NonZeroI16);
pretty_via_display!(core::num::NonZeroU32);
pretty_via_display!(core::num::NonZeroI32);
pretty_via_display!(core::num::NonZeroU64);
pretty_via_display!(core::num::NonZeroI64);
pretty_via_display!(core::num::NonZeroU128);
pretty_via_display!(core::num::NonZeroI128);
pretty_via_display!(core::num::NonZeroUsize);
pretty_via_display!(core::num::NonZeroIsize);
impl<'a, T: ?Sized + PrettyPrint> PrettyPrint for &'a T {
#[inline]
fn render(&self) -> Document {
(**self).render()
}
#[inline]
fn to_pretty_string(&self) -> String {
(**self).to_pretty_string()
}
#[inline]
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).pretty_print(f)
}
}
impl PrettyPrint for str {
fn render(&self) -> Document {
self.lines()
.map(text)
.reduce(|acc, doc| match acc {
Document::Empty => doc + nl(),
other => other + doc + nl(),
})
.unwrap_or(Document::Empty)
}
}
impl PrettyPrint for String {
fn render(&self) -> Document {
PrettyPrint::render(self.as_str())
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self.as_str(), f)
}
}
impl<'a> PrettyPrint for alloc::borrow::Cow<'a, str> {
fn render(&self) -> Document {
PrettyPrint::render(self.as_ref())
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self.as_ref(), f)
}
}
impl<T: PrettyPrint> PrettyPrint for alloc::boxed::Box<T> {
fn render(&self) -> Document {
PrettyPrint::render(self.as_ref())
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self.as_ref(), f)
}
}
impl<T: PrettyPrint> PrettyPrint for alloc::rc::Rc<T> {
fn render(&self) -> Document {
PrettyPrint::render(self.as_ref())
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self.as_ref(), f)
}
}
impl<T: PrettyPrint> PrettyPrint for alloc::sync::Arc<T> {
fn render(&self) -> Document {
PrettyPrint::render(self.as_ref())
}
fn pretty_print(&self, f: &mut fmt::Formatter) -> fmt::Result {
PrettyPrint::pretty_print(self.as_ref(), f)
}
}
impl<T: PrettyPrint> PrettyPrint for alloc::vec::Vec<T> {
fn render(&self) -> Document {
let single = self.iter().fold(Document::Empty, |acc, e| match acc {
Document::Empty => e.render(),
acc => acc + ',' + ' ' + e.render(),
});
let multi = self.iter().fold(Document::Empty, |acc, e| match acc {
Document::Empty => e.render(),
acc => acc + ',' + nl() + e.render(),
});
let single_line = '[' + single + ']';
let multi_line = '[' + indent(4, nl() + multi) + nl() + ']';
single_line | multi_line
}
}
impl<T: PrettyPrint> PrettyPrint for alloc::collections::BTreeSet<T> {
fn render(&self) -> Document {
let single = self.iter().fold(Document::Empty, |acc, e| match acc {
Document::Empty => e.render(),
acc => acc + ',' + ' ' + e.render(),
});
let multi = self.iter().fold(Document::Empty, |acc, e| match acc {
Document::Empty => e.render(),
acc => acc + ',' + nl() + e.render(),
});
let single_line = '{' + single + '}';
let multi_line = '{' + indent(4, nl() + multi) + nl() + '}';
single_line | multi_line
}
}
impl<K: PrettyPrint, V: PrettyPrint> PrettyPrint for alloc::collections::BTreeMap<K, V> {
fn render(&self) -> Document {
let single = self.iter().fold(Document::Empty, |acc, (k, v)| match acc {
Document::Empty => k.render() + " => " + v.render(),
acc => acc + ',' + ' ' + k.render() + " => " + v.render(),
});
let multi = self.iter().fold(Document::Empty, |acc, (k, v)| match acc {
Document::Empty => k.render() + " => " + v.render(),
acc => acc + ',' + nl() + k.render() + " => " + v.render(),
});
let single_line = '{' + single + '}';
let multi_line = '{' + indent(4, nl() + multi) + nl() + '}';
single_line | multi_line
}
}
struct Prettier<'a, P: ?Sized + PrettyPrint>(&'a P);
impl<'a, P: ?Sized + PrettyPrint> fmt::Display for Prettier<'a, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.pretty_print(f)
}
}