basilisp.pprint

Pretty Printing

Pretty printing built-in data structures is as easy as a call to pprint.

(require '[basilisp.pprint :as pprint])
(pprint/pprint (range 30))

The output can be configured using a number of different control variables, which are expressed as dynamic Vars.

You can pretty print the last result from the REPL using the pp convenience macro.

As an alternative, the write API enables a more ergonomic API for configuring the printer using keyword arguments rather than dynamic Vars.

(pprint/write (ns-interns 'basilisp.pprint) :sort-keys true)
;; {*current-length* #'basilisp.pprint/*current-length*
;;  ...
;;  write-out #'basilisp.pprint/write-out}

Custom Pretty Print Dispatch Function

The default dispatch function is simple-dispatch which can print most builtin Basilisp types. Using the builtin macros and utilities, it is possible to create a custom dispatch function.

Pretty Printing Concepts

The pretty printing algorithm used in basilisp.pprint is based on the XP algorithm defined in Richard Water’s 1989 paper “XP: A Common Lisp Pretty Printing System” as adapted in Clojure’s pprint by Tom Faulhaber. There are three basic concepts in the XP algorithm which are necessary in order to create a custom dispatch function.

  • Logical blocks are groups of output that should be treated as a single unit by the pretty printer. Logical blocks can nest, so one logical block may contain 0 or more other logical blocks. For example, a vector may contain a map; the vector would be a logical block and the map would also be a logical block. simple-dispatch even treats key/value pairs in associative type outputs as a logical block, so they are printed on the same line whenever possible.

    A dispatch function can emit a logical block using the pprint-logical-block macro.

  • Conditional newlines can be emitted anywhere a newline may need inserted into the output stream. Newlines can be one of 3 different types which hints to the pretty printer when a newline should be emitted.

    Dispatch functions can emit newlines in any supported style using the pprint-newline function.

    • :linear style newlines should be emitted whenever the enclosing logical block does not fit on a single line. Note that if any linear newline is emitted in a block, every linear newline will be emitted in that block.

    • :mandatory style newlines are emitted in all cases.

    • :miser style newlines are emitted only when the output will occur in the “miser” region as defined by *print-miser-width*. This allows additional newlines to be emitted as the output nests closer to the right margin.

  • Indentation commands indicate how indentation of subsequent lines in a logical block should be defined. Indentation may be defined relative to either the starting column of the current logical block or to the current column of the output.

    Dispatch functions can control indentation using the pprint-indent function.

Pretty printing is most useful for viewing large, nested structures in a more human-friendly way. To that end, dispatch functions wishing to print any collection may want to use the print-length-loop macro to loop over the output, respecting the basilisp.core/*print-length* setting.

Dispatch functions which may need to be called on nested elements should use write-out to ensure that basilisp.core/*print-level* is respected. Scalar values can be printed with basilisp.core/pr or just written directly to *out*.

Unimplemented Features

The following features from clojure.pprint are not currently implemented:

  • :fill newlines

  • code-dispatch for printing code

  • cl-format

References

  • Tom Faulhaber et al.; clojure.pprint (API, Documentation)

  • Oppen, Derek; "Prettyprinting"; October 1980

  • Waters, Richard; "XP: A Common Lisp Pretty Printing System"; March 1989

API

dynamic Var *print-base*[source]

The base used for printing integer literals and rationals.

Default is 10.

dynamic Var *print-miser-width*[source]

The text column number to start using miser style.

Not all dispatch functions support using a miser style, so the effect of this value depends on the value of *print-pprint-dispatch*.

Default is 40. May be set to nil to disable.

dynamic Var *print-pprint-dispatch*[source]

The dispatch function used for pretty printing.

Default is simple-dispatch.

dynamic Var *print-pretty*[source]

If bound to true, calls to write will use pretty printing.

Default is false, but pprint binds the value to true.

dynamic Var *print-radix*[source]

If bound to true, integers and rationals will be printed with a radix prefix. For bases 2, 8, and 16 the prefix will be #b, #o and #x respectively. All other bases will be specified as #XXr where XX is the decimal value of *print-base*.

Default is false.

dynamic Var *print-right-margin*[source]

The soft upper limit for the length of the right margin.

Default is 72.

dynamic Var *print-sort-keys*[source]

If bound to true, associative collections will be printed in sorted order by their keys.

Default is false.

dynamic Var *print-suppress-namespaces*[source]

If true, suppress printing symbol namespaces. This may be useful when printing macroexpansions.

Default is nil.

protocolPrettyWriter[source]

Protocol defining a writer type for pretty printing with the XP algorithm.

Callers should generally not be calling PrettyWriter protocol methods directly, but should instead call the other helper functions and macros directly.

fn (end-block this)[source]
fn (pp-indent this relative-to offset)[source]
fn (pp-newline this kind)[source]
fn (start-block this prefix per-line-prefix suffix)[source]
fn (get-pretty-writer writer)[source]
fn (get-pretty-writer writer max-columns)

Return a pretty writer instance which satisfies PrettyWriter and which is also an io.TextIOBase.

The current state can be fetched using basilisp.core/deref.

fn (pp)[source]

Print the last thing output to the REPL.

Equivalent to calling (pprint *1).

fn (pprint object)[source]
fn (pprint object writer)

Pretty print object to the writer subject to the bindings of the pretty printing control variables.

If no writer is given, the value bound to basilisp.core/*out* is used.

fn (pprint-indent relative-to offset)[source]

Configure the indent of offset characters relative to an anchor at this point in the pretty print output.

relative-to must be one of the following keywords:

  • :current, meaning that the indent offset is relative to the current column when the indent token is encountered

  • :block, meaning that the indent offset is relative to the starting column of the current logical block

macro (pprint-logical-block & body)[source]

Macro for grouping logical elements together in pprint outputs.

fn (pprint-newline kind)[source]

Emit a newline to the output buffer.

kind must be one of the following keywords:

  • :linear, which will be emitted as newlines only if the the logical block doesn’t fit on one line

  • :mandatory, which the pretty writer will emit in all cases

  • :miser, which will emit a newline whenever the output column is in the miser region, as configured by *print-miser-width*

macro (print-length-loop bindings & body)[source]

loop -like macro which loops at most basilisp.core/*print-length* times, which is often useful when defining custom pretty-printing functions.

fn (print-table rows)[source]
fn (print-table ks rows)

Print a collection of maps as a table to the buffer currently bound to basilisp.core/*out*.

If there is at least one element in rows, a header row will be printed followed by a single divider row followed by a line for each element in rows.

If no keys are given (as ks), then use the keys returned from the first element in rows (as by (keys (first rows))). Note that in this case, the order of headers in the resulting table is based on the order of keys returned by basilisp.core/keys.

fn (set-pprint-dispatch function)[source]

Set the root value of *print-pprint-dispatch* to function.

By default, the root value is simple-dispatch.

multi fn (simple-dispatch & args)[source]
macro (with-pprint-dispatch function & body)[source]

Convenience macro for setting the *print-pprint-dispatch* while executing the body.

fn (write object & {:as opts})[source]

Pretty print object as by pprint, but options may be specified as keyword arguments rather than dynamic Vars.

The supported keyword arguments are listed below with their corresponding dynamic Var:

fn (write-out object)[source]

Write object to basilisp.core/*out*, respecting the current bindings of the pretty printing control variables.

*out* should be a pretty writer (as returned by get-pretty-writer).

This function is intended to be called from within pretty print dispatch functions which already have pretty print control variables correctly set up.

Note

This function performs cycle detection on input values.