Skip to content

Commit

Permalink
Fix "~n@*"-directives in clojure.pprint/cl-format. Fixes #CLJ-1134.
Browse files Browse the repository at this point in the history
This solves two issues as specified by #CLJ-1134. Issue #1 is solved by doing a
relative jump forward within `absolute-reposition` in cl_format.clj, line 114 by
switching `(- (:pos navigator) position)` with `(- position (:pos navigator))`.

Issue #2 is handled by changing the default `n`-parameter to `*` depending on
whether the `@`-prefix is placed or not. If it is placed, then `n` defaults to
0, otherwise it defaults to 1.

In addition, new tests have been appended to `test_cl_format.clj` to ensure the
correctness of this patch. The tests have been tested on the Common Lisp
implementation GNU CLISP 2.49, which presumably handle the `~n@*`
correctly. This patch and GNU CLISP returns the same output for each format
call, sans case for printed symbols; Common Lisp has case-insensitive symbols,
whereas Clojure has not.

Signed-off-by: Stuart Halloway <stu@cognitect.com>
  • Loading branch information
hypirion authored and stuarthalloway committed Jul 31, 2015
1 parent c4e0279 commit 8a8e1f9
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
17 changes: 9 additions & 8 deletions src/clj/clojure/pprint/cl_format.clj
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm

(defn- absolute-reposition [navigator position]
(if (>= position (:pos navigator))
(relative-reposition navigator (- (:pos navigator) position))
(relative-reposition navigator (- position (:pos navigator)))
(struct arg-navigator (:seq navigator) (drop position (:seq navigator)) position)))

(defn- relative-reposition [navigator position]
Expand Down Expand Up @@ -1471,14 +1471,15 @@ not a pretty writer (which keeps track of columns), this function always outputs
#(absolute-tabulation %1 %2 %3)))

(\*
[ :n [1 Integer] ]
[ :n [nil Integer] ]
#{ :colon :at } {}
(fn [params navigator offsets]
(let [n (:n params)]
(if (:at params)
(absolute-reposition navigator n)
(relative-reposition navigator (if (:colon params) (- n) n)))
)))
(if (:at params)
(fn [params navigator offsets]
(let [n (or (:n params) 0)] ; ~@* has a default n = 0
(absolute-reposition navigator n)))
(fn [params navigator offsets]
(let [n (or (:n params) 1)] ; whereas ~* and ~:* have a default n = 1
(relative-reposition navigator (if (:colon params) (- n) n))))))

(\?
[ ]
Expand Down
18 changes: 18 additions & 0 deletions test/clojure/test_clojure/pprint/test_cl_format.clj
Original file line number Diff line number Diff line change
Expand Up @@ -823,3 +823,21 @@ but it was called with an argument of type short-float.\n")
| -2/3 | | panda | dog |
"
)

(simple-tests *-at-tests
(format nil "~*~c defaults to ~D, so ~~@* goes ~A to the ~@*~A arg."
'first \n 0 'back)
"n defaults to 0, so ~@* goes back to the first arg."
(format nil "~~n@* is an ~1@*~A ~0@*~A rather than a ~2@*~A ~0@*~A."
'goto 'absolute 'relative)
"~n@* is an absolute goto rather than a relative goto."
(format nil "We will see no numbers: ~6@*~S"
0 1 2 3 4 5 :see?) "We will see no numbers: :see?"
(format nil "~4@*~D ~3@*~D ~2@*~D ~1@*~D ~0@*~D"
0 1 2 3 4) "4 3 2 1 0"
(format nil "~{~A a ~~{ ~3@*~A, the ~1@*~A is ~A to the ~4@*~A of ~A~}[...]"
'("Within" goto relative construct list arguments))
"Within a ~{ construct, the goto is relative to the list of arguments[...]"
(format nil "~{~2@*~S ~1@*~S ~4@*~S ~3@*~S ~S~}"
'(:a :b :c :d :e)) ":c :b :e :d :e"
)

0 comments on commit 8a8e1f9

Please sign in to comment.