Skip to content

Commit a330f18

Browse files
authored
Merge pull request #152 from clj-commons/hls/20250806-151-repeat-format
Fix repeat formatting with omitted frames, hide clojure.lang.RestFn stack frames
2 parents 2b30712 + f3bc259 commit a330f18

5 files changed

Lines changed: 42 additions & 52 deletions

File tree

CHANGES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 3.6.2 -- UNRELEASED
2+
3+
- Fix a bug where the horizontal bar for repeated stack frames could be misaligned
4+
- Hide `clojure.lang.RestFn` stack frames
5+
6+
[Closed Issues](https://github.com/clj-commons/pretty/milestone/61?closed=1)
7+
18
## 3.6.1 -- 4 Aug 2025
29

310
Fix a bug where omitted stack frames were printed.

docs/images/exception-repeat.png

217 KB
Loading

src/clj_commons/format/exceptions.clj

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,14 @@
116116
The default rules:
117117
118118
* omit everything in `clojure.lang`, `java.lang.reflect`
119-
* omit `clojure.core/with-bindings*` and `clojure.core/apply`
119+
* hide `clojure.core/with-bindings*` and `clojure.core/apply`, `clojure.lang.RestFn`
120120
* hide everything in `sun.reflect`
121121
* omit a number of functions in `clojure.test`
122122
* terminate at `speclj.*`, `clojure.main/.*`, or `nrepl.middleware.interruptible-eval`
123123
"
124124
[[:name "clojure.core/apply" :hide]
125125
[:id #"\Qclojure.lang.AFn.applyTo\E(Helper)?.*" :hide]
126+
[:id #"\Qclojure.lang.RestFn.\E.*" :hide]
126127
[:package "clojure.lang" :omit]
127128
[:name "clojure.core/with-bindings*" :hide]
128129
[:package #"sun\.reflect.*" :hide]
@@ -382,7 +383,6 @@
382383
dec)]
383384
(assoc frame
384385
:name-width width
385-
:line (str line)
386386
:name [(get *fonts* (clj-frame-font-key frame))
387387
(->> names' drop-last (str/join "/"))
388388
"/"
@@ -401,7 +401,7 @@
401401
402402
Formatting is based on whether the frame is omitted, and whether it is a Clojure or Java frame."
403403
{:added "0.3.0"}
404-
[{:keys [file line names repeats] :as frame}]
404+
[{:keys [line names] :as frame}]
405405
(cond
406406
(:omitted frame)
407407
(assoc frame
@@ -415,8 +415,7 @@
415415
(let [full-name (str (:class frame) "." (:method frame))]
416416
(assoc frame
417417
:name [(:java-frame *fonts*) full-name]
418-
:name-width (length full-name)
419-
:line (str line)))
418+
:name-width (length full-name)))
420419

421420
:else
422421
(format-clojure-frame-base frame)))
@@ -536,29 +535,35 @@
536535
max-name-width (max-from rows :name-width)
537536
;; Allow for the colon in frames w/ a line number (this assumes there's at least one)
538537
max-file-width (inc (max-from rows #(-> % :file length)))
539-
max-line-width (max-from rows #(-> % :line length))
538+
max-line-width (max-from rows #(-> % :line str length))
540539
*lines (volatile! (transient []))
541540
format-single-frame (fn [{:keys [name file line]} repeat-count frame-index frame-count]
542-
(list
543-
[{:width max-name-width} name]
544-
" "
545-
[{:width max-file-width
546-
:font source-font} file]
547-
(when line ":")
548-
" "
549-
[{:width max-line-width} line]
550-
(when (> repeat-count 1)
551-
(cond
552-
(= frame-index 0)
553-
(format " %s (repeats %,d times)"
554-
(if (= 1 frame-count) "" "")
555-
repeat-count)
556-
557-
(= frame-index (dec frame-count))
558-
""
559-
560-
:else
561-
""))))]
541+
(let [has-repeat? (> repeat-count 1)
542+
show-line? (or line has-repeat?)
543+
show-file? (or show-line? file)]
544+
(list
545+
[{:width max-name-width} name]
546+
(when show-file?
547+
(list
548+
" "
549+
[{:width max-file-width
550+
:font source-font} file]
551+
(when show-line?
552+
(list
553+
(if line ":" " ")
554+
[{:width max-line-width} line]
555+
(when (> repeat-count 1)
556+
(cond
557+
(= frame-index 0)
558+
(format " %s (repeats %,d times)"
559+
(if (= 1 frame-count) "" "")
560+
repeat-count)
561+
562+
(= frame-index (dec frame-count))
563+
""
564+
565+
:else
566+
"")))))))))]
562567
(doseq [[repeat-count frames] (repetitions :id rows)
563568
[frame-index frame] (map-indexed vector frames)]
564569
(vswap! *lines

test/clj_commons/exception_test.clj

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,6 @@
6969
"tcp-client"]
7070
:package "riemann"
7171
:simple-class "client$tcp_client"}
72-
{:class "clojure.lang.RestFn"
73-
:file "RestFn.java"
74-
:id "clojure.lang.RestFn.invoke:408"
75-
:is-clojure? false
76-
:line 408
77-
:method "invoke"
78-
:name ""
79-
:names []
80-
:omitted true
81-
:package "clojure.lang"
82-
:simple-class "RestFn"}
8372
{:class "com.example.error_monitor$make_connection"
8473
:file "error_monitor.clj"
8574
:id "com.example.error-monitor/make-connection:22"
@@ -214,17 +203,6 @@
214203
"-main"]
215204
:package "com.example.error_monitor"
216205
:simple-class "main$_main"}
217-
{:class "clojure.lang.RestFn"
218-
:file "RestFn.java"
219-
:id "clojure.lang.RestFn.applyTo:137"
220-
:is-clojure? false
221-
:line 137
222-
:method "applyTo"
223-
:name ""
224-
:names []
225-
:omitted true
226-
:package "clojure.lang"
227-
:simple-class "RestFn"}
228206
{:class "com.example.error_monitor.main"
229207
:file ""
230208
:id "com.example.error_monitor.main.main:-1"

test/demo.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@
6565
(countdown (dec n))))
6666

6767
(defn nested-interloper
68-
[f arg]
69-
(f arg))
68+
[f & arg]
69+
(apply f arg))
7070

7171
(defn interloper
72-
[f arg]
73-
(nested-interloper f arg))
72+
[& args]
73+
(apply nested-interloper args))
7474

7575
(defn countdown-alt
7676
[n]

0 commit comments

Comments
 (0)