Skip to main content

Crate pretty_lang

Crate pretty_lang 

Source
Expand description

§pretty_lang

A language-agnostic pretty-printer: turn any syntax tree into laid-out source text that reflows to a target line width. It is the rendering half of a formatter — a gofmt-style tool for any language, nearly free — and knows nothing about grammars. You describe the layout with a handful of combinators and pretty_lang decides where the lines break.

§The idea

You do not print strings directly. Instead you build a Doc: a lazy description that says these pieces belong together, put a break here that becomes a space or a newline, indent the inside by four, keep this on one line if it fits. Rendering a Doc against a width then chooses concrete line breaks. The same document renders compactly at width 100 and stacked at width 20, with no branching in your code.

The engine is Wadler’s A Prettier Printer in Lindig’s linear-time imperative form: rendering is O(document size), look-ahead is bounded by the target width, and neither pass recurses on the tree, so deeply nested documents cannot overflow the stack.

§Quick start

use pretty_lang::Doc;

// Build `f(a, b, c)` as a document that can break into one-argument-per-line.
let call = Doc::text("f(")
    .append(
        Doc::softline()
            .append(Doc::join(
                Doc::text(",").append(Doc::line()),
                ["a", "b", "c"].map(Doc::text),
            ))
            .nest(4),
    )
    .append(Doc::softline())
    .append(Doc::text(")"))
    .group();

// Wide: it all fits on one line.
assert_eq!(call.render(80), "f(a, b, c)");

// Narrow: the group breaks and the arguments stack, indented.
assert_eq!(call.render(6), "f(\n    a,\n    b,\n    c\n)");

§The combinators

Build withMeaning
Doc::textliteral, unbreakable text
Doc::linespace when flat, newline when broken
Doc::softlinenothing when flat, newline when broken
Doc::hardlinealways a newline; forces enclosing groups to break
Doc::appendput one document after another
Doc::concat / Doc::joinfold / intersperse a sequence
Doc::nestindent the line breaks inside a document
Doc::grouplay flat if it fits, otherwise break every flexible line

Render with Doc::render (to a String), Doc::render_into (into any core::fmt::Write), or Doc::render_writer (into a std::io::Write, behind the std feature).

§no_std

The crate is no_std and needs only alloc. The default std feature adds the Doc::render_writer I/O sink. There is no unsafe anywhere (#![forbid(unsafe_code)]).

§Stability

As of 1.0.0 the public surface — the Doc type, its constructors, combinators, render methods, and trait implementations, together with the std feature flag — is stable and frozen under Semantic Versioning. It will not change in a breaking way within the 1.x series; 1.x releases may only add. See docs/API.md for the full promise.

Structs§

Doc
An immutable, cheaply-clonable description of a document’s layout.