aboutsummaryrefslogtreecommitdiff
path: root/branch-master/doc/pprint/PrettyPrinting.html
blob: 323a8ee9a8eec0d1834c487ace75d457c2ca1646 (plain)
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
<html>
  <head>
    <title>A Pretty Printer for Clojure</title>
    <link href="../../../static/favicon.png" rel="icon" />
    <link href="../../../static/favicon.png" rel="shortcut icon" />
    <link media="all" type="text/css" href="../../../static/clojure.css" rel="stylesheet" />
    <link media="all" type="text/css" href="../../../static/wiki.css" rel="stylesheet" />
    <link media="all" type="text/css" href="../../../static/internal.css" rel="stylesheet" />
    <!-- TODO: are we using these (from clojure.org)? If so, add the files -->
    <script src="file/view/code_highlighter.js" type="text/javascript"></script>
    <script src="file/view/clojure.js" type="text/javascript"></script>
    <style>.menuWrapper{height: 36px;}</style>
    <!--[if lte IE 6]>
    <link rel="stylesheet" href="http://www.wikispaces.com/_/2009051601/s/internal_ie.css" type="text/css" />
    <![endif]-->
  </head>
<!--
This document was auto-generated from the source by the clojure autodoc system.
To report errors or ask questions about the overall documentation structure, formatting,
etc., contact Tom Faulhaber (google mail name: tomfaulhaber).
For errors in the documentation of a particular namespace, contact the author of that
namespace.
-->
  <body>
    <div id="AllContentContainer">
      <div id="Header">
	<a id="Logo" href="index.html"><img alt="Clojure" height="100" width="100" src="../../../static/clojure-icon.gif" /></a>
	<h1><a title="page header title" id="page-header" href="index.html">Clojure-contrib API Reference</a></h1>
      </div>
      <div id="leftcolumn"><div style="text-align: center;"></div>
