Crate pretty

Source
Expand description

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

(1 2 3)

or, if the line would be too long, like

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

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

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

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.

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

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

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()
    }
}

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

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

§Advanced usage

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

Re-exports§

pub use self::block::Affixes;
pub use self::block::BlockDoc;

Modules§

block
Document formatting of “blocks” such as where some number of prefixes and suffixes would ideally be layed out onto a single line instead of breaking them up into multiple lines. See BlockDoc for an example

Macros§

docs
Concatenates a number of documents (or values that can be converted into a document via the Pretty trait, like &str)

Structs§

Arena
An arena which can be used to allocate Doc values.
BoxAllocator
BoxDoc
DocBuilder
The DocBuilder type allows for convenient appending of documents even for arena allocated documents by storing the arena inline.
FmtWrite
Writes to something implementing std::fmt::Write
IoWrite
Writes to something implementing std::io::Write
PrettyFmt
RcAllocator
RcDoc
RefDoc
Newtype wrapper for &Doc

Enums§

BuildDoc
Either a Doc or a pointer to a Doc (D)
Doc
The concrete document type. This type is not meant to be used directly. Instead use the static functions on Doc or the methods on an DocAllocator.

Traits§

DocAllocator
The DocAllocator trait abstracts over a type which can allocate (pointers to) Doc.
DocPtr
Pretty
Trait for types which can be converted to a Document
Render
Trait representing the operations necessary to render a document
RenderAnnotated
Trait representing the operations necessary to write an annotated document.
StaticDoc

Type Aliases§

SmallText