Library
Module
Module type
Parameter
Class
Class type
PPrint
is an OCaml library for pretty-printing textual documents. It takes care of indentation and line breaks, and is typically used to pretty-print code.
val empty : document
empty
is the empty document.
val char : char -> document
char c
is an atomic document that consists of the single character c
. This character must not be a newline character.
val string : string -> document
string s
is an atomic document that consists of the string s
. This string must not contain a newline. The printing engine assumes that the ideal width of this string is String.length s
. This assumption is safe if this is an ASCII string. Otherwise, fancystring
or utf8string
should be preferred.
val substring : string -> int -> int -> document
substring s ofs len
is an atomic document that consists of the portion of the string s
delimited by the offset ofs
and the length len
. This portion must not contain a newline. substring s ofs len
is equivalent to string (String.sub s ofs len)
, but is expected to be more efficient, as the substring is not actually extracted.
val fancystring : string -> int -> document
fancystring s alen
is an atomic document that consists of the string s
. This string must not contain a newline. The string may contain fancy characters: color escape characters, UTF-8 characters, etc. Thus, its apparent length (which measures how many columns the text will take up on screen) differs from its length in bytes. The printing engine assumes that its apparent length is alen
.
val fancysubstring : string -> int -> int -> int -> document
fancysubstring s ofs len alen
is equivalent to fancystring (String.sub
s ofs len) alen
.
val utf8string : string -> document
utf8string s
is an atomic document that consists of the UTF-8-encoded string s
. This string must not contain a newline. utf8string s
is equivalent to fancystring s (utf8_length s)
, where utf8_length s
is the apparent length of the UTF-8-encoded string s
.
val utf8format : ('a, unit, string, document) Stdlib.format4 -> 'a
utf8format format <args>...
is equivalent to utf8string (Printf.sprintf format <args>...)
.
val hardline : document
The atomic document hardline
represents a forced newline. This document has infinite ideal width: thus, if there is a choice between printing it in flat mode and printing it in normal mode, normal mode is preferred. In other words, when hardline
is placed directly inside a group, this group is dissolved: group hardline
is equivalent to hardline
. This combinator should be seldom used; consider using break
instead.
val blank : int -> document
The atomic document blank n
consists of n
blank characters. A blank character is like an ordinary ASCII space character char ' '
, except that blank characters that appear at the end of a line are automatically suppressed.
val space : document
space
is a synonym for blank 1
. It consists of one blank character. It is therefore not equivalent to char ' '
.
val break : int -> document
The document break n
is a breakable blank of width n
. It produces n
blank characters if the printing engine is in flat mode, and a single newline character if the printing engine is in normal mode. break 1
is equivalent to ifflat (blank 1) hardline
.
doc1 ^^ doc2
is the concatenation of the documents doc1
and doc2
.
group doc
encodes a choice. If the document doc
fits on the current line, then it is rendered on a single line, in flat mode. (All group
combinators inside it are then ignored.) Otherwise, this group is dissolved, and doc
is rendered in normal mode. There might be more groups within doc
, whose presence leads to further choices being explored.
ifflat doc1 doc2
is rendered as doc1
if the printing engine is in flat mode, that is, if the printing engine has determined that some enclosing group fits on the current line. Otherwise, it is rendered as doc2
. Use this combinator with caution! Because the printing engine is free to choose between doc1
and doc2
, these documents must be semantically equivalent. It is up to the user to enforce this property.
To render the document nest j doc
, the printing engine temporarily increases the current indentation level by j
, then renders doc
. The effect of the current indentation level is as follows: every time a newline character is emitted, it is immediately followed by n
blank characters, where n
is the current indentation level. Thus, one may think of nest j doc
roughly as the document doc
in which j
blank characters have been inserted after every newline character.
To render align doc
, the printing engine sets the current indentation level to the current column, then renders doc
. In other words, the document doc
is rendered within a box whose upper left corner is the current position of the printing engine.
The document range hook doc
is printed like the document doc
, but allows the caller to register a hook that is applied, when the document is printed, to the range occupied by this document in the output text. This offers a way of mapping positions in the output text back to (sub)documents.
Documents are abstract, and cannot be inspected. Nevertheless, it is possible to test whether a document is empty.
val is_empty : document -> bool
Three renderers are available. They offer the same API, described by the signature RENDERER
, and differ only in the nature of the output channel that they use.
module type RENDERER = sig ... end
This signature describes the document renderers in a manner that is independent of the type of the output channel.
This renderer sends its output into an output channel.
This renderer sends its output into a memory buffer.
module ToFormatter :
RENDERER
with type channel = Stdlib.Format.formatter
and type document = document
This renderer sends its output into a formatter channel.
It is possible to define custom document constructors, provided they meet the expectations of the printing engine. In short, the custom document combinator custom
expects an object of class custom
. This object must provide three methods. The method requirement
must compute the ideal width of the custom document. The methods pretty
and compact
must render the custom document. For this purpose, they have access to the output channel and to the state of the printing engine.
A width requirement is expressed as an integer. The value max_int
is reserved and represents infinity.
val infinity : requirement
infinity
represents an infinite width requirement.
class type output = object ... end
An output channel is abstractly represented as an object equipped with methods for displaying one character and for displaying a substring.
type state = {
width : int;
The line width. This parameter is fixed throughout the execution of the renderer.
*)ribbon : int;
The ribbon width. This parameter is fixed throughout the execution of the renderer.
*)mutable last_indent : int;
The number of blanks that were printed at the beginning of the current line. This field is updated (only) when a hardline is emitted. It is used (only) to determine whether the ribbon width constraint is respected.
*)mutable line : int;
The current line. This field is updated (only) when a hardline is emitted. It is not used by the pretty-printing engine itself.
*)mutable column : int;
The current column. This field must be updated whenever something is sent to the output channel. It is used (only) to determine whether the width constraint is respected.
*)}
The internal state of the rendering engine is exposed to the user who wishes to define custom documents. However, its structure is subject to change in future versions of the library.
class type custom = object ... end
A custom document is defined by implementing an object of class custom
.
Some of the key functions of the library are exposed, in the hope that they may be useful to authors of custom (leaf and composite) documents. In the case of a leaf document, they can help perform certain basic functions; for instance, applying the function pretty
to the document hardline
is a simple way of printing a hardline, while respecting the indentation parameters and updating the state in a correct manner. Similarly, applying pretty
to the document blank n
is a simple way of printing n
blank characters. In the case of a composite document (one that contains subdocuments), these functions are essential: they allow computing the width requirement of a subdocument and displaying a subdocument.
val requirement : document -> requirement
requirement doc
computes the width requirement of the document doc
. It runs in constant time.
pretty output state indent flatten doc
prints the document doc
. See the documentation of the method pretty
in the class custom
.