<div class="menu">
  <div class="WikiCustomNav WikiElement wiki">
    <span class="toc-header"><span id="project-name">clojure-contrib</span> <span id="version">v1.3</span> API</span><br />
    <ul>
      <li><a class="wiki_link" href="../../../index.html">Overview</a></li>
      <li><a class="wiki_link" href="../../../api-index.html">API Index</a></li>
    </ul>
    <span class="toc-header">Namespaces</span>
    <ul id="left-sidebar-list">
      <li><a href="../../../accumulators-api.html" class="wiki_link">accumulators</a></li><li><a href="../../../agent-utils-api.html" class="wiki_link">agent-utils</a></li><li><a href="../../../base64-api.html" class="wiki_link">base64</a></li><li><a href="../../../classpath-api.html" class="wiki_link">classpath</a></li><li><a href="../../../combinatorics-api.html" class="wiki_link">combinatorics</a></li><li><a href="../../../command-line-api.html" class="wiki_link">command-line</a></li><li><a href="../../../complex-numbers-api.html" class="wiki_link">complex-numbers</a></li><li><a href="../../../cond-api.html" class="wiki_link">cond</a></li><li><a href="../../../condition-api.html" class="wiki_link">condition</a></li><li><a href="../../../core-api.html" class="wiki_link">core</a></li><li><a href="../../../dataflow-api.html" class="wiki_link">dataflow</a></li><li><a href="../../../datalog-api.html" class="wiki_link">datalog</a></li><li><a href="../../../def-api.html" class="wiki_link">def</a></li><li><a href="../../../error-kit-api.html" class="wiki_link">error-kit</a></li><li><a href="../../../except-api.html" class="wiki_link">except</a></li><li><a href="../../../fcase-api.html" class="wiki_link">fcase</a></li><li><a href="../../../find-namespaces-api.html" class="wiki_link">find-namespaces</a></li><li><a href="../../../fnmap-api.html" class="wiki_link">fnmap</a></li><li><a href="../../../gen-html-docs-api.html" class="wiki_link">gen-html-docs</a></li><li><a href="../../../generic.arithmetic-api.html" class="wiki_link">generic.arithmetic</a></li><li><a href="../../../generic.collection-api.html" class="wiki_link">generic.collection</a></li><li><a href="../../../generic.comparison-api.html" class="wiki_link">generic.comparison</a></li><li><a href="../../../generic.functor-api.html" class="wiki_link">generic.functor</a></li><li><a href="../../../generic.math-functions-api.html" class="wiki_link">generic.math-functions</a></li><li><a href="../../../graph-api.html" class="wiki_link">graph</a></li><li><a href="../../../greatest-least-api.html" class="wiki_link">greatest-least</a></li><li><a href="../../../import-static-api.html" class="wiki_link">import-static</a></li><li><a href="../../../io-api.html" class="wiki_link">io</a></li><li><a href="../../../jar-api.html" class="wiki_link">jar</a></li><li><a href="../../../java-utils-api.html" class="wiki_link">java-utils</a></li><li><a href="../../../jmx-api.html" class="wiki_link">jmx</a></li><li><a href="../../../json-api.html" class="wiki_link">json</a></li><li><a href="../../../lazy-seqs-api.html" class="wiki_link">lazy-seqs</a></li><li><a href="../../../lazy-xml-api.html" class="wiki_link">lazy-xml</a></li><li><a href="../../../logging-api.html" class="wiki_link">logging</a></li><li><a href="../../../macro-utils-api.html" class="wiki_link">macro-utils</a></li><li><a href="../../../macros-api.html" class="wiki_link">macros</a></li><li><a href="../../../map-utils-api.html" class="wiki_link">map-utils</a></li><li><a href="../../../math-api.html" class="wiki_link">math</a></li><li><a href="../../../miglayout-api.html" class="wiki_link">miglayout</a></li><li><a href="../../../mmap-api.html" class="wiki_link">mmap</a></li><li><a href="../../../mock-api.html" class="wiki_link">mock</a></li><li><a href="../../../monadic-io-streams-api.html" class="wiki_link">monadic-io-streams</a></li><li><a href="../../../monads-api.html" class="wiki_link">monads</a></li><li><a href="../../../ns-utils-api.html" class="wiki_link">ns-utils</a></li><li><a href="../../../priority-map-api.html" class="wiki_link">priority-map</a></li><li><a href="../../../probabilities.finite-distributions-api.html" class="wiki_link">probabilities.finite-distributions</a></li><li><a href="../../../probabilities.monte-carlo-api.html" class="wiki_link">probabilities.monte-carlo</a></li><li><a href="../../../probabilities.random-numbers-api.html" class="wiki_link">probabilities.random-numbers</a></li><li><a href="../../../profile-api.html" class="wiki_link">profile</a></li><li><a href="../../../properties-api.html" class="wiki_link">properties</a></li><li><a href="../../../prxml-api.html" class="wiki_link">prxml</a></li><li><a href="../../../reflect-api.html" class="wiki_link">reflect</a></li><li><a href="../../../repl-ln-api.html" class="wiki_link">repl-ln</a></li><li><a href="../../../repl-utils-api.html" class="wiki_link">repl-utils</a></li><li><a href="../../../seq-api.html" class="wiki_link">seq</a></li><li><a href="../../../server-socket-api.html" class="wiki_link">server-socket</a></li><li><a href="../../../set-api.html" class="wiki_link">set</a></li><li><a href="../../../singleton-api.html" class="wiki_link">singleton</a></li><li><a href="../../../sql-api.html" class="wiki_link">sql</a></li><li><a href="../../../stream-utils-api.html" class="wiki_link">stream-utils</a></li><li><a href="../../../string-api.html" class="wiki_link">string</a></li><li><a href="../../../strint-api.html" class="wiki_link">strint</a></li><li><a href="../../../swing-utils-api.html" class="wiki_link">swing-utils</a></li><li><a href="../../../test-base64-api.html" class="wiki_link">test-base64</a></li><li><a href="../../../trace-api.html" class="wiki_link">trace</a></li><li><a href="../../../types-api.html" class="wiki_link">types</a></li><li><a href="../../../with-ns-api.html" class="wiki_link">with-ns</a></li><li><a href="../../../zip-filter-api.html" class="wiki_link">zip-filter</a></li>
    </ul>
    <div class="BranchTOC">
      <span class="toc-header">Other Versions</span>
      <ul id="left-sidebar-branch-list">
        <li><a href="../../../../index.html" class="wiki_link">v1.2 (stable)</a></li><li><a href="../../../../branch-1.1.x/index.html" class="wiki_link">v1.1 (stable)</a></li>
      </ul>
    </div>
    <a href="../../../http://clojure.org" class="wiki_link">Clojure Home</a>
  </div>
