|
44 | 44 | :max-coll-size 5
|
45 | 45 | :max-nested-depth nil
|
46 | 46 | :display-analytics-hint nil
|
47 |
| - :analytics-size-cutoff 100000}) |
| 47 | + :analytics-size-cutoff 100000 |
| 48 | + :pretty-print false}) |
48 | 49 |
|
49 | 50 | (defn- reset-render-state [inspector]
|
50 | 51 | (-> inspector
|
51 | 52 | (assoc :counter 0, :index [], :indentation 0, :rendered [])
|
52 | 53 | (dissoc :chunk :start-idx :last-page)))
|
53 | 54 |
|
| 55 | +(defn- print-string |
| 56 | + "Print or pretty print the string `value`, depending on the view mode |
| 57 | + of the inspector." |
| 58 | + [{:keys [indentation pretty-print]} value] |
| 59 | + (if pretty-print |
| 60 | + (print/pprint-str value {:indentation (or indentation 0)}) |
| 61 | + (print/print-str value))) |
| 62 | + |
54 | 63 | (defn- array? [obj]
|
55 | 64 | (some-> (class obj) .isArray))
|
56 | 65 |
|
|
211 | 220 |
|
212 | 221 | (defn- validate-config [{:keys [page-size max-atom-length max-value-length
|
213 | 222 | max-coll-size max-nested-depth display-analytics-hint
|
214 |
| - analytics-size-cutoff] |
| 223 | + analytics-size-cutoff pretty-print] |
215 | 224 | :as config}]
|
216 | 225 | (when (some? page-size) (pre-ex (pos-int? page-size)))
|
217 | 226 | (when (some? max-atom-length) (pre-ex (pos-int? max-atom-length)))
|
|
220 | 229 | (when (some? max-nested-depth) (pre-ex (pos-int? max-nested-depth)))
|
221 | 230 | (when (some? display-analytics-hint) (pre-ex (= display-analytics-hint "true")))
|
222 | 231 | (when (some? analytics-size-cutoff) (pre-ex (pos-int? analytics-size-cutoff)))
|
| 232 | + (when (some? pretty-print) (pre-ex (contains? #{true false} pretty-print))) |
223 | 233 | (select-keys config (keys default-inspector-config)))
|
224 | 234 |
|
225 | 235 | (defn refresh
|
|
294 | 304 | (render-onto values)
|
295 | 305 | (render '(:newline))))
|
296 | 306 |
|
297 |
| -(defn- indent [inspector] |
298 |
| - (update inspector :indentation + 2)) |
| 307 | +(defn- indent |
| 308 | + "Increment the `:indentation` of `inspector` by `n` or 2." |
| 309 | + [inspector & [n]] |
| 310 | + (update inspector :indentation + (or n 2))) |
299 | 311 |
|
300 |
| -(defn- unindent [inspector] |
301 |
| - (update inspector :indentation - 2)) |
| 312 | +(defn- unindent |
| 313 | + "Decrement the `:indentation` of `inspector` by `n` or 2." |
| 314 | + [inspector & [n]] |
| 315 | + (indent inspector (- (or n 2)))) |
302 | 316 |
|
303 | 317 | (defn- padding [{:keys [indentation]}]
|
304 | 318 | (when (and (number? indentation) (pos? indentation))
|
|
325 | 339 | ([inspector value] (render-value inspector value nil))
|
326 | 340 | ([inspector value {:keys [value-role value-key display-value]}]
|
327 | 341 | (let [{:keys [counter]} inspector
|
328 |
| - display-value (or display-value (print/print-str value)) |
| 342 | + display-value (or display-value (print-string inspector value)) |
329 | 343 | expr (list :value display-value counter)]
|
330 | 344 | (-> inspector
|
331 | 345 | (update :index conj {:value value
|
|
340 | 354 | (render-value value value-opts)
|
341 | 355 | (render-ln)))
|
342 | 356 |
|
343 |
| -(defn render-labeled-value [inspector label value & [value-opts]] |
344 |
| - (-> inspector |
345 |
| - (render-indent (str label ": ")) |
346 |
| - (render-value value value-opts) |
347 |
| - (render-ln))) |
| 357 | +(defn render-labeled-value [{:keys [pretty-print] :as inspector} label value & [value-opts]] |
| 358 | + (let [formatted-label (str label ": ") |
| 359 | + indentation (if pretty-print (count formatted-label) 0)] |
| 360 | + (-> inspector |
| 361 | + (render-indent formatted-label) |
| 362 | + (indent indentation) |
| 363 | + (render-value value value-opts) |
| 364 | + (unindent indentation) |
| 365 | + (render-ln)))) |
348 | 366 |
|
349 | 367 | (defn- render-class-name [inspector obj]
|
350 | 368 | (render-labeled-value inspector "Class" (class obj)))
|
|
356 | 374 | (render-ln))
|
357 | 375 | inspector))
|
358 | 376 |
|
| 377 | +(defn- long-map-key? |
| 378 | + "Returns true of `s` is a long string, more than 20 character or |
| 379 | + containing newlines." |
| 380 | + [^String s] |
| 381 | + (or (.contains s "\n") (> (count s) 20))) |
| 382 | + |
| 383 | +(defn- render-map-separator |
| 384 | + "Render the map separator according to `rendered-key`. If |
| 385 | + `rendered-key` is long or contains newlines the key and value will |
| 386 | + be rendered on separate lines." |
| 387 | + [{:keys [pretty-print] :as inspector} long-key?] |
| 388 | + (if (and pretty-print long-key?) |
| 389 | + (-> (render-ln inspector) |
| 390 | + (render-indent "=") |
| 391 | + (render-ln)) |
| 392 | + (render inspector " = "))) |
| 393 | + |
| 394 | +(defn- render-map-value |
| 395 | + "Render a map value. If `mark-values?` is true, attach the keys to the |
| 396 | + values in the index." |
| 397 | + [{:keys [pretty-print] :as inspector} key val mark-values? rendered-key long-key?] |
| 398 | + (if pretty-print |
| 399 | + (let [indentation (if long-key? 0 (+ 3 (count rendered-key)))] |
| 400 | + (-> (indent inspector indentation) |
| 401 | + (render (if (zero? indentation) " " "")) |
| 402 | + (render-value val |
| 403 | + (when mark-values? |
| 404 | + {:value-role :map-value, :value-key key})) |
| 405 | + (unindent indentation) |
| 406 | + ((if (long-map-key? rendered-key) render-ln identity)))) |
| 407 | + (render-value inspector val |
| 408 | + (when mark-values? |
| 409 | + {:value-role :map-value, :value-key key})))) |
| 410 | + |
359 | 411 | (defn- render-map-values
|
360 | 412 | "Render associative key-value pairs. If `mark-values?` is true, attach the keys
|
361 | 413 | to the values in the index."
|
362 | 414 | [inspector mappable mark-values?]
|
363 | 415 | (reduce (fn [ins [key val]]
|
364 |
| - (-> ins |
365 |
| - (render-indent) |
366 |
| - (render-value key) |
367 |
| - (render " = ") |
368 |
| - (render-value val (when mark-values? |
369 |
| - {:value-role :map-value, :value-key key})) |
370 |
| - (render-ln))) |
| 416 | + (let [rendered-key (print-string ins key) |
| 417 | + long-key? (long-map-key? rendered-key)] |
| 418 | + (-> (render-indent ins) |
| 419 | + (render-value key {:display-value rendered-key}) |
| 420 | + (render-map-separator long-key?) |
| 421 | + (render-map-value key val mark-values? rendered-key long-key?) |
| 422 | + (render-ln)))) |
371 | 423 | inspector
|
372 | 424 | mappable))
|
373 | 425 |
|
|
426 | 478 | "Render an indexed chunk of values. Renders all values in `chunk`, so `chunk`
|
427 | 479 | must be finite. If `mark-values?` is true, attach the indices to the values in
|
428 | 480 | the index."
|
429 |
| - [inspector chunk idx-starts-from mark-values?] |
| 481 | + [{:keys [pretty-print] :as inspector} chunk idx-starts-from mark-values?] |
430 | 482 | (let [n (count chunk)
|
431 | 483 | last-idx (+ idx-starts-from n -1)
|
432 | 484 | last-idx-len (count (str last-idx))
|
433 | 485 | idx-fmt (str "%" last-idx-len "s")]
|
434 | 486 | (loop [ins inspector, chunk (seq chunk), idx idx-starts-from]
|
435 | 487 | (if chunk
|
436 |
| - (recur (-> ins |
437 |
| - (render-indent (format idx-fmt idx) ". ") |
438 |
| - (render-value (first chunk) |
439 |
| - (when mark-values? |
440 |
| - {:value-role :seq-item, :value-key idx})) |
441 |
| - (render-ln)) |
442 |
| - (next chunk) (inc idx)) |
| 488 | + (let [header (str (format idx-fmt idx) ". ") |
| 489 | + indentation (if pretty-print (count header) 0)] |
| 490 | + (recur (-> ins |
| 491 | + (render-indent header) |
| 492 | + (indent indentation) |
| 493 | + (render-value (first chunk) |
| 494 | + (when mark-values? |
| 495 | + {:value-role :seq-item, :value-key idx})) |
| 496 | + (unindent indentation) |
| 497 | + (render-ln)) |
| 498 | + (next chunk) (inc idx))) |
443 | 499 | ins))))
|
444 | 500 |
|
445 | 501 | (declare known-types)
|
|
656 | 712 |
|
657 | 713 | (defmethod inspect :string [inspector ^java.lang.String obj]
|
658 | 714 | (-> (render-class-name inspector obj)
|
659 |
| - (render "Value: " (print/print-str obj)) |
| 715 | + (render "Value: " (print-string inspector obj)) |
660 | 716 | (render-ln)
|
661 | 717 | (render-section-header "Print")
|
662 | 718 | (indent)
|
|
714 | 770 | (shorten-member-string (str obj) (.getDeclaringClass ^Method obj))
|
715 | 771 |
|
716 | 772 | (instance? Field obj)
|
717 |
| - (shorten-member-string (str obj) (.getDeclaringClass ^Field obj)) |
718 |
| - |
719 |
| - :else (print/print-str obj))] |
| 773 | + (shorten-member-string (str obj) (.getDeclaringClass ^Field obj)))] |
720 | 774 | (letfn [(render-fields [inspector section-name field-values]
|
721 | 775 | (if (seq field-values)
|
722 | 776 | (-> inspector
|
|
924 | 978 | (unindent)))))
|
925 | 979 |
|
926 | 980 | (defn inspect-render
|
927 |
| - ([{:keys [max-atom-length max-value-length max-coll-size max-nested-depth value] |
| 981 | + ([{:keys [max-atom-length max-value-length max-coll-size max-nested-depth value pretty-print] |
928 | 982 | :as inspector}]
|
929 | 983 | (binding [print/*max-atom-length* max-atom-length
|
930 | 984 | print/*max-total-length* max-value-length
|
931 | 985 | *print-length* max-coll-size
|
932 |
| - *print-level* max-nested-depth] |
| 986 | + *print-level* (cond-> max-nested-depth |
| 987 | + ;; In pretty mode a higher *print-level* |
| 988 | + ;; leads to better results, otherwise we |
| 989 | + ;; render a ton of # characters when |
| 990 | + ;; there is still enough screen estate |
| 991 | + ;; in most cases. |
| 992 | + (and pretty-print (number? max-nested-depth)) |
| 993 | + (* 2))] |
933 | 994 | (-> inspector
|
934 | 995 | (reset-render-state)
|
935 | 996 | (decide-if-paginated)
|
|
0 commit comments