1use pretty::RcDoc;
4use std::{borrow::Cow, fmt, ops};
5
6pub trait ToDoc {
8 fn to_doc<'a>(&self) -> D<'a>;
10}
11
12#[derive(Clone)]
17pub struct D<'a>(pub RcDoc<'a, ()>);
18
19impl<'a> ops::Add for D<'a> {
20 type Output = D<'a>;
21
22 fn add(self, rhs: Self) -> Self::Output {
23 D(self.0.append(rhs.0))
24 }
25}
26
27pub fn t<'a, U: Into<Cow<'a, str>>>(data: U) -> D<'a> {
29 D(RcDoc::text(data))
30}
31
32pub fn s<'a>() -> D<'a> {
34 D(RcDoc::line())
35}
36
37pub fn hardline<'a>() -> D<'a> {
39 D(RcDoc::hardline())
40}
41
42pub fn unop<'a>(op: D<'a>, arg: D<'a>) -> D<'a> {
44 (op + s() + arg).group()
45}
46
47pub fn binop<'a>(op: D<'a>, l: D<'a>, r: D<'a>) -> D<'a> {
49 ((l + s() + op).group() + (s() + r).indented()).group()
50}
51
52pub fn tuple<'a, I: IntoIterator<Item = D<'a>>>(i: I) -> D<'a> {
54 D(RcDoc::intersperse(i.into_iter().map(|d| d.0.group()), (t(",") + s()).0))
55 .brackets()
56 .group()
57}
58
59pub fn intersperse<'a, I: IntoIterator<Item = D<'a>>>(i: I, sep: D<'a>) -> D<'a> {
61 D(RcDoc::intersperse(i.into_iter().map(|d| d.0), sep.0))
62}
63
64impl<'a> D<'a> {
65 pub fn group(self) -> D<'a> {
67 D(self.0.group())
68 }
69
70 pub fn parens(self) -> D<'a> {
72 t("(") + self.group() + t(")")
73 }
74
75 pub fn indented(self) -> Self {
77 D(self.0.nest(2))
78 }
79
80 pub fn brackets(self) -> D<'a> {
82 t("[") + self.indented() + t("]")
83 }
84
85 pub fn pretty(&self) -> impl fmt::Display {
87 self.0.pretty(80)
88 }
89}