Skip to content

Commit 404110d

Browse files
tomfaulhaberstuarthalloway
authored andcommitted
I added a new macro, print-length-loop, that augments loop to only iterate *print-length* times and then emit the "...". This makes it easy to write correct hand-coded dispatch functions.
Signed-off-by: Stuart Halloway <[email protected]>
1 parent f30995c commit 404110d

File tree

4 files changed

+90
-8
lines changed

4 files changed

+90
-8
lines changed

src/clj/clojure/pprint.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ See documentation for pprint and cl-format for more information or
3535
complete documentation on the the clojure web site on github.",
3636
:added "1.2"}
3737
clojure.pprint
38-
(:refer-clojure :exclude (deftype)))
38+
(:refer-clojure :exclude (deftype))
39+
(:use [clojure.walk :only [walk]]))
3940

4041

4142
(load "pprint/utilities")

src/clj/clojure/pprint/dispatch.clj

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
;;; (def pprint-simple-list (formatter-out "~:<~@{~w~^ ~_~}~:>"))
6666
(defn- pprint-simple-list [alis]
6767
(pprint-logical-block :prefix "(" :suffix ")"
68-
(loop [alis (seq alis)]
68+
(print-length-loop [alis (seq alis)]
6969
(when alis
7070
(write-out (first alis))
7171
(when (next alis)
@@ -80,7 +80,7 @@
8080
;;; (def pprint-vector (formatter-out "~<[~;~@{~w~^ ~_~}~;]~:>"))
8181
(defn- pprint-vector [avec]
8282
(pprint-logical-block :prefix "[" :suffix "]"
83-
(loop [aseq (seq avec)]
83+
(print-length-loop [aseq (seq avec)]
8484
(when aseq
8585
(write-out (first aseq))
8686
(when (next aseq)
@@ -93,12 +93,13 @@
9393
;;; (def pprint-map (formatter-out "~<{~;~@{~<~w~^ ~_~w~:>~^, ~_~}~;}~:>"))
9494
(defn- pprint-map [amap]
9595
(pprint-logical-block :prefix "{" :suffix "}"
96-
(loop [aseq (seq amap)]
96+
(print-length-loop [aseq (seq amap)]
9797
(when aseq
9898
(pprint-logical-block
9999
(write-out (ffirst aseq))
100100
(.write ^java.io.Writer *out* " ")
101101
(pprint-newline :linear)
102+
(set! *current-length* 0) ; always print both parts of the [k v] pair
102103
(write-out (fnext (first aseq))))
103104
(when (next aseq)
104105
(.write ^java.io.Writer *out* ", ")
@@ -218,7 +219,7 @@
218219

219220
(defn- pprint-binding-form [binding-vec]
220221
(pprint-logical-block :prefix "[" :suffix "]"
221-
(loop [binding binding-vec]
222+
(print-length-loop [binding binding-vec]
222223
(when (seq binding)
223224
(pprint-logical-block binding
224225
(write-out (first binding))
@@ -255,7 +256,7 @@
255256
(when (next alis)
256257
(.write ^java.io.Writer *out* " ")
257258
(pprint-newline :linear)
258-
(loop [alis (next alis)]
259+
(print-length-loop [alis (next alis)]
259260
(when alis
260261
(pprint-logical-block alis
261262
(write-out (first alis))
@@ -273,7 +274,7 @@
273274
(pprint-logical-block :prefix "(" :suffix ")"
274275
(pprint-indent :block 1)
275276
(apply (formatter-out "~w ~@_~w ~@_~w ~_") alis)
276-
(loop [alis (seq (drop 3 alis))]
277+
(print-length-loop [alis (seq (drop 3 alis))]
277278
(when alis
278279
(pprint-logical-block alis
279280
(write-out (first alis))
@@ -315,7 +316,7 @@
315316
(defn- pprint-simple-code-list [alis]
316317
(pprint-logical-block :prefix "(" :suffix ")"
317318
(pprint-indent :block 1)
318-
(loop [alis (seq alis)]
319+
(print-length-loop [alis (seq alis)]
319320
(when alis
320321
(write-out (first alis))
321322
(when (next alis)

src/clj/clojure/pprint/pprint_base.clj

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,33 @@ THIS FUNCTION IS NOT YET IMPLEMENTED."
371371
(throw (UnsupportedOperationException. "pprint-tab is not yet implemented")))
372372

373373

374+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
375+
;;;
376+
;;; Helpers for dispatch function writing
377+
;;;
378+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
379+
380+
(defn- pll-mod-body [var-sym body]
381+
(letfn [(inner [form]
382+
(if (seq? form)
383+
(let [form (macroexpand form)]
384+
(condp = (first form)
385+
'loop* form
386+
'recur (concat `(recur (inc ~var-sym)) (rest form))
387+
(walk inner identity form)))
388+
form))]
389+
(walk inner identity body)))
390+
391+
(defmacro print-length-loop
392+
"A version of loop that iterates at most *print-length* times. This is designed
393+
for use in pretty-printer dispatch functions."
394+
{:added "1.3"}
395+
[bindings & body]
396+
(let [count-var (gensym "length-count")
397+
mod-body (pll-mod-body count-var body)]
398+
`(loop ~(apply vector count-var 0 bindings)
399+
(if (or (not *print-length*) (< ~count-var *print-length*))
400+
(do ~@mod-body)
401+
(.write ^java.io.Writer *out* "...")))))
402+
374403
nil

test/clojure/test_clojure/pprint/test_pretty.clj

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,55 @@ Usage: *hello*
272272
"[\"hello\" \"there\"]\n"
273273
)
274274

275+
(simple-tests print-length-tests
276+
(binding [*print-length* 1] (with-out-str (pprint '(a b c d e f))))
277+
"(a ...)\n"
278+
(binding [*print-length* 2] (with-out-str (pprint '(a b c d e f))))
279+
"(a b ...)\n"
280+
(binding [*print-length* 6] (with-out-str (pprint '(a b c d e f))))
281+
"(a b c d e f)\n"
282+
(binding [*print-length* 8] (with-out-str (pprint '(a b c d e f))))
283+
"(a b c d e f)\n"
284+
285+
(binding [*print-length* 1] (with-out-str (pprint [1 2 3 4 5 6])))
286+
"[1 ...]\n"
287+
(binding [*print-length* 2] (with-out-str (pprint [1 2 3 4 5 6])))
288+
"[1 2 ...]\n"
289+
(binding [*print-length* 6] (with-out-str (pprint [1 2 3 4 5 6])))
290+
"[1 2 3 4 5 6]\n"
291+
(binding [*print-length* 8] (with-out-str (pprint [1 2 3 4 5 6])))
292+
"[1 2 3 4 5 6]\n"
293+
294+
;; This set of tests isn't that great cause it assumes that the set remains
295+
;; ordered for printing. This is currently (1.3) true, but no future
296+
;; guarantees
297+
(binding [*print-length* 1] (with-out-str (pprint #{1 2 3 4 5 6})))
298+
"#{1 ...}\n"
299+
(binding [*print-length* 2] (with-out-str (pprint #{1 2 3 4 5 6})))
300+
"#{1 2 ...}\n"
301+
(binding [*print-length* 6] (with-out-str (pprint #{1 2 3 4 5 6})))
302+
"#{1 2 3 4 5 6}\n"
303+
(binding [*print-length* 8] (with-out-str (pprint #{1 2 3 4 5 6})))
304+
"#{1 2 3 4 5 6}\n"
305+
306+
;; See above comment and apply to this map :)
307+
(binding [*print-length* 1] (with-out-str (pprint {1 2, 3 4, 5 6, 7 8, 9 10, 11 12})))
308+
"{1 2, ...}\n"
309+
(binding [*print-length* 2] (with-out-str (pprint {1 2, 3 4, 5 6, 7 8, 9 10, 11 12})))
310+
"{1 2, 3 4, ...}\n"
311+
(binding [*print-length* 6] (with-out-str (pprint {1 2, 3 4, 5 6, 7 8, 9 10, 11 12})))
312+
"{1 2, 3 4, 5 6, 7 8, 9 10, 11 12}\n"
313+
(binding [*print-length* 8] (with-out-str (pprint {1 2, 3 4, 5 6, 7 8, 9 10, 11 12})))
314+
"{1 2, 3 4, 5 6, 7 8, 9 10, 11 12}\n"
315+
316+
317+
(binding [*print-length* 1] (with-out-str (pprint (int-array [1 2 3 4 5 6]))))
318+
"[1, ...]\n"
319+
(binding [*print-length* 2] (with-out-str (pprint (int-array [1 2 3 4 5 6]))))
320+
"[1, 2, ...]\n"
321+
(binding [*print-length* 6] (with-out-str (pprint (int-array [1 2 3 4 5 6]))))
322+
"[1, 2, 3, 4, 5, 6]\n"
323+
(binding [*print-length* 8] (with-out-str (pprint (int-array [1 2 3 4 5 6]))))
324+
"[1, 2, 3, 4, 5, 6]\n"
325+
)
275326

0 commit comments

Comments
 (0)