# Module Pretty

    module Pretty: sig .. end

Utility functions for pretty-printing. The major features provided by this module are

- An `fprintf`-style interface with support for user-defined printers
- The printout is fit to a width by selecting some of the optional newlines
- Constructs for alignment and indentation
- Print ellipsis starting at a certain nesting depth
- Constructs for printing lists and arrays

Pretty-printing occurs in two stages:

- Construct a `Pretty.doc` object that encodes all of the elements to be printed along with alignment specifiers and optional and mandatory newlines
- Format the `Pretty.doc` to a certain width and emit it as a string, to an output stream or pass it to a user-defined function

The formatting algorithm is not optimal but it does a pretty good job while still operating in linear time. The original version was based on a pretty printer by Philip Wadler which turned out to not scale to large jobs.

API

    type doc

The type of unformated documents. Elements of this type can be constructed in two ways. Either with a number of constructor shown below, or using the `Pretty.dprintf` function with a `printf`-like interface. The `Pretty.dprintf` method is slightly slower so we do not use it for large jobs such as the output routines for a compiler. But we use it for small jobs such as logging and error messages.
Constructors for the doc type.

    val nil : doc

Constructs an empty document

    val (++) : doc -> doc -> doc

Concatenates two documents. This is an infix operator that associates to the left.

    val text : string -> doc

A document that prints the given string

    val num : int -> doc

A document that prints an integer in decimal form

    val real : float -> doc

A document that prints a real number

    val chr : char -> doc

A document that prints a character. This is just like `Pretty.text` with a one-character string.

    val line : doc

A document that consists of a mandatory newline. This is just like `(text "\n")`. The new line will be indented to the current indentation level, unless you use `Pretty.leftflush` right after this.

    val leftflush : doc

Use after a `Pretty.line` to prevent the indentation. Whatever follows next will be flushed left. Indentation resumes on the next line.

    val break : doc

A document that consists of either a space or a line break. Also called an optional line break. Such a break will be taken only if necessary to fit the document in a given width. If the break is not taken a space is printed instead.

    val align : doc

Mark the current column as the current indentation level. Does not print anything. All taken line breaks will align to this column. The previous alignment level is saved on a stack.

    val unalign : doc

Reverts to the last saved indentation level.

    val mark : doc

Mark the beginning of a markup section. The width of a markup section is considered 0 for the purpose of computing identation

    val unmark : doc

The end of a markup section
Syntactic sugar

    val indent : int -> doc -> doc

Indents the document. Same as `((text " ") ++ align ++ doc ++ unalign)`, with the specified number of spaces.

    val markup : doc -> doc

Prints a document as markup. The marked document cannot contain line breaks or alignment constructs.

    val seq : sep:doc -> doit:('a -> doc) -> elements:'a list -> doc

Formats a sequence. `sep` is a separator, `doit` is a function that converts an element to a document.

    val docList : ?sep:doc -> ('a -> doc) -> unit -> 'a list -> doc

An alternative function for printing a list. The `unit` argument is there to make this function more easily usable with the `Pretty.dprintf` interface. The first argument is a separator, by default a comma.

    val d_list : string -> (unit -> 'a -> doc) -> unit -> 'a list -> doc

sm: Yet another list printer. This one accepts the same kind of printing function that `Pretty.dprintf` does, and itself works in the dprintf context. Also accepts a string as the separator since that's by far the most common.

    val docArray : ?sep:doc ->
           (int -> 'a -> doc) -> unit -> 'a array -> doc

Formats an array. A separator and a function that prints an array element. The default separator is a comma.

    val docOpt : (unit -> 'a -> doc) -> unit -> 'a option -> doc

Prints an `'a option` with `None` or `Some`

    module MakeMapPrinter: functor (Map : Map.S) -> sig .. end

Format maps.

    val insert : unit -> doc -> doc

A function that is useful with the `printf`-like interface

    val dprintf : ('a, unit, doc) Pervasives.format -> 'a

This function provides an alternative method for constructing `doc` objects. The first argument for this function is a format string argument (of type `('a, unit, doc) format`; if you insist on understanding what that means see the module `Printf`). The format string is like that for the `printf` function in C, except that it understands a few more formatting controls, all starting with the @ character.

The following special formatting characters are understood (these do not correspond to arguments of the function):

- @[ Inserts an `Pretty.align`. Every format string must have matching `Pretty.align` and `Pretty.unalign`.
- @] Inserts an `Pretty.unalign`.
- @! Inserts a `Pretty.line`. Just like "\n"
- @? Inserts a `Pretty.break`.
- @< Inserts a `Pretty.mark`.
- @> Inserts a `Pretty.unmark`.
- @^ Inserts a `Pretty.leftflush` Should be used immediately after @! or "\n".
- @@ : inserts a @ character

In addition to the usual `printf` % formatting characters the following two new characters are supported:

- %t Corresponds to an argument of type `unit -> doc`. This argument is invoked to produce a document
- %a Corresponds to two arguments. The first of type `unit -> 'a -> doc` and the second of type `'a`. (The extra `unit` is do to the peculiarities of the built-in support for format strings in Ocaml. It turns out that it is not a major problem.) Here is an example of how you use this:

    dprintf "Name=%s, SSN=%7d, Children=@[%a@]\n"
                 pers.name pers.ssn (docList (chr ',' ++ break) text)
                 pers.children

The result of `dprintf` is a `Pretty.doc`. You can format the document and emit it using the functions `Pretty.fprint` and `Pretty.sprint`.

    val fprint : Pervasives.out_channel -> width:int -> doc -> unit

Format the document to the given width and emit it to the given channel

    val sprint : width:int -> doc -> string

Format the document to the given width and emit it as a string

    val fprintf : Pervasives.out_channel -> ('a, unit, doc) Pervasives.format -> 'a

Like `Pretty.dprintf` followed by `Pretty.fprint`

    val printf : ('a, unit, doc) Pervasives.format -> 'a

Like `Pretty.fprintf` applied to `stdout`

    val eprintf : ('a, unit, doc) Pervasives.format -> 'a

Like `Pretty.fprintf` applied to `stderr`

    val gprintf : (doc -> doc) -> ('a, unit, doc) Pervasives.format -> 'a

Like `Pretty.dprintf` but more general. It also takes a function that is invoked on the constructed document but before any formatting is done.

    val withPrintDepth : int -> (unit -> unit) -> unit

Invokes a thunk, with printDepth temporarily set to the specified value
The following variables can be used to control the operation of the printer

    val printDepth : int Pervasives.ref

Specifies the nesting depth of the `align`/`unalign` pairs at which everything is replaced with ellipsis

    val printIndent : bool Pervasives.ref

If false then does not indent

    val fastMode : bool Pervasives.ref

If set to `true` then optional breaks are taken only when the document has exceeded the given width. This means that the printout will looked more ragged but it will be faster

    val flushOften : bool Pervasives.ref

If true the it flushes after every print

    val countNewLines : int Pervasives.ref

Keep a running count of the taken newlines. You can read and write this from the client code if you want