This crate defines a Wadler-style pretty-printing API.

Start with the static functions of Doc.

Quick start

Let's pretty-print simple sexps! We want to pretty print sexps like

lisp (1 2 3) or, if the line would be too long, like

lisp ((1) (2 3) (4 5 6))

A simple symbolic expression consists of a numeric atom or a nested ordered list of symbolic expression children.

```rust

use pretty::*;

enum SExp { Atom(u32), List(Vec), } use SExp::*;

fn main() { }

```

We define a simple conversion to a Doc. Atoms are rendered as strings; lists are recursively rendered, with spaces between children where appropriate. Children are nested and grouped, allowing them to be laid out in a single line as appropriate.

```rust

use pretty::*;

enum SExp {

Atom(u32),

List(Vec),

}

use SExp::*;

impl SExp { /// Return a pretty printed format of self. pub fn todoc(&self) -> RcDoc<()> { match *self { Atom(ref x) => RcDoc::asstring(x), List(ref xs) => RcDoc::text("(") .append(RcDoc::intersperse(xs.intoiter().map(|x| x.todoc()), Doc::line()).nest(1).group()) .append(RcDoc::text(")")) } } }

fn main() { }

```

Next, we convert the Doc to a plain old string.

```rust

use pretty::*;

enum SExp {

Atom(u32),

List(Vec),

}

use SExp::*;

impl SExp {

/// Return a pretty printed format of self.

pub fn to_doc(&self) -> BoxDoc<()> {

match *self {

Atom(ref x) => BoxDoc::as_string(x),

List(ref xs) =>

BoxDoc::text("(")

.append(BoxDoc::intersperse(xs.intoiter().map(|x| x.todoc()), Doc::line()).nest(1).group())

.append(BoxDoc::text(")"))

}

}

}

impl SExp { pub fn topretty(&self, width: usize) -> String { let mut w = Vec::new(); self.todoc().render(width, &mut w).unwrap(); String::from_utf8(w).unwrap() } }

fn main() { }

```

And finally we can test that the nesting and grouping behaves as we expected.

```rust

use pretty::*;

enum SExp {

Atom(u32),

List(Vec),

}

use SExp::*;

impl SExp {

/// Return a pretty printed format of self.

pub fn to_doc(&self) -> BoxDoc<()> {

match *self {

Atom(ref x) => BoxDoc::as_string(x),

List(ref xs) =>

BoxDoc::text("(")

.append(BoxDoc::intersperse(xs.intoiter().map(|x| x.todoc()), Doc::line()).nest(1).group())

.append(BoxDoc::text(")"))

}

}

}

impl SExp {

pub fn to_pretty(&self, width: usize) -> String {

let mut w = Vec::new();

self.to_doc().render(width, &mut w).unwrap();

String::from_utf8(w).unwrap()

}

}

fn main() {

let atom = SExp::Atom(5); asserteq!("5", atom.topretty(10)); let list = SExp::List(vec![SExp::Atom(1), SExp::Atom(2), SExp::Atom(3)]); asserteq!("(1 2 3)", list.topretty(10)); asserteq!("\ (1 2 3)", list.topretty(5));

}

```

Advanced usage

There's a more efficient pattern that uses the DocAllocator trait, as implemented by BoxAllocator, to allocate DocumentTree instances. See examples/trees.rs for this approach.