Pretty-printing is displaying a data structure as text, by adding line-breaks and indenttaion so that the visual structure of the output corresponds to the logical structure of data structure. This makes it easier to read and understand. Pretty-printing takes into account the column width of the output so as to avoid using more lines than needed.
Pretty-printing of standard sequences types such as lists and vectors is done by default. For example:
#|kawa:11|#(set! *print-right-margin* 50)
#|kawa:12|#'(ABCDEF (aa bb cc dd) (x123456789
#|.....13|#y123456789 z123456789) ABCDEFG HIJKL)
(ABCDEF (aa bb cc dd) (x123456789 y123456789 z123456789) ABCDEFG HIJK)
Setting *print-right-margin*
to 50
causes output to be limited to 50 columns.
Notice the top-level list has to be split,
but sub-lists (aa bb cc dd)
and (x123456789 y123456789 z123456789)
don’t need to be split.
When outputting to a DomTerm REPL,
then *print-right-margin*
is ignored,
and the line-breaking is actually handled by DomTerm.
If you change the window width, DomTerm will dynamically
re-calculate the line-breaks of previous pretten output.
This works even in the case of a session saved to an HTML
file, as long as JavaScript is enabled.
The concepts and terminology are based on those of Common Lisp.
Scheme and Lisp code is traditionally pretty-printed
slightly differently than plain lists.
The pprint
procedure assumes the argument
is a Scheme form, and prints its accordingly.
For example the special form (let ...)
is printed
differently from a regular function call (list ...)
.
Assume
obj
is a Scheme form, and pretty-print it in traditional Scheme format. For example:#|kawa:1|#(import (kawa pprint))
#|kawa:2|#(define fib-form
#|.....3|#'(define (fibonacci n)
#|.....4|#(let loop ((i0 0) (i1 1) (n n))
#|.....5|#(if (<= n 0) i0
#|.....6|#(loop i1 (+ i0 i1) (- n 1))))))
#|kawa:7|#(set! *print-right-margin* 80)
#|kawa:8|#(pprint fib-form)
(define (fibonacci n) (let loop ((i0 0) (i1 1) (n n)) (if (<= n 0) i0 (loop i1 (+ i0 i1) (- n 1))))) #|kawa:9|#(set! *print-right-margin* 40)
#|kawa:10|#(pprint fib-form)
(define (fibonacci n) (let loop ((i0 0) (i1 1) (n n)) (if (<= n 0) i0 (loop i1 (+ i0 i1) (- n 1)))))The
pprint
special-cases forms that start withdefine
,if
,lambda
,let
, and a few more, and formats them with “traditional” indentation. However, it is not as complete or polished as it should be. (It should also use a programmable dispatch table, rather than having these special cases hard-wired. That is an improvemet for another day.)
The following procedures are used to indicate logical blocks, and optional newlines.
To access them do:
(import (kawa pprint))
In the following, out
is the output port, which
defaults to (current-output-port)
.
Syntax: pprint-logical-block
options
statement
*
Evaluate the
statement
s within the context of a new “logical block”.The
options
are one or more of the following:
prefix:
prefix
per-line:
per-line-prefix
Emit
prefix
orper-line-prefix
(only one of them can be specified) before the start of the logical block. Ifper-line-prefix
is provided, it is also print for each line within the logical block, indented the same. These are strings and default to""
.suffix:
suffix
Emit
suffix
after the end of the logical block.out:
out
The output file.
For example to print a list you might do:
(pprint-logical-block prefix: "(" suffix: ")" print contents of list)
This macro is equivalent to:
(pprint-start-logical-blockprefix
is-per-line
suffix
out
) (try-finally (beginstatement
*) (pprint-end-logical-blocksuffix
out
))
Procedure: pprint-start-logical-block
prefix
is-per-line
suffix
out
Start a logical block. The
is-per-line
argument is a boolean to specifiy ofprefix
is a per-line-prefix or a plain prefix.
Procedure: pprint-end-logical-block
suffix
out
End a logical block.
Procedure: pprint-newline
kind
[out
]
Print a conditional newline, where
kind
is one of the symbols'fill
,'linear
,'mandatory
, or'miser
. Usually follows printing of a space, as nothing is printed if the line is not broken here.
Procedure: pprint-ident
mode
amount
[out
]
Change how much following lines are indented (with the current logical block). The
amount
is the size of the indentation, in characters. Themode
is either'current
(if theamount
is relative to the current position), or'block
(if theamount
is relative to the start (after anyprefix
) of the current logical block).