</div>
</div>
      <div id="rightcolumn">
	<div id="Content">
	  <div class="contentBox"><div class="innerContentBox">
              <div id="content_view" class="wiki wikiPage">
                <div id="right-sidebar"></div>
                <div id="content-tag"><html><body><h1>A Pretty Printer for Clojure</h1>

<p>To use pretty printing in clojure.contrib, it is necessary to build
clojure.contrib with compiled classes. To do this, you must tell
ant where to find clojure.jar. For me, this looks like:</p>

<pre><code> ant -Dclojure.jar=../clojure/clojure.jar
</code></pre>

<p>because I keep clojure source and clojure.contrib source right next to
each other. Just point the pathname to wherever you keep clojure.jar.</p>

<h2>Overview</h2>

<p>This library adds a new feature to Clojure: a generalized pretty
printer.</p>

<p>The pretty printer is easy to use:</p>

<pre><code>user=&gt; (println (for [x (range 10)] (range x)))
(() (0) (0 1) (0 1 2) (0 1 2 3) (0 1 2 3 4) (0 1 2 3 4 5) (0 1 2 3 4 5 6) (0 1 2 3 4 5 6 7) (0 1 2 3 4 5 6 7 8))
nil
user=&gt; (use 'clojure.contrib.pprint)             
nil
user=&gt; (pprint (for [x (range 10)] (range x)))         
(()
 (0)
 (0 1)
 (0 1 2)
 (0 1 2 3)
 (0 1 2 3 4)
 (0 1 2 3 4 5)
 (0 1 2 3 4 5 6)
 (0 1 2 3 4 5 6 7)
 (0 1 2 3 4 5 6 7 8))
nil
user=&gt;
</code></pre>

<p>The pretty printer supports two modes: <em>code</em> which has special
formatting for special forms and core macros and <em>simple</em> (the
default) which formats the various Clojure data structures as
appropriate for raw data. In the future, the pretty printer will be
highly customizable, but right now it is pretty simple.</p>

<p>All the functions and variables described here are in the
clojure.contrib.pprint namespace. Using them is as simple as including
clojure-contrib.jar to your classpath and adding a (:use clojure.contrib.pprint) to
your namespace declarations.</p>

<p>pprint is being developed by Tom Faulhaber (to mail me you can use
my first name at my domain which is infolace.com).</p>

<p>As part of clojure.contrib, the pretty printer is licensed under the 
[http://opensource.org/licenses/eclipse-1.0.php Eclipse Public License 1.0].</p>

<p>clojure.contrib is hosted on google code at [http://code.google.com/p/clojure-contrib/]</p>

<p>Future development is guided by those using it, so send feedback about
what's working and not working for you and what you'd like to see in the 
pretty printer.</p>

<h2>Pretty Printing Basics</h2>

<p>Pretty printing is primarily implemented with the function
pprint. pprint takes a single argument and formats it according to the
settings of several special variables.</p>

<p>Generally, the defaults are fine for pretty printing and you can
simply use:</p>

<pre><code>(pprint obj)
</code></pre>

<p>to print your object. If you wish to write to
another stream besides <code>*</code>out<code>*</code>, you can use:</p>

<pre><code>(write obj :pretty true :stream foo)
</code></pre>

<p>where foo is the stream to which you wish to write. (The write
function has a lot more options which are not yet documented. Stay
tuned.)</p>

<p>When at the REPL, the pp macro pretty prints the last output
value. This is useful when you get something too complex to read
comfortably. Just type:</p>

<pre><code>user=&gt; (pp)
</code></pre>

<p>and you'll get a pretty printed version of the last thing output (the
magic variable <code>*</code>1).</p>

<h2>Dispatch tables and code formatting</h2>

<p>The behavior of the pretty printer can be finely controlled through
the use of <em>dispatch tables</em> that contain descriptions for how
different structures should be formatted. </p>

<p>Using custom dispatch tables, the pretty printer can create formatted
output for data structures that is customized for the
application. This allows pretty printing to be baked into any
structured output. For information and examples, see below in
[#Custom<em>Dispatch</em>Functions Custom Dispatch Functions].</p>

<p>The pretty printer comes with two pre-defined dispatch tables to cover
the most common situations:</p>

<p><code>*</code>simple-dispatch<code>*</code> - supports basic representation of data in various
Clojure structures: seqs, maps, vectors, etc. in a fairly statndard
way. When structures need to be broken across lines, following lines
are indented to line up with the first element. <code>*</code>simple-dispatch<code>*</code> is
the default and is good from showing the output of most operations.</p>

<p><code>*</code>code-dispatch<code>*</code> - has special representation for various structures
found in code: defn, condp, binding vectors, anonymous functions,
etc. This dispatch indents following lines of a list one more space as
appropriate for a function/argument type of list.</p>

<p>An example formatted with code dispatch:</p>

<pre><code>user=&gt; (def code '(defn cl-format 
"An implementation of a Common Lisp compatible format function"
[stream format-in &amp; args] (let [compiled-format (if (string? format-in) 
(compile-format format-in) format-in) navigator (init-navigator args)] 
(execute-format stream compiled-format navigator))))
#'user/code
user=&gt; (with-pprint-dispatch *code-dispatch* (pprint code))
(defn cl-format
  "An implementation of a Common Lisp compatible format function"
  [stream format-in &amp; args]
  (let [compiled-format (if (string? format-in)
                          (compile-format format-in)
                          format-in)
        navigator (init-navigator args)]
    (execute-format stream compiled-format navigator)))
nil
user=&gt;
</code></pre>

<p>There are three ways to set the current dispatch: set it to a specific
table permanantly with set-pprint-dispatch, bind it with
with-pprint-dispatch (as shown in the example above), or use the
:dispatch keyword argument to write.</p>

<h2>Control variables</h2>

<p>The operation of pretty printing is also controlled by a set of variables
that control general parameters of how the pretty printer makes
decisions. The current list is as follows:</p>

<p><em><code>*</code>print-pretty<code>*</code></em>: Default: <em>true</em>  </p>

<p>Bind to true if you want write to use pretty printing. (pprint and pp automatically 
bind this to true.)</p>

<p><em><code>*</code>print-right-margin<code>*</code></em>: Default: <em>72</em></p>

<p>Pretty printing will try to avoid anything going beyond this column.</p>

<p><em><code>*</code>print-miser-width<code>*</code></em>: Default: <em>40</em></p>

<p>The column at which to enter miser style. Depending on the dispatch table, 
miser style add newlines in more places to try to keep lines short allowing for further 
levels of nesting. For example, in the code dispatch table, the pretty printer will 
insert a newline between the "if" and its condition when in miser style.</p>

<p><em><code>*</code>print-suppress-namespaces<code>*</code></em>: Default: <em>false</em></p>

<p>Don't print namespaces with symbols. This is particularly useful when 
pretty printing the results of macro expansions</p>

<p><em><code>*</code>print-level<code>*</code></em>: Default: <em>nil</em></p>

<p>As with the regular Clojure print function, this variable controls the 
depth of structure that is printed. The argument itself is level 0,
the first level of a collection is level 1, etc. When the structure
gets deeper than the specified <code>*</code>print-level<code>*</code>, a hash sign (#) is
printed.</p>

<p>For example:</p>

<pre><code>user=&gt; (binding [*print-level* 2] (pprint '(a b (c d) ((e) ((f d) g)))))
(a b (c d) (# #))
nil
user=&gt;
</code></pre>

<p><em><code>*</code>print-length<code>*</code></em>: Default: <em>nil</em></p>

<p>As with the regular Clojure print function, this variable controls the 
number of items that are printed at each layer of structure. When a
layer has too many items, elipses (...) are displayed. </p>

<p>For example:</p>

<pre><code>user=&gt; (defn foo [x] (for [i (range x) ] (range 1 (- x (dec i)))))
#'user/foo
user=&gt; (binding [*print-length* 6] (pprint (foo 10)))
((1 2 3 4 5 6 ...)
 (1 2 3 4 5 6 ...)
 (1 2 3 4 5 6 ...)
 (1 2 3 4 5 6 ...)
 (1 2 3 4 5 6)
 (1 2 3 4 5)
 ...)
nil
user=&gt;
</code></pre>

<h2>Custom Dispatch Functions</h2>

<p>Using custom dispatch, you can easily create your own formatted output
for structured data. Examples included with the pretty printer show
how to use custom dispatch to translate simple Clojure structures into
nicely formatted JSON and XML.</p>

<h3>Basic Concepts of Pretty Printing</h3>

<p>In order to create custom dispatch functions, you need to understand
the fundamentals of pretty printing. The clojure pretty printer is
based on the XP pretty printer algorithm (used in many Lisps including
Common Lisp) which supports sophisticated decision-making about line
breaking and indentation with reasonable performance even for very
large structures. The XP algorithm is documented in the paper,
[http://dspace.mit.edu/handle/1721.1/6504 XP. A Common Lisp Pretty
Printing System].</p>

<p>The Clojure implementation of XP is similar in spirit to the Common
Lisp implementation, but the details of the interface are somewhat
different. The result is that writing custom dispatch in Clojure is
more "Clojure-y."</p>

<p>There are three key concepts to understand when creating custom pretty
printing functions: <em>logical blocks</em>,  <em>conditional newlines</em>, and
<em>indentation</em>.</p>

<p>A <em>logical block</em> marks a set of output that should be thought about
as a single unit by the pretty printer. Logical blocks can contain
other logical blocks (that is, they nest). As a simple example, when
printing list structure, every sublist will typically be a logical
block.</p>

<p><em>Conditional newlines</em> tell the pretty printer where it can insert
line breaks and how to make the decisions about when to do it. There
are four types of conditional newline:</p>

<ul>
<li>Linear newlines tell the pretty printer to insert a newline in a
place whenever the enclosing logical block won't fit on a single
line. Linear newlines are an all-or-nothing proposition; if the
logical block doesn't fit on a single line, <em>all</em> the linear
newlines are emitted as actual newlines.</li>
<li>Fill newlines tell the pretty printer that it should fit as many
chunks of the logical block as possible on this line and then emit
a newline.</li>
<li>Mandatory newlines tell the pretty printer to emit a newline
regardless of where it is in the output line.  </li>
<li>Miser newlines tell the pretty printer to emit a newline if the
output column is in the miser region (as defined by the pretty
printer variable <code>*</code>pprint-miser-width<code>*</code>). This allows you to
define special behavior as the output gets heavily nested near the
right margin.</li>
</ul>

<p><em>Indentation</em> commands allow you to specify how wrapped lines should
be indented. Indentation can be relative to either the start column of
the current logical block or the current column position of the output. </p>

<p>(This section is still incomplete...)</p>

<h2>Current limitations and future plans</h2>

<p>This is an early version release of the pretty printer and there is
plenty that is yet to come.</p>

<p>Here are some examples:</p>

<ul>
<li>Support all the types and forms in Clojure (most of the way there now).</li>
<li>Support for limiting pretty printing based on line counts.</li>
<li>Support for circular and shared substructure detection.</li>
<li>Finishing the integration with the format function (support for ~/ and tabular pretty printing).</li>
<li>Performance! (Not much thought has been made to making this go fast, but there are a bunch of pretty obvious speedups to be had.)</li>
<li>Handle Java objects intelligently</li>
</ul>

<p>Please let me know about anything that's not working right, anything that
should work differently, or the feature you think should be at the top
of my list. </p>
</body></html></div>
              </div>
            </div>
          </div>
	</div>
	<div id="foot">
	  <div style="text-align: center;" id="copyright">Copyright 2007-2010 by Rich Hickey and the various contributors</div>
	</div>
      </div>
      <div id="DesignedBy">Logo &amp; site design by <a title="Visit Tom Hickey's website." href="http://www.tomhickey.com">Tom Hickey</a>.<br />
      Clojure auto-documentation system by Tom Faulhaber.</div>
    </div>
    <!-- /AllContentContainer -->
  </body>

</html>