The primary interface to operations for dynamically determining the arrangement of output is provided through the functions above. However, an additional interface is provided via a set of format directives because, as shown by the examples in this section and the next, format strings are typically a much more compact way to specify pretty printing. In addition, without such an interface, one would have to abandon the use of format when interacting with the pretty printer.
~W provides automatic support for circularity detection. If *print-circle* (and possibly also *print-shared*) is not nil and ~W is applied to an argument that is a circular (or shared) reference, an appropriate “#n#” marker is inserted in the output instead of printing the argument.
The format string portion enclosed by ~<...~:> can be divided into segments ~<pre x~;body~; su x~:> by ~; directives. If the ﬁrst section is terminated by ~@;, it speciﬁes a per-line preﬁx rather than a simple preﬁx. The preﬁx and suﬃx cannot contain format directives. An error is signaled if either the preﬁx or suﬃx fails to be a constant string or if the enclosed portion is divided into more than three segments.
If the enclosed portion is divided into only two segments, the suﬃx defaults to the null string. If the enclosed portion consists of only a single segment, both the preﬁx and the suﬃx default to the null string. If the colon modiﬁer is used (that is, ~:<...~:>), the preﬁx and suﬃx default to "(" and ")", respectively, instead of the null string.
The body segment can be any arbitrary format control string. This format control string is applied to the elements of the list corresponding to the ~<...~:> directive as a whole. Elements are extracted from this list using pprint-pop, thereby providing automatic support for malformed lists and the detection of circularity, sharing, and length abbreviation. Within the body segment, ~̂ acts like pprint-exit-if-list-exhausted.
~<...~:> supports a feature not supported by pprint-logical-block. If ~:@> is used to terminate the directive (that is, ~<...~:@>), then a ﬁll-style conditional newline is automatically inserted after each group of blanks immediately contained in the body (except for blanks after a ~<newline> directive). This makes it easy to achieve the equivalent of paragraph ﬁlling.
If the atsign modiﬁer is used with ~<...~:>, the entire remaining argument list is passed to the directive as its argument. All of the remaining arguments are always consumed by ~@<...~:>, even if they are not all used by the format string nested in the directive. Other than the diﬀerence in its argument, ~@<...~:> is exactly the same as ~<...~:>, except that circularity (and sharing) detection is not applied if the ~@<...~:> is at top level in a format string. This ensures that circularity detection is applied only to data lists and not to format argument lists.
To a considerable extent, the basic form of the directive ~<...~> is incompatible with the dynamic control of the arrangement of output by ~W, ~_, ~<...~:>, ~I, and ~:T. As a result, an error is signaled if any of these directives is nested within ~<...~>. Beyond this, an error is also signaled if the ~<...~:;...~> form of ~<...~> is used in the same format string with ~W, ~_, ~<...~:>, ~I, or ~:T.
When a ~/name/ directive is encountered, the indicated function is called with four or more arguments. The ﬁrst four arguments are the output stream, the format argument corresponding to the directive, the value t if the colon modiﬁer was used (nil otherwise), and the value t if the atsign modiﬁer was used (nil otherwise). The remaining arguments consist of any parameters speciﬁed with the directive. The function should print the argument appropriately. Any values returned by the function are ignored.
The three functions pprint-linear, pprint-ﬁll, and pprint-tabular are designed so that they can be called by ~/.../ (that is, ~/pprint-linear/, ~/pprint-ﬁll/, and ~/pprint-tabular/. In particular they take colon and atsign arguments.
As examples of the convenience of specifying pretty printing with format strings, consider the functions pprint-defun and pprint-let used as examples in the last section. They can be more compactly deﬁned as follows. The function pprint-vector cannot be deﬁned using format, because the data structure it traverses is not a list. The function pprint-tabular is inconvenient to deﬁne using format, because of the need to pass its tabsize argument through to a ~:T directive nested within an iteration over a list.