Pretty

A pretty printing library

type Position = { line : Nat; column : Nat; indent : Nat; nextIndent : Nat; pageWidth : Nat; ribbonWidth : Nat }

Document lines and columns are 0-based offsets.

type Doc<A> = {#append : (Doc<A>, Doc<A>); #indent : Doc<A>; #align : (Nat, Doc<A>); #annotate : (A, Doc<A>); #flexSelect : (Doc<A>, Doc<A>, Doc<A>); #flexAlt : (Doc<A>, Doc<A>); #withPosition : Position -> Doc<A>; #text : (Nat, Text); #linebreak; #empty}

Documents are built using append as horizontal, line-wise concatenation. The functions in this module let you build documents that respond well to width constraints (such as flexGroup and flexAlt).

public func showDoc<A>(showAnn : A -> Text, doc : Doc<A>) : Text

public func mapDoc<A, B>(doc : Doc<A>, f : A -> B) : Doc<B>

Transforms all annotations in the given document, using the passed function

public func append<A>(d1 : Doc<A>, d2 : Doc<A>) : Doc<A>

Appending two documents will put them next to each other on a line.

public func appendAll<A>(ds : Iter.Iter<Doc<A>>) : Doc<A>

Appends all given documents

public func bothNotEmpty<A>(
  d1 : Doc<A>,
  d2 : Doc<A>,
  f : (Doc<A>, Doc<A>) -> Doc<A>
) : Doc<A>

public let empty : Doc<None>

The empty document

public func isEmpty<A>(doc : Doc<A>) : Bool

Checks whether the document is empty.

public func indent<A>(doc : Doc<A>) : Doc<A>

Increases the indentation level by one indent.

public func align<A>(n : Nat, doc : Doc<A>) : Doc<A>

Increases the indentation level by the number of spaces (for alignment purposes).

public func alignCurrentColumn<A>(doc : Doc<A>) : Doc<A>

Increases the indentation level so that it aligns to the current column.

public func annotate<A>(annotation : A, doc : Doc<A>) : Doc<A>

Adds an annotation to a document. Printers can interpret annotations to style their output, eg. ANSI colors.

public func flexGroup<A>(doc : Doc<A>) : Doc<A>

Attempts to layout the document with flex alternatives, falling back to defaults if it doesn't fit the page width.

public func flexSelect<A>(
  doc : Doc<A>,
  defaults : Doc<A>,
  fallback : Doc<A>
) : Doc<A>

Attempts to layout the first document with flex alternatives, falling back to defaults if it doesn't fit the page width. If the flex alternatives are used then the second document will be appended, otherwise the third document will be appended.

public func flexAlt<A>(doc : Doc<A>, fallback : Doc<A>) : Doc<A>

Attempts to layout the first document when in a flex group, falling back to the second as a default.

public func withPosition<A>(f : Position -> Doc<A>) : Doc<A>

Build a document based on the current layout position.

public func text<A>(t : Text) : Doc<A>

The most basic document leaf. This should not contain newlines. If it does your document will look very funny.

public func lineBreak<A>() : Doc<A>

Inserts a hard line break.

public func spaceBreak<A>() : Doc<A>

Inserts a space when in a flex group, otherwise inserts a break.

public func softBreak<A>() : Doc<A>

Inserts nothing when in a flex group, otherwise inserts a break.

public func space<A>() : Doc<A>

A singe space character.

public func lines<A>(docs : [Doc<A>]) : Doc<A>

Appends documents with a break in between them.

public func words<A>(docs : [Doc<A>]) : Doc<A>

Appends documents with a space in between them.

public func paragraph<A>(docs : [Doc<A>]) : Doc<A>

Appends documents with a space-break in between them.

public func textParagraph<A>(t : Text) : Doc<A>

Constructs a wrapping paragraph from a blob of text. Ignores newlines and multiple spaces.

public func appendBreak<A>(doc1 : Doc<A>, doc2 : Doc<A>) : Doc<A>

Appends two documents with a break between them.

public func appendSpace<A>(doc1 : Doc<A>, doc2 : Doc<A>) : Doc<A>

Appends two documents with a space between them.

public func appendSpaceBreak<A>(doc1 : Doc<A>, doc2 : Doc<A>) : Doc<A>

Appends two documents with a space between them, falling back to a break if that does not fit.

public func enclose<A>(
  open : Doc<A>,
  close : Doc<A>,
  inner : Doc<A>
) : Doc<A>

Uses an opening and closing document to wrap another document.

public func encloseEmptyAlt<A>(
  open : Doc<A>,
  close : Doc<A>,
  fallback : Doc<A>,
  inner : Doc<A>
) : Doc<A>

Uses an opening and closing document to wrap another document, falling back when the inner document is empty.

encloseEmptyAlt(text("[ "), text(" ]"), text("[]"), #empty)

public func encloseWithSeparator<A>(
  open : Doc<A>,
  close : Doc<A>,
  separator : Doc<A>,
  inner : [Doc<A>]
) : Doc<A>

Uses an opening and closing document, as a well as a separator, to render a series of documents.

public func foldWithSeparator<A>(separator : Doc<A>, docs : [Doc<A>]) : Doc<A>

Appends a series of documents together with a separator in between them.

public func foldWith<A>(docs : [Doc<A>], f : (Doc<A>, Doc<A>) -> Doc<A>) : Doc<A>

Appends a series of documents together with a given append function. This is notable because it ignores empty documents.

type Printer<Buf, A, Res> = { emptyBuffer : Buf; writeText : (Nat, Text, Buf) -> Buf; writeIndent : (Nat, Text, Buf) -> Buf; writeBreak : Buf -> Buf; enterAnnotation : (A, List.List<A>, Buf) -> Buf; leaveAnnotation : (A, List.List<A>, Buf) -> Buf; flushBuffer : Buf -> Res }

public let plainText : Printer<Text, Any, Text>

A plain text printer. Can be used with any document.

type PrintOptions = { pageWidth : Nat; ribbonRatio : Float; indentUnit : Text; indentWidth : Nat }

Configuration options for the printer.

public let twoSpaces : PrintOptions

Prints 2-space indents, with a default 80-column page width.

public let fourSpaces : PrintOptions

Prints 4-space indents, with a default 80-column page width.

public func print<Buf, A, Res>(
  printer : Printer<Buf, A, Res>,
  opts : PrintOptions,
  doc : Doc<A>
) : Res

Prints a documents given a printer and print options.

This will use full line-lookahead from the start of a flex group. If it encounters a break or content overflows the page-width, it will layout the group using flex alternative defaults instead.