-
Notifications
You must be signed in to change notification settings - Fork 9
/
pprint.tex
1129 lines (992 loc) · 53.3 KB
/
pprint.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%%%Chapter of Common Lisp Manual. Copyright 1989 Guy L. Steele Jr.
% +++ Final version of chapter +++
\clearpage\def\pagestatus{FINAL PROOF}
\chapter{Pretty Printing}
\label{PPRINT}
Author: Richard C. Waters
\prefaceword
\begin{new}
X3J13 voted in January 1989
\issue{PRETTY-PRINT-INTERFACE}
to adopt a facility for user-controlled pretty printing
as a part of the forthcoming draft Common Lisp standard.
This facility is the culmination of thirteen
years of design, testing, revision, and use of this approach.
\end{new}
This chapter presents the bulk of the Common Lisp
pretty printing specification, written by Richard C.~Waters. I have
edited it only very lightly
to conform to the overall style of this book.
\noindent\hbox to \textwidth{\hss---Guy L. Steele Jr.}
\vskip 8pt plus 3pt minus 2pt
\section{Introduction}
Pretty printing has traditionally been a black box process, displaying
program code using a set of fixed layout rules. Its utility can be greatly
enhanced by opening it up to user control. The facilities described
in this chapter provide general and powerful means for specifying pretty-printing
behavior.
By providing direct access to the mechanisms within the pretty printer that
make dynamic decisions about layout, the macros and functions
\cdf{pprint-logical-block}, \cdf{pprint-newline}, and \cdf{pprint-indent} make
it possible to specify pretty printing layout rules as a part of any
function that produces output. They also make it very easy for the
function to support
detection of circularity and sharing and abbreviation based on length and
nesting depth. Using the function
\cdf{set-pprint-dispatch}, one can associate a user-defined pretty
printing function with any type of object. A small set of new \cdf{format}
directives allows concise implementation of user-defined pretty-printing
functions.
Together, these facilities
enable users to redefine the way code is displayed and allow the full power
of pretty printing to be applied to complex combinations of data
structures.
\beforenoterule
\begin{implementation}
This chapter describes the interface of
the XP pretty printer. XP is described fully
in~\cite{XP-PRETTY-PRINTER},
which also explains how to obtain a portable implementation. XP uses
a highly efficient linear-time algorithm. When properly integrated into a
Common Lisp, this algorithm supports pretty printing that is only
fractionally slower than ordinary printing.
\end{implementation}
\afternoterule
\section{Pretty Printing Control Variables}
\label{PPRINT-VARIABLES-SECTION}
The function \cdf{write} accepts keyword arguments named
\cd{:pprint-dispatch}, \cd{:miser-width}, \cd{:right-margin}, and \cd{:lines},
corresponding to these variables.
\begin{defun}[Variable]
*print-pprint-dispatch*
When \cdf{*print-pretty*} is not \cdf{nil}, printing is controlled by the `pprint
dispatch table' stored in the variable \cdf{*print-pprint-dispatch*}. The
initial value of \cdf{*print-pprint-dispatch*} is implementation-dependent and
causes traditional pretty printing of Lisp code. The last section of this
chapter explains how the contents of this table can be changed.
\end{defun}
\begin{defun}[Variable]
*print-right-margin*
A primary goal of pretty printing is to keep the output between a pair of
margins. The left margin is set at the column where the output begins. If
this cannot be determined, the left margin is set to zero.
When \cdf{*print-right-margin*} is not \cdf{nil}, it specifies the right
margin to use when making layout decisions. When \cdf{*print-right-margin*}
is \cdf{nil} (the initial value), the right margin is set at the maximum
line length that can be displayed by the output stream without wraparound
or truncation. If this cannot be determined, the right margin is set to an
implementation-dependent value.
To allow for the possibility of variable-width fonts,
\cdf{*print-right-margin*} is in units of ems---the width of an
``m'' in the font being used to display characters on the relevant output
stream at the moment when the variables are consulted.
\end{defun}
\begin{defun}[Variable]
*print-miser-width*
If \cdf{*print-miser-width*} is not \cdf{nil}, the pretty printer switches to a compact
style of output (called miser style) whenever the width available for
printing a substructure is less than or equal to \cdf{*print-miser-width*} ems.
The initial value of \cdf{*print-miser-width*} is implementation-dependent.
\end{defun}
\begin{defun}[Variable]
*print-lines*
When given a value other than its initial value of \cdf{nil},
\cdf{*print-lines*} limits the number of output lines produced when
something is pretty printed. If an attempt is made to go beyond
\cdf{*print-lines*} lines, ``\cd{~..}'' (a space and two periods)
is printed at the end of the last
line followed by all of the suffixes (closing delimiters) that are pending
to be printed.
\begin{lisp}
(let ((*print-right-margin* 25) (*print-lines* 3)) \\*
~~(pprint '(progn (setq a 1 b 2 c 3 d 4)))) \\*
\\
(PROGN (SETQ A 1 \\*
~~~~~~~~~~~~~B 2 \\*
~~~~~~~~~~~~~C 3 ..))
\end{lisp}
(The symbol ``\cd{..}'' is printed out to ensure that a reader error will
occur if the output is later read. A symbol different from ``\cd{...}'' is
used to indicate that a different kind of abbreviation has occurred.)
\end{defun}
\section{Dynamic Control of the Arrangement of Output}
The following functions and macros support precise control of what should
be done when a piece of output is too large to fit in the space available.
Three concepts underlie the way these operations work: \emph{logical blocks},
\emph{conditional newlines}, and \emph{sections}. Before proceeding further, it is
important to define these terms.
The first line of figure~\ref{PRETTY-PRINT-SECTIONS-FIGURE} shows a
schematic piece of output. The characters in the output are represented by
hyphens. The positions of conditional newlines are indicated by
digits. The beginnings and ends of logical blocks are indicated in the
figure by ``\cdf{<}'' and ``\cdf{>}'' respectively.
The output as a whole is a logical block and the outermost section. This
section is indicated by the \cd{0}'s on the second line of
figure~\ref{PRETTY-PRINT-SECTIONS-FIGURE}. Logical blocks nested within
the output are specified by the macro
\cdf{pprint-logical-block}. Conditional newline positions are specified by calls
on \cdf{pprint-newline}. Each conditional newline defines two sections (one
before it and one after it) and is associated with a third (the section
immediately containing it).
The section after a conditional newline consists of all the output up to,
but not including, (a) the next conditional newline immediately contained
in the same logical block; or if (a) is not applicable, (b) the next
newline that is at a lesser level of nesting in logical blocks; or if (b)
is not applicable, (c) the end of the output.
The section before a conditional newline consists of all the output back
to, but not including, (a) the previous conditional newline that is
immediately contained in the same logical block; or if (a) is not
applicable, (b) the beginning of the immediately containing logical block.
The last four lines in figure~\ref{PRETTY-PRINT-SECTIONS-FIGURE} indicate
the sections before and after the four conditional newlines.
The section immediately containing a conditional newline is the shortest
section that contains the conditional newline in question. In
figure~\ref{PRETTY-PRINT-SECTIONS-FIGURE}, the first conditional newline is
immediately contained in the section marked with \cd{0}'s, the second and third
conditional newlines are immediately contained in the section before the
fourth conditional newline, and the fourth conditional newline is
immediately contained in the section after the first conditional newline.
\begin{figure}[t]
\caption{Example of Logical Blocks, Conditional Newlines, and Sections}
\label{PRETTY-PRINT-SECTIONS-FIGURE}
\begin{lisp}
~~~~~~~~~~~~~~~~~<-1---<--<--2---3->--4-->-> \\[4pt]
~~~~~~~~~~~~~~~~~000000000000000000000000000 \\
~~~~~~~~~~~~~~~~~11~111111111111111111111111 \\
~~~~~~~~~~~~~~~~~~~~~~~~~~~22~222 \\
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~333~3333 \\
~~~~~~~~~~~~~~~~~~~~~~~~44444444444444~44444
\end{lisp}
\end{figure}
Whenever possible, the pretty printer displays the entire contents of a
section on a single line. However, if the section is too long to fit in
the space available, line breaks are inserted at conditional newline
positions within the section.
\begin{defun}[Function]
pprint-newline kind &optional stream
The \emph{stream} (which defaults to \cdf{*standard-output*}) follows the
standard conventions for stream arguments to printing functions (that is,
\cdf{nil} stands for \cdf{*standard-output*} and \cdf{t} stands for
\cdf{*terminal-io*}). The \emph{kind} argument specifies the style of
conditional newline. It must be one of \cd{:linear}, \cd{:fill},
\cd{:miser}, or \cd{:mandatory}. An error is signaled if any other value is
supplied. If \emph{stream} is a pretty printing stream created by
\cdf{pprint-logical-block}, a line break is inserted in the output when the
appropriate condition below is satisfied. Otherwise, \cdf{pprint-newline}
has no effect. The value \cdf{nil} is always returned.
If \emph{kind} is \cd{:linear}, it specifies a `linear-style' conditional newline.
A line break is inserted if and only if the immediately containing section
cannot be printed on one line. The effect of this is that line breaks are
either inserted at every linear-style conditional newline in a logical
block or at none of them.
If \emph{kind} is \cd{:miser}, it specifies a `miser-style' conditional newline.
A line break is inserted if and only if the immediately containing section
cannot be printed on one line and miser style is in effect in the
immediately containing logical block. The effect of this is that
miser-style conditional newlines act like linear-style conditional
newlines, but only when miser style is in effect. Miser style is in effect
for a logical block if and only if the starting position of the logical
block is less than or equal to \cd{*print-miser-width*} from the right margin.
If \emph{kind} is \cd{:fill}, it specifies a `fill-style' conditional
newline. A line break is inserted if and only if either (a) the following
section cannot be printed on the end of the current line, (b) the preceding
section was not printed on a single line, or (c) the immediately containing
section cannot be printed on one line and miser style is in effect in the
immediately containing logical block. If a logical block is broken up into
a number of subsections by fill-style conditional newlines, the basic
effect is that the logical block is printed with as many subsections as
possible on each line. However, if miser style is in effect, fill-style
conditional newlines act like linear-style conditional newlines.
If \emph{kind} is \cd{:mandatory}, it specifies a `mandatory-style' conditional
newline. A line break is always inserted. This implies that none of the
containing sections can be printed on a single line and will therefore
trigger the insertion of line breaks at linear-style conditional newlines
in these sections.
When a line break is inserted by any type of conditional newline, any
blanks that immediately precede the conditional newline are omitted from
the output and indentation is introduced at the beginning of the next line.
By default, the indentation causes the following line to begin in the same
horizontal position as the first character in the immediately containing
logical block. (The indentation can be changed via \cdf{pprint-indent}.)
There are a variety of ways \emph{un\/}conditional newlines can be introduced into
the output (for example, via \cdf{terpri} or by printing a string containing a newline
character). As with mandatory conditional newlines, this prevents any of
the containing sections from being printed on one line. In general, when
an unconditional newline is encountered, it is printed out without
suppression of the preceding blanks and without any indentation following
it. However, if a per-line prefix has been specified (see
\cdf{pprint-logical-block}), that prefix will always be printed no matter how a
newline originates.
\end{defun}
\begin{defmac}
pprint-logical-block (stream-symbol list
<{\!:prefix! | \!:per-line-prefix!} p | \!:suffix! s>)
{form}*
This macro causes printing to be grouped into a logical block. It returns
\cdf{nil}.
The \emph{stream-symbol} must be a symbol. If it is \cdf{nil}, it is treated the same
as if it were \cdf{*standard-output*}. If it is \cdf{t}, it is treated the same as if
it were \cdf{*terminal-io*}. The run-time value of \emph{stream-symbol} must
be a stream (or \cdf{nil} standing for \cdf{*standard-output*}
or \cdf{t} standing for \cdf{*terminal-io*}).
The logical block is printed into this destination stream.
The body (which consists of the \emph{form\/}s)
can contain any arbitrary Lisp forms. Within the body,
\emph{stream-symbol} (or \cdf{*standard-output*} if \emph{stream-symbol} is
\cdf{nil}, or \cdf{*terminal-io*} if \emph{stream-symbol} is \cdf{t}) is bound
to a ``pretty printing'' stream that supports decisions about the arrangement
of output and then forwards the output to the destination stream. All the
standard printing functions (for example, \cdf{write}, \cdf{princ}, \cdf{terpri}) can
be used to send output to the pretty printing stream created by
\cdf{pprint-logical-block}. All and only the output sent to this pretty
printing stream is treated as being in the logical block.
\cdf{pprint-logical-block} and the pretty printing stream it creates have dynamic
extent. It is undefined what happens if output is attempted outside of
this extent to the pretty printing stream created. It is unspecified what
happens if, within this extent, any output is sent directly to the
underlying destination stream (by calling \cdf{write-char}, for example).
The \cd{:suffix}, \cd{:prefix}, and \cd{:per-line-prefix} arguments must all
be expressions that (at run time) evaluate to strings. The \cd{:suffix} argument \emph{s}
(which defaults to the null string) specifies a suffix that is printed just
after the logical block. The \cd{:prefix} and \cd{:per-line-prefix} arguments
are mutually exclusive. If neither \cd{:prefix} nor \cd{:per-line-prefix} is
specified, a \cd{:prefix} of the null string is assumed.
The \cd{:prefix} argument
specifies a prefix \emph{p} that is printed before the beginning of the logical block.
The \cd{:per-line-prefix} specifies a prefix \emph{p} that is printed before the block
and at the beginning of each subsequent line in the block.
An error is signaled if \cd{:prefix} and \cd{:per-line-prefix} are both used
or if a \cd{:suffix}, \cd{:prefix}, or \cd{:pre-line-prefix} argument does not
evaluate to a string.
The \emph{list} is interpreted as being a list that the body is responsible
for printing. (See \cdf{pprint-exit-if-list-exhausted} and
\cdf{pprint-pop}.) If \emph{list} does not (at run time) evaluate to a list,
it is printed using \cdf{write}. (This makes it easier to write printing
functions that are robust in the face of malformed arguments.) If
\cdf{*print-circle*} (and possibly also \cdf{*print-shared*})
is not \cdf{nil} and \emph{list} is a circular (or shared) reference
to a cons, then an appropriate ``\cd{\#\emph{n}\#}'' marker is printed.
(This makes it easy to write printing functions that provide full support
for circularity and sharing abbreviation.) If \cdf{*print-level*} is not
\cdf{nil} and the logical block is at a dynamic nesting depth of greater
than \cdf{*print-level*} in logical blocks, ``\cd{\#}'' is printed. (This
makes it easy to write printing functions that provide full support for depth
abbreviation.)
If any of the three preceding conditions occurs, the indicated output is
printed on \emph{stream-symbol} and the \emph{body} is skipped along with the
printing of the prefix and suffix. (If the
body is not responsible for printing a list, then the first two tests
above can be turned off by supplying \cdf{nil} for the \emph{list} argument.)
In addition to the \emph{list} argument of \cdf{pprint-logical-block}, the
arguments of the standard printing functions such as \cdf{write},
\cdf{print}, \cdf{pprint}, \cdf{print1}, and \cdf{pprint}, as well as the
arguments of the standard \cdf{format} directives such as \cd{{\Xtilde}A},
\cd{{\Xtilde}S}, (and \cd{{\Xtilde}W}) are all checked (when necessary) for
circularity and sharing. However, such checking is not applied to the
arguments of the functions \cdf{write-line}, \cdf{write-string}, and
\cdf{write-char} or to the literal text output by \cdf{format}. A
consequence of this is that you must use one of the latter functions if you
want to print some literal text in the output that is not supposed to be
checked for circularity or sharing. (See the examples below.)
\beforenoterule
\begin{implementation}
Detection of circularity and sharing is supported by the pretty printer by
in essence performing the requested output twice. On the first pass,
circularities and sharing are detected and the actual outputting of
characters is suppressed. On the second pass, the appropriate
``\cd{\#\emph{n}=}'' and ``\cd{\#\emph{n}\#}'' markers are inserted and
characters are output.
A consequence of this two-pass approach to the detection of circularity and
sharing is that the body of a \cdf{pprint-logical-block} must not
perform any side-effects on the surrounding environment. This includes not
modifying any variables that are bound outside of its scope. Obeying this
restriction is facilitated by using \cdf{pprint-pop}, instead of an ordinary
\cdf{pop} when traversing a list being printed by the body of a
\cdf{pprint-logical-block}.)
\end{implementation}
\afternoterule
\end{defmac}
\begin{defmac}
pprint-exit-if-list-exhausted \!!
\cdf{pprint-exit-if-list-exhausted} tests whether or not the \emph{list}
argument of \cdf{pprint-logical-block} has been exhausted (see
\cdf{pprint-pop}). If this list has been reduced to \cdf{nil},
\cdf{pprint-exit-if-list-exhausted} terminates the execution of the
immediately containing \cdf{pprint-logical-block} except for the printing of
the suffix. Otherwise \cdf{pprint-exit-if-list-exhausted} returns \cdf{nil}.
An error message is issued if \cdf{pprint-exit-if-list-exhausted} is used
anywhere other than syntactically nested within a call on
\cdf{pprint-logical-block}. It is undefined what happens if \cdf{pprint-pop}
is executed outside of the dynamic extent of this
\cdf{pprint-logical-block}.
\end{defmac}
\begin{defmac}
pprint-pop \!!
\cdf{pprint-pop} pops elements one at a time off the \emph{list} argument of
\cdf{pprint-logical-block}, taking care to obey \cdf{*print-length*},
\cdf{*print-circle*}, and \cdf{*print-shared*}. An error message is issued if it is
used anywhere other than syntactically nested within a call on
\cdf{pprint-logical-block}. It is undefined what happens if \cdf{pprint-pop} is executed
outside of the dynamic extent of this call on \cdf{pprint-logical-block}.
Each time \cdf{pprint-pop} is called, it pops the next value off the \emph{list}
argument of \cdf{pprint-logical-block} and returns it. However,
before doing this, it performs three tests. If the remaining list is not a
list (neither a cons nor \cdf{nil}), ``\cd{.~}'' is printed
followed by the remaining list. (This makes it easier to write printing
functions that are robust in the face of malformed arguments.) If
\cdf{*print-length*} is \cdf{nil} and \cdf{pprint-pop} has already been called
\cdf{*print-length*} times within the immediately containing logical block,
``\cd{...}'' is printed. (This makes it easy to write printing functions
that properly handle \cd{*print-length*}.) If \cdf{*print-circle*} (and possibly also
\cdf{*print-shared*}) is not \cdf{nil}, and the remaining list is a circular
(or shared) reference, then ``\cd{.~}'' is printed followed by an appropriate
``\cd{\#\emph{n}\#}'' marker. (This catches instances of cdr circularity and sharing
in lists.)
If any of the three preceding conditions occurs, the indicated output is
printed on the pretty printing stream created by the immediately containing
\cdf{pprint-logical-block}
and the execution of the immediately containing
\cdf{pprint-logical-block}
is terminated except for the printing of the suffix.
If \cdf{pprint-logical-block} is given a \emph{list} argument of
\cdf{nil}---because it is not processing a list---\cdf{pprint-pop} can still
be used to obtain support for \cdf{*print-length*} (see the example function
\cdf{pprint-vector} below). In this situation, the first and third tests
above are disabled and \cdf{pprint-pop} always returns \cdf{nil}.
\end{defmac}
\begin{defun}[Function]
pprint-indent relative-to n &optional stream
\cdf{pprint-indent} specifies the indentation to use in a logical block.
\emph{Stream} (which defaults to \cdf{*standard-output*}) follows the
standard conventions for stream arguments to printing functions. The argument
\emph{n} specifies the indentation in ems. If \emph{relative-to} is
\cd{:block}, the
indentation is set to the horizontal position of the first character in the
block plus \emph{n} ems. If \emph{relative-to} is \cd{:current}, the
indentation is set to the current output position plus \emph{n} ems.
The argument \emph{n} can be negative; however, the total indentation cannot be moved
left of the beginning of the line or left of the end of the rightmost per-line
prefix. Changes in indentation caused by \cdf{pprint-indent} do not take
effect until after the next line break. In addition, in miser mode all
calls on \cdf{pprint-indent} are ignored, forcing the lines corresponding to the
logical block to line up under the first character in the block.
An error is signaled if a value other than \cd{:block} or \cd{:current} is
supplied for \emph{relative-to}. If \emph{stream} is a pretty printing
stream created by \cdf{pprint-logical-block}, \cdf{pprint-indent} sets the
indentation in the innermost dynamically enclosing logical block.
Otherwise, \cdf{pprint-indent} has no effect. The value \cdf{nil} is always
returned.
\end{defun}
\begin{defun}[Function]
pprint-tab kind colnum colinc &optional stream
\cdf{pprint-tab} specifies tabbing as performed by the standard \cdf{format}
directive \cd{{\Xtilde}T}. \emph{Stream} (which defaults to
\cdf{*standard-output*}) follows the standard conventions for stream
arguments to printing functions. The arguments \emph{colnum} and \emph{colinc}
correspond to the two parameters to \cd{{\Xtilde}T} and are in
terms of ems. The \emph{kind} argument specifies the style of tabbing. It
must be one of \cd{:line} (tab as by \cd{{\Xtilde}T}) \cd{:section} (tab as
by \cd{{\Xtilde}T}, but measuring horizontal positions relative to the
start of the dynamically enclosing section), \cd{:line-relative} (tab as by
\cd{{\Xtilde}{\Xatsign}T}), or \cd{:section-relative} (tab as by
\cd{{\Xtilde}{\Xatsign}T}, but measuring horizontal positions relative to
the start of the dynamically enclosing section). An error is signaled if
any other value is supplied for \emph{kind}. If \emph{stream} is a pretty
printing stream created by \cdf{pprint-logical-block}, tabbing is performed.
Otherwise, \cdf{pprint-tab} has no effect. The value \cdf{nil} is always
returned.
\end{defun}
\begin{defun}[Function]
pprint-fill stream list &optional colon? atsign? \\
pprint-linear stream list &optional colon? atsign? \\
pprint-tabular stream list &optional colon? atsign? tabsize
These three functions specify particular ways of pretty printing lists.
\emph{Stream} follows the standard conventions for stream arguments to
printing functions. Each function prints parentheses around the output if
and only if \emph{colon?} (default \cdf{t}) is not \cdf{nil}. Each function
ignores its \emph{atsign?} argument and returns \cdf{nil}. (These two
arguments are included in this way so that these functions can be used via
\cd{{\Xtilde}/.../} and as \cdf{set-pprint-dispatch} functions as well as
directly.) Each function handles abbreviation and the detection of
circularity and sharing correctly and uses \cdf{write} to print \emph{list}
when given a non-list argument.
The function \cdf{pprint-linear} prints a list either all on one line or with
each element on a separate line. The function \cdf{pprint-fill} prints a list
with as many elements as possible on each line. The function
\cdf{pprint-tabular} is the same as \cdf{pprint-fill} except that it prints the
elements so that they line up in columns. This function takes an
additional argument \cdf{tabsize} (default 16) that specifies the column
spacing in ems.
\end{defun}
As an example of the interaction of logical blocks, conditional newlines,
and indentation, consider the function \cdf{pprint-defun} below. This
function pretty prints a list whose \emph{car} is \cdf{defun} in the standard way assuming
that the length of the list is exactly 4.
\begin{lisp}
;;; Pretty printer function for DEFUN forms. \\*
\\*
(defun pprint-defun (list) \\*
~~(pprint-logical-block (nil list :prefix "(" :suffix ")") \\*
~~~~(write (first list)) \\*
~~~~(write-char \#{\Xbackslash}space) \\*
~~~~(pprint-newline :miser) \\*
~~~~(pprint-indent :current 0) \\*
~~~~(write (second list)) \\*
~~~~(write-char \#{\Xbackslash}space) \\*
~~~~(pprint-newline :fill) \\*
~~~~(write (third list)) \\*
~~~~(pprint-indent :block 1) \\*
~~~~(write-char \#{\Xbackslash}space) \\*
~~~~(pprint-newline :linear) \\*
~~~~(write (fourth list))))
\end{lisp}
Suppose that one evaluates the following:
\begin{lisp}
(pprint-defun '(defun prod (x y) (* x y)))
\end{lisp}
If the line width available is greater than or equal to 26, all of the
output appears on one line. If the width is reduced to 25,
a line break is inserted at the linear-style conditional newline before
\cd{(*~X~Y)}, producing the output shown below. The
\cd{(pprint-indent~:block~1)} causes \cd{(*~X~Y)} to be printed at a relative
indentation of 1 in the logical block.
\begin{lisp}
(DEFUN PROD (X Y) \\*
~~(* X Y))
\end{lisp}
If the width is 15, a line break is also inserted at the
fill-style conditional newline before the argument list. The argument list lines
up under the function name because of the call on
\cd{(pprint-indent~:current~0)} before the printing of the function name.
\begin{lisp}
(DEFUN PROD \\*
~~~~~~~(X Y) \\*
~~(* X Y))
\end{lisp}
If \cdf{*print-miser-width*} were greater than or equal to 14,
the output would have been entirely in miser mode.
All indentation changes are
ignored in miser mode and line breaks are inserted at miser-style
conditional newlines. The result would have been as follows:
\begin{lisp}
(DEFUN \\*
~PROD \\*
~(X Y) \\*
~(* X Y))
\end{lisp}
As an example of the use of a per-line prefix, consider that evaluating the expression
\begin{lisp}
(pprint-logical-block (nil nil :per-line-prefix ";;; ") \\*
~~(pprint-defun '(defun prod (x y) (* x y))))
\end{lisp}
produces the output
\begin{lisp}
;;; (DEFUN PROD \\*
;;;~~~~~~~~(X Y) \\*
;;;~~~(* X Y))
\end{lisp}
with a line width of 20 and \cdf{nil} as the value
of the printer control variable \cdf{*print-miser-width*}.
(If \cdf{*print-miser-width*} were not \cdf{nil} the output
\begin{lisp}
;;; (DEFUN \\*
;;; ~PROD \\*
;;; ~(X Y) \\*
;;; ~(* X Y))
\end{lisp}
might appear instead.)
As a more complex (and realistic) example, consider the function
\cdf{pprint-let} below. This specifies how to pretty print a \cdf{let} in the
standard style. It is more complex than \cdf{pprint-defun} because it has
to deal with nested structure. Also, unlike \cdf{pprint-defun}, it contains
complete code to print readably any possible list that begins with the
symbol \cdf{let}. The outermost \cdf{pprint-logical-block} handles the
printing of the input list as a whole and specifies that parentheses should
be printed in the output. The second \cdf{pprint-logical-block} handles the
list of binding pairs. Each pair in the list is itself printed by the
innermost \cdf{pprint-logical-block}. (A \cdf{loop} is used instead of
merely decomposing the pair into two elements so that readable output will
be produced no matter whether the list corresponding to the pair has one
element, two elements, or (being malformed) has more than two elements.) A
space and a fill-style conditional newline are placed after each pair
except the last. The loop at the end of the topmost
\cdf{pprint-logical-block} prints out the forms in the body of the \cdf{let}
separated by spaces and linear-style conditional newlines.
\begin{lisp}
;;; Pretty printer function for LET forms, \\*
;;; carefully coded to handle malformed binding pairs. \\*
\\*
(defun pprint-let (list) \\*
~~(pprint-logical-block (nil list :prefix "(" :suffix ")") \\*
~~~~(write (pprint-pop)) \\*
~~~~(pprint-exit-if-list-exhausted) \\*
~~~~(write-char \#{\Xbackslash}space) \\*
~~~~(pprint-logical-block \\*
~~~~~~~~(nil (pprint-pop) :prefix "(" :suffix ")") \\*
~~~~~~(pprint-exit-if-list-exhausted) \\*
~~~~~~(loop (pprint-logical-block \\*
~~~~~~~~~~~~~~~~(nil (pprint-pop) :prefix "(" :suffix ")") \\*
~~~~~~~~~~~~~~(pprint-exit-if-list-exhausted) \\*
~~~~~~~~~~~~~~(loop (write (pprint-pop)) \\*
~~~~~~~~~~~~~~~~~~~~(pprint-exit-if-list-exhausted) \\*
~~~~~~~~~~~~~~~~~~~~(write-char \#{\Xbackslash}space) \\*
~~~~~~~~~~~~~~~~~~~~(pprint-newline :linear))) \\*
~~~~~~~~~~~~(pprint-exit-if-list-exhausted) \\*
~~~~~~~~~~~~(write-char \#{\Xbackslash}space) \\*
~~~~~~~~~~~~(pprint-newline :fill))) \\*
~~~~(pprint-indent :block 1) \\*
~~~~(loop (pprint-exit-if-list-exhausted) \\*
~~~~~~~~~~(write-char \#{\Xbackslash}space) \\*
~~~~~~~~~~(pprint-newline :linear) \\*
~~~~~~~~~~(write (pprint-pop)))))
\end{lisp}
Suppose that the following is evaluated with \cdf{*print-level*} having the value \cd{4} and
\cdf{*print-circle*} having the value \cdf{t}.
\begin{lisp}
(pprint-let '\#1=(let (x (*print-length* (f (g 3))) \\*
~~~~~~~~~~~~~~~~~~~~~~(z . 2) (k (car y))) \\*
~~~~~~~~~~~~~~~~~~(setq x (sqrt z)) \#1\#))
\end{lisp}
If the line length is greater than or equal to 77, the output produced
appears on one line. However, if the line length is 76, line breaks are
inserted at the linear-style conditional newlines separating the forms in
the body and the output below is produced. Note that the degenerate
binding pair \cdf{X} is printed readably even though it fails to be a list; a
depth abbreviation marker is printed in place of \cd{(G~3)}; the binding pair
\cd{(Z~.~2)} is printed readably even though it is not a proper list; and
appropriate circularity markers are printed.
\begin{lisp}
\#1=(LET (X (*PRINT-LENGTH* (F \#)) (Z . 2) (K (CAR Y))) \\*
~~~~~(SETQ X (SQRT Z)) \\*
~~~~~\#1\#)
\end{lisp}
If the line length is reduced to 35, a line break is inserted at one of the
fill-style conditional newlines separating the binding pairs.
\begin{lisp}
\#1=(LET (X (*PRINT-PRETTY* (F \#)) \\*
~~~~~~~~~(Z . 2) (K (CAR Y))) \\*
~~~~~(SETQ X (SQRT Z)) \\*
~~~~~\#1\#)
\end{lisp}
Suppose that the line length is further reduced to 22 and \cdf{*print-length*} is
set to 3. In this situation, line breaks are inserted after both the first
and second binding pairs. In addition, the second binding pair is itself
broken across two lines. Clause (b) of the description of fill-style
conditional newlines prevents the binding pair \cd{(Z~.~2)} from being printed
at the end of the third line. Note that the length abbreviation hides the
circularity from view and therefore the printing of circularity markers
disappears.
\begin{lisp}
(LET (X \\*
~~~~~~(*PRINT-LENGTH* \\*
~~~~~~~(F \#)) \\*
~~~~~~(Z . 2) ...) \\*
~~(SETQ X (SQRT Z)) \\*
~~...)
\end{lisp}
The function \cdf{pprint-tabular} could be defined as follows:
\begin{lisp}
(defun pprint-tabular (s list \&optional (c? t) a? (size 16)) \\*
~~(declare (ignore a?)) \\*
~~(pprint-logical-block \\*
~~~~~~(s list :prefix (if c? "(" "") :suffix (if c? ")" "")) \\*
~~~~(pprint-exit-if-list-exhausted) \\*
~~~~(loop (write (pprint-pop) :stream s) \\*
~~~~~~~~~~(pprint-exit-if-list-exhausted) \\*
~~~~~~~~~~(write-char \#{\Xbackslash}space s) \\*
~~~~~~~~~~(pprint-tab :section-relative 0 size s) \\*
~~~~~~~~~~(pprint-newline :fill s))))
\end{lisp}
Evaluating the following with a line length of 25 produces the output shown.
\begin{lisp}
(princ "Roads ") \\*
(pprint-tabular nil '(elm main maple center) nil nil 8) \\*
\\
Roads ELM~~~~~MAIN \\*
~~~~~~MAPLE~~~CENTER
\end{lisp}
The function below prints a vector using \cd{\#(...)} notation.
\begin{lisp}
(defun pprint-vector (v) \\*
~~(pprint-logical-block (nil nil :prefix "\#(" :suffix ")") \\*
~~~~(let ((end (length v)) (i 0)) \\*
~~~~~~(when (plusp end) \\*
~~~~~~~~(loop (pprint-pop) \\*
~~~~~~~~~~~~~~(write (aref v i)) \\*
~~~~~~~~~~~~~~(if (= (incf i) end) (return nil)) \\*
~~~~~~~~~~~~~~(write-char \#{\Xbackslash}space) \\*
~~~~~~~~~~~~~~(pprint-newline :fill))))))
\end{lisp}
Evaluating the following with a line length of 15 produces the output shown.
\begin{lisp}
(pprint-vector '\#(12 34 567 8 9012 34 567 89 0 1 23)) \\*
\\
\#(12 34 567 8 \\*
~~9012 34 567 \\*
~~89 0 1 23)
\end{lisp}
\section{Format Directive Interface}
\label{PPRINT-FORMAT-DIRECTIVES-SECTION}
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, \cdf{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 \cdf{format} when interacting with the pretty printer.
\begin{flushdesc}
\item[\cd{{\Xtilde}W}]
\emph{Write.} An \emph{arg}, any Lisp object, is printed obeying \emph{every}
printer control variable (as by \cdf{write}). In addition, \cd{{\Xtilde}W}
interacts correctly with depth abbreviation by not resetting the depth
counter to zero. \cd{{\Xtilde}W} does not accept parameters. If given the colon
modifier, \cd{{\Xtilde}W} binds \cdf{*print-pretty*} to \cdf{t}. If given the atsign
modifier, \cd{{\Xtilde}W} binds \cdf{*print-level*} and \cdf{*print-length*} to
\cdf{nil}.
\cd{{\Xtilde}W} provides automatic support for circularity detection. If
\cdf{*print-circle*} (and possibly also \cdf{*print-shared*}) is not \cdf{nil} and
\cd{{\Xtilde}W} is applied to an argument that is a circular (or shared) reference,
an appropriate ``\cd{\#\emph{n}\#}'' marker is inserted in the output
instead of printing the argument.
\item[\cd{{\Xtilde}{\Xunderscore}}]
\emph{Conditional newline.} Without any modifiers,
\cd{{\Xtilde}{\Xunderscore}} is equivalent to
\cd{(pprint-newline :linear)}.
The directive \cd{{\Xtilde}{\Xatsign}{\Xunderscore}} is
equivalent to \cd{(pprint-newline :miser)}.
The directive \cd{{\Xtilde}:{\Xunderscore}}
is equivalent to \cd{(pprint-newline :fill)}.
The directive \cd{{\Xtilde}:{\Xatsign}{\Xunderscore}} is
equivalent to \cd{(pprint-newline :mandatory)}.
\item[\cd{{\Xtilde}<\emph{str}{\Xtilde}:>}]
\emph{Logical block.} If \cd{{\Xtilde}:>} is used to terminate a
\cd{{\Xtilde}<...} directive, the directive is equivalent to a call on
\cdf{pprint-logical-block}. The \cdf{format} argument corresponding to the
\cd{{\Xtilde}<...{\Xtilde}:>} directive is treated in the same way as the \emph{list}
argument to \cdf{pprint-logical-block}, thereby providing automatic support for
non-list arguments and the detection of circularity, sharing, and depth abbreviation.
The portion of the \cdf{format} control string nested within the
\cd{{\Xtilde}<...{\Xtilde}:>} specifies the \cd{:prefix} (or \cd{:per-line-prefix}),
\cd{:suffix}, and body of the \cdf{pprint-logical-block}.
The \cdf{format} string portion enclosed by \cd{{\Xtilde}<...{\Xtilde}:>} can be
divided into segments \cd{{\Xtilde}<\emph{prefix\/}{\Xtilde};\emph{body\/}{\Xtilde};
\emph{suffix}{\Xtilde}:>} by \cd{{\Xtilde};} directives. If the first section is
terminated by \cd{\Xtilde\Xatsign;}, it specifies a per-line prefix rather than a
simple prefix. The prefix and suffix cannot contain \cdf{format} directives.
An error is signaled if either the prefix or suffix 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 suffix defaults
to the null string. If the enclosed portion consists of only a single
segment, both the prefix and the suffix default to the null string. If the
colon modifier is used (that is, \cd{{\Xtilde}:<...{\Xtilde}:>}), the prefix and
suffix default to \cd{"("} and \cd{")"}, respectively, instead of the null
string.
The body segment can be any arbitrary \cdf{format} control string. This \cdf{format}
control string is applied to the elements of the list corresponding to the
\cd{{\Xtilde}<...{\Xtilde}:>} directive as a whole. Elements are extracted from this
list using \cdf{pprint-pop}, thereby providing automatic support for malformed lists
and the detection of circularity, sharing, and length abbreviation.
Within the body segment, \cd{\Xtilde\Xcircumflex} acts like
\cdf{pprint-exit-if-list-exhausted}.
\cd{{\Xtilde}<...{\Xtilde}:>} supports a feature not supported by
\cdf{pprint-logical-block}. If \cd{\Xtilde:\Xatsign>} is used to terminate the
directive (that is, \cd{{\Xtilde}<...{\Xtilde}:\Xatsign>}), then a fill-style
conditional newline is automatically inserted after each group of blanks
immediately contained in the body (except for blanks after a
\cd{\Xtilde<newline>} directive). This makes it easy to achieve the equivalent
of paragraph filling.
If the atsign modifier is used with \cd{{\Xtilde}<...{\Xtilde}:>}, the
entire remaining argument list is passed to the directive as its argument.
All of the remaining arguments are always consumed by
\cd{{\Xtilde}\Xatsign<...{\Xtilde}:>}, even if they are not all used by the
\cdf{format} string nested in the directive. Other than the difference in its
argument, \cd{{\Xtilde}\Xatsign<...{\Xtilde}:>} is exactly the same as
\cd{{\Xtilde}<...{\Xtilde}:>}, except that circularity (and sharing) detection
is not applied if the \cd{{\Xtilde}\Xatsign<...{\Xtilde}:>} is at top level
in a \cdf{format} string. This ensures that circularity detection is applied
only to data lists and not to \cdf{format} argument lists.
To a considerable extent, the basic form of the directive
\cd{{\Xtilde}<...{\Xtilde}>} is incompatible with the dynamic control of
the arrangement of output by \cd{{\Xtilde}W}, \cd{{\Xtilde}\Xunderscore},
\cd{{\Xtilde}<...{\Xtilde}:>}, \cd{{\Xtilde}I}, and \cd{{\Xtilde}:T}. As
a result, an error is signaled if any of these directives is nested within
\cd{{\Xtilde}<...{\Xtilde}>}. Beyond this, an error is also signaled if
the \cd{{\Xtilde}<...{\Xtilde}:;...{\Xtilde}>} form of
\cd{{\Xtilde}<...{\Xtilde}>} is used in the same \cdf{format} string with
\cd{{\Xtilde}W}, \cd{{\Xtilde}\Xunderscore},
\cd{{\Xtilde}<...{\Xtilde}:>}, \cd{{\Xtilde}I}, or \cd{{\Xtilde}:T}.
\item[\cd{{\Xtilde}I}]
\emph{Indent.} \cd{{\Xtilde}\emph{n}I} is equivalent to
\cd{(pprint-indent~:block~\emph{n})}. \cd{{\Xtilde}:\emph{n}I} is equivalent to
\cd{(pprint-indent~:current~\emph{n})}. In both cases, \emph{n} defaults to zero
if it is omitted.
\item[\cd{{\Xtilde}:T}]
\emph{Tabulate.} If the colon modifier is used with the \cd{{\Xtilde}T}
directive, the tabbing computation is done relative to the column where the
section immediately containing the directive begins, rather than with
respect to column zero. \cd{{\Xtilde}\emph{n},\emph{m}:T} is equivalent to
\cd{(pprint-tab~:section~\emph{n}~\emph{m})}. \cd{{\Xtilde}\emph{n},\emph{m}:{\Xatsign}T}
is equivalent to \cd{(pprint-tab~:section-relative~\emph{n}~\emph{m})}. The numerical
parameters are both interpreted as being in units of ems and both default
to 1.
\item[\cd{{\Xtilde}/\emph{name}/}]
\emph{Call function.} User-defined functions can be called from within a
\cdf{format} string by using the directive \cd{{\Xtilde}/\emph{name}/}. The
colon modifier, the atsign modifier, and arbitrarily many parameters can be
specified with the \cd{{\Xtilde}/\emph{name}/} directive. The \emph{name}
can be any string that does not contain ``\cdf{/}''. All of the characters
in \emph{name} are treated as if they were upper case. If \emph{name}
contains a ``\cd{:}'' or ``\cd{::}'', then everything up to but not
including the first ``\cd{:}'' or ``\cd{::}'' is taken to be a string that
names a package. Everything after the first ``\cd{:}'' or ``\cd{::}'' (if
any) is taken to be a string that names a symbol. The function
corresponding to a \cd{{\Xtilde}/\emph{name}/} directive is obtained by
looking up the symbol that has the indicated name in the indicated package.
If \emph{name} does not contain a ``\cd{:}'' or ``\cd{::}'', then the whole
name string is looked up in the \cdf{user} package.
When a \cd{{\Xtilde}/\emph{name}/} directive is encountered, the indicated
function is called with four or more arguments. The first four arguments
are the output stream, the \cdf{format} argument corresponding to the
directive, the value \cdf{t} if the colon modifier was used (\cdf{nil}
otherwise), and the value \cdf{t} if the atsign modifier was used (\cdf{nil}
otherwise). The remaining arguments consist of any parameters specified
with the directive. The function should print the argument appropriately.
Any values returned by the function are ignored.
The three functions \cdf{pprint-linear}, \cdf{pprint-fill}, and
\cdf{pprint-tabular} are designed so that they can be called by
\cd{\Xtilde/.../} (that is, \cd{{\Xtilde}/pprint-linear/},
\cd{{\Xtilde}/pprint-fill/}, and \cd{{\Xtilde}/pprint-tabular/}. In
particular they take colon and atsign arguments.
\end{flushdesc}
As examples of the convenience of specifying pretty printing with
\cdf{format} strings, consider the functions \cdf{pprint-defun}
and \cdf{pprint-let} used as
examples in the last section. They can be more compactly defined as follows. The
function \cdf{pprint-vector} cannot be defined using \cdf{format}, because the data
structure it traverses is not a list. The function \cdf{pprint-tabular} is
inconvenient to define using \cdf{format}, because of the need to pass its
\cdf{tabsize} argument through to a \cd{\Xtilde:T} directive nested within
an iteration over a list.
\begin{lisp}
(defun pprint-defun (list) \\*
~~(format t
"{\Xtilde}:<{\Xtilde}W~{\Xtilde}\Xatsign\Xunderscore{\Xtilde}:I{\Xtilde}W~{\Xtilde}:\Xunderscore{\Xtilde}W{\Xtilde}1I~{\Xtilde}\Xunderscore{\Xtilde}W{\Xtilde}:>"
list))\\
\\
(defun pprint-let (list) \\*
~~(format t "{\Xtilde}:<{\Xtilde}W{\Xtilde}{\Xcircumflex} \relax
{\Xtilde}:<{\Xtilde}{\Xatsign}\{{\Xtilde}:<{\Xtilde}{\Xatsign}\{{\Xtilde}W{\Xtilde}{\Xcircumflex} \relax
{\Xtilde}{\Xunderscore}{\Xtilde}\}{\Xtilde}:>{\Xtilde}{\Xcircumflex} \relax
{\Xtilde}:{\Xunderscore}{\Xtilde}\}{\Xtilde}:>{\Xtilde}1I{\Xtilde} \\*
~~~~~~~~~~~~~~~~{\Xtilde}{\Xatsign}\{{\Xtilde}{\Xcircumflex} {\Xtilde}{\Xunderscore}{\Xtilde}W{\Xtilde}\}{\Xtilde}:>" \\*
~~~~~~~~~~list))
\end{lisp}
\section{Compiling Format Control Strings}
The control strings used by \cdf{format} are essentially programs that
perform printing. The macro \cdf{formatter} provides the efficiency of
using a compiled function for printing without losing the visual compactness of
\cdf{format} strings.
\begin{defmac}
formatter control-string
The \emph{control-string} must be a literal string. An error is signaled if
\emph{control-string} is not a valid \cdf{format} control string. The macro
\cdf{formatter} expands into an expression of the form
\cd{(function~(lambda~(stream~\&rest~args)~...))} that does the printing
specified by \emph{control-string}. The \cdf{lambda} created accepts an
output stream as its first argument and zero or more data values as its
remaining arguments. The value returned by the \cdf{lambda} is the tail (if
any) of the data values that are not printed out by \emph{control-string}.
(For example, if the \emph{control-string} is \cd{"{\Xtilde}A{\Xtilde}A"}, the
\cdf{cddr} (if any) of the data values is returned.) The form
\cd{(formatter~"{\Xtilde}\%{\Xtilde}2\Xatsign\{{\Xtilde}S,~{\Xtilde}\}")} is
equivalent to the following:
\begin{lisp}
\#'(lambda (stream \&rest args) \\*
~~~~(terpri stream) \\*
~~~~(dotimes (n 2) \\*
~~~~~~(if (null args) (return nil)) \\*
~~~~~~(prin1 (pop args) stream) \\*
~~~~~~(write-string ", " stream)) \\*
~~~~args)
\end{lisp}
In support of the above mechanism, \cdf{format} is extended so that it accepts
functions as its second argument as well as strings. When a function is
provided, it must be a function of the form created by \cdf{formatter}. The
function is called with the appropriate output stream as its first argument
and the data arguments to \cdf{format} as its remaining arguments. The
function should perform whatever output is necessary and return the unused
tail of the arguments (if any). The directives \cd{\Xtilde?} and
\cd{\Xtilde\{\Xtilde\}} with no body are also extended so that they accept
functions as well as control strings. Every other standard function that
takes a \cdf{format} string as an argument (for example, \cdf{error} and \cdf{warn})
is also extended so that it can accept functions of the form above
instead.
\end{defmac}
\section{Pretty Printing Dispatch Tables}
When \cdf{*print-pretty*} is not \cdf{nil}, the pprint dispatch table in the variable
\cdf{*print-pprint-dispatch*} controls how objects are printed. The information
in this table takes precedence over all other mechanisms for specifying how
to print objects. In particular, it overrides user-defined \cdf{print-object}
methods and print functions for structures. However, if there is no
specification for how to pretty print a particular kind of object, it is then
printed using the standard mechanisms as if \cdf{*print-pretty*} were \cdf{nil}.
A pprint dispatch table is a mapping from keys to pairs of values. The keys
are type specifiers. The values are functions and numerical priorities.
Basic insertion and retrieval is done based on the keys with the equality
of keys being tested by \cdf{equal}. The function to use when pretty printing an
object is chosen by finding the highest priority function in
\cdf{*print-pprint-dispatch*} that is associated with a type specifier that
matches the object.
\begin{defun}[Function]
copy-pprint-dispatch &optional table
A copy is made of \emph{table}, which defaults to the current pprint dispatch
table. If \emph{table} is \cdf{nil}, a copy is returned of the initial value of
\cdf{*print-pprint-dispatch*}.
\end{defun}
\begin{defun}[Function]
pprint-dispatch object &optional table
This retrieves the highest priority function from a pprint table that is
associated with a type specifier in the table that matches \emph{object}.
The function is chosen by finding all the type specifiers in \emph{table}
that match the object and selecting the highest priority function
associated with any of these type specifiers. If there is more than one
highest priority function, an arbitrary choice is made. If no type
specifiers match the object, a function is returned that prints object with
\cdf{*print-pretty*} bound to \cdf{nil}.
As a second return value, \cdf{pprint-dispatch} returns a flag that is \cdf{t} if a
matching type specifier was found in \emph{table} and \cdf{nil} if not.
\emph{Table} (which defaults to \cdf{*print-pprint-dispatch*}) must be a
pprint dispatch table. \emph{Table} can be \cdf{nil}, in which case
retrieval is done in the initial value of \cdf{*print-pprint-dispatch*}.
When \cdf{*print-pretty*} is \cdf{t}, \cd{(write~object~:stream~s)} is equivalent to
\cd{(funcall~(pprint-dispatch~object)~s~object)}.
\end{defun}
\begin{defun}[Function]
set-pprint-dispatch type function &optional priority table
This puts an entry into a pprint dispatch table and returns \cdf{nil}. The {\it
type} must be a valid type specifier and is the key of the entry.
The first action of \cdf{set-pprint-dispatch} is to remove any pre-existing
entry associated with \emph{type}. This guarantees that there
will never be two entries associated with the same type specifier in a
given pprint dispatch table. Equality of type specifiers is tested by
\cdf{equal}.
Two values are associated with each type specifier in a pprint dispatch
table: a function and a priority. The \emph{function} must accept two
arguments: the stream to send output to and the object to be printed.