Skip to content

Commit 60ae109

Browse files
[inspect] Add :table view-mode
1 parent 7df1ada commit 60ae109

File tree

2 files changed

+170
-3
lines changed

2 files changed

+170
-3
lines changed

src/orchard/inspect.clj

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
[orchard.print :as print])
1515
(:import
1616
(java.lang.reflect Constructor Field Method Modifier)
17-
(java.util List Map)))
17+
(java.util Arrays List Map)))
1818

1919
;;
2020
;; Navigating Inspector State
@@ -33,7 +33,7 @@
3333
(list 'get key)))
3434
(conj path '<unknown>)))
3535

36-
(def ^:private supported-view-modes #{:normal :object})
36+
(def ^:private supported-view-modes #{:normal :object :table})
3737

3838
(def ^:private default-inspector-config
3939
"Default configuration values for the inspector."
@@ -351,6 +351,60 @@
351351
inspector
352352
mappable))
353353

354+
(defn supports-table-view-mode?
355+
"Return whether the inspected object can be rendered in :table view-mode."
356+
[{:keys [chunk value] :as inspector}]
357+
(let [val (or chunk value)]
358+
(and (#{:list :array} (object-type val))
359+
(#{:list :array :map} (object-type (first val))))))
360+
361+
(defn- render-chunk-as-table [inspector chunk idx-starts-from mark-values?]
362+
(let [m-i map-indexed
363+
fst (first chunk)
364+
;; If items are maps, use map keys as keys. Otherwise assume items are
365+
;; lists/vectors, so we use indices as keys.
366+
getter (if (map? fst) get nth)
367+
ks (vec (if (map? fst)
368+
(keys fst)
369+
(range (count fst))))
370+
pr-rows (into []
371+
(m-i (fn [i row]
372+
(let [i (+ i idx-starts-from)]
373+
(into [[i (str i)]]
374+
(m-i (fn [j k]
375+
(let [v (getter row k)]
376+
[v (print/print-str v)])))
377+
ks))))
378+
chunk)
379+
pr-ks (into [["#" "#"]] (map (fn [k] [k (print/print-str k)])) ks)
380+
381+
widths (m-i (fn [i [_ pr-k]]
382+
(apply max (count pr-k)
383+
(map #(count (second (nth % i))) pr-rows)))
384+
pr-ks)
385+
pad #(String. (doto (char-array %1) (Arrays/fill ^char %2)))
386+
spacers (mapv #(fn [c] (pad (- % c) \space)) widths)
387+
divider (format "|-%s-|" (str/join "-+-" (map #(pad % \-) widths)))
388+
389+
render-row #(as-> %1 ins
390+
(render-indent ins "| ")
391+
(reduce-kv (fn [ins i [val pr-val]]
392+
(-> ins
393+
(render ((nth spacers i) (count pr-val)))
394+
(render-value val {:display-value pr-val
395+
;; :value-role :seq-item
396+
;; :value-key 0
397+
})
398+
(render " | ")))
399+
ins %2)
400+
(render-ln ins))]
401+
(as-> inspector ins
402+
(render-ln ins)
403+
(render-row ins pr-ks)
404+
(render-indent ins)
405+
(render-ln ins divider)
406+
(reduce render-row ins pr-rows))))
407+
354408
(defn- render-indexed-chunk
355409
"Render an indexed chunk of values. Renders all values in `chunk`, so `chunk`
356410
must be finite. If `mark-values?` is true, attach the indices to the values in
@@ -389,7 +443,9 @@
389443
(defn- render-items [inspector items map? start-idx mark-values?]
390444
(if map?
391445
(render-map-values inspector items mark-values?)
392-
(render-indexed-chunk inspector items start-idx mark-values?)))
446+
(if (and (= (:view-mode inspector) :table) (supports-table-view-mode? inspector))
447+
(render-chunk-as-table inspector items start-idx mark-values?)
448+
(render-indexed-chunk inspector items start-idx mark-values?))))
393449

394450
(defn- render-value-maybe-expand
395451
"If `obj` is a collection smaller than page-size, then render it as a

test/orchard/inspect_test.clj

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,117 @@
14501450
" " [:value "_hash" pos?] " = " [:value "0" pos?] [:newline]])
14511451
(section "Instance fields" rendered)))))
14521452

1453+
(deftest table-view-mode-test
1454+
(testing "in :table view-mode lists of maps are rendered as tables"
1455+
(let [rendered (-> (for [i (range 5)]
1456+
{:a (- i)
1457+
:bb (str i i i)
1458+
:ccc (range i 0 -1)})
1459+
(inspect/start)
1460+
(inspect/set-view-mode :table)
1461+
render)]
1462+
(is+ ["--- Contents:" [:newline] [:newline]
1463+
" | " [:value "#" pos?] " | " [:value ":a" pos?] " | "
1464+
[:value ":bb" pos?] " | " [:value ":ccc" pos?] " | " [:newline]
1465+
" |---+----+-------+-----------|" [:newline]
1466+
" | " [:value "0" pos?] " | " [:value "0" pos?] " | "
1467+
[:value "\"000\"" pos?] " | " [:value "()" pos?] " | " [:newline]
1468+
" | " [:value "1" pos?] " | " [:value "-1" pos?] " | "
1469+
[:value "\"111\"" pos?] " | " [:value "(1)" pos?] " | " [:newline]
1470+
" | " [:value "2" pos?] " | " [:value "-2" pos?] " | "
1471+
[:value "\"222\"" pos?] " | " [:value "(2 1)" pos?] " | " [:newline]
1472+
" | " [:value "3" pos?] " | " [:value "-3" pos?] " | "
1473+
[:value "\"333\"" pos?] " | " [:value "(3 2 1)" pos?] " | " [:newline]
1474+
" | " [:value "4" pos?] " | " [:value "-4" pos?] " | "
1475+
[:value "\"444\"" pos?] " | " [:value "(4 3 2 1)" pos?] " | " [:newline]
1476+
[:newline]]
1477+
(section "Contents" rendered))
1478+
(is+ ["--- View mode:" [:newline] " :table"]
1479+
(section "View mode" rendered))))
1480+
1481+
(testing "in :table view-mode lists of vectors are rendered as tables"
1482+
(let [rendered (-> (for [i (range 5)]
1483+
[(- i) (str i i i) (range i 0 -1)])
1484+
(inspect/start)
1485+
(inspect/set-view-mode :table)
1486+
render)]
1487+
(is+ ["--- Contents:" [:newline] [:newline]
1488+
" | " [:value "#" pos?] " | " [:value "0" pos?] " | "
1489+
[:value "1" pos?] " | " [:value "2" pos?] " | " [:newline]
1490+
" |---+----+-------+-----------|" [:newline]
1491+
" | " [:value "0" pos?] " | " [:value "0" pos?] " | "
1492+
[:value "\"000\"" pos?] " | " [:value "()" pos?] " | " [:newline]
1493+
" | " [:value "1" pos?] " | " [:value "-1" pos?] " | "
1494+
[:value "\"111\"" pos?] " | " [:value "(1)" pos?] " | " [:newline]
1495+
" | " [:value "2" pos?] " | " [:value "-2" pos?] " | "
1496+
[:value "\"222\"" pos?] " | " [:value "(2 1)" pos?] " | " [:newline]
1497+
" | " [:value "3" pos?] " | " [:value "-3" pos?] " | "
1498+
[:value "\"333\"" pos?] " | " [:value "(3 2 1)" pos?] " | " [:newline]
1499+
" | " [:value "4" pos?] " | " [:value "-4" pos?] " | "
1500+
[:value "\"444\"" pos?] " | " [:value "(4 3 2 1)" pos?] " | " [:newline]
1501+
[:newline]]
1502+
(section "Contents" rendered))
1503+
(is+ ["--- View mode:" [:newline] " :table"]
1504+
(section "View mode" rendered))))
1505+
1506+
(testing "doesn't break if table mode is requested for unsupported value"
1507+
(let [rendered (-> {:a 1}
1508+
(inspect/start)
1509+
(inspect/set-view-mode :table)
1510+
render)]
1511+
(is+ ["--- Contents:" [:newline]
1512+
" " [:value ":a" pos?] " = " [:value "1" pos?] [:newline]
1513+
[:newline]]
1514+
(section "Contents" rendered))))
1515+
1516+
(testing "works with paging"
1517+
(let [rendered (-> (map #(vector % %) (range 9))
1518+
(inspect/start)
1519+
(set-page-size 3)
1520+
(inspect/set-view-mode :table)
1521+
render)]
1522+
(is+ ["--- Contents:" [:newline] [:newline]
1523+
" | " [:value "#" pos?] " | " [:value "0" pos?] " | " [:value "1" pos?] " | " [:newline]
1524+
" |---+---+---|" [:newline]
1525+
" | " [:value "0" pos?] " | " [:value "0" pos?] " | " [:value "0" pos?] " | " [:newline]
1526+
" | " [:value "1" pos?] " | " [:value "1" pos?] " | " [:value "1" pos?] " | " [:newline]
1527+
" | " [:value "2" pos?] " | " [:value "2" pos?] " | " [:value "2" pos?] " | " [:newline]
1528+
" ..." [:newline] [:newline]]
1529+
(section "Contents" rendered)))
1530+
1531+
(let [rendered (-> (map #(vector % %) (range 9))
1532+
(inspect/start)
1533+
(set-page-size 3)
1534+
(inspect/next-page)
1535+
(inspect/set-view-mode :table)
1536+
render)]
1537+
(is+ ["--- Contents:" [:newline]
1538+
" ..." [:newline] [:newline]
1539+
" | " [:value "#" pos?] " | " [:value "0" pos?] " | " [:value "1" pos?] " | " [:newline]
1540+
" |---+---+---|" [:newline]
1541+
" | " [:value "3" pos?] " | " [:value "3" pos?] " | " [:value "3" pos?] " | " [:newline]
1542+
" | " [:value "4" pos?] " | " [:value "4" pos?] " | " [:value "4" pos?] " | " [:newline]
1543+
" | " [:value "5" pos?] " | " [:value "5" pos?] " | " [:value "5" pos?] " | " [:newline]
1544+
" ..." [:newline] [:newline]]
1545+
(section "Contents" rendered)))
1546+
1547+
(let [rendered (-> (map #(vector % %) (range 9))
1548+
(inspect/start)
1549+
(set-page-size 3)
1550+
(inspect/next-page)
1551+
(inspect/next-page)
1552+
(inspect/set-view-mode :table)
1553+
render)]
1554+
(is+ ["--- Contents:" [:newline]
1555+
" ..." [:newline] [:newline]
1556+
" | " [:value "#" pos?] " | " [:value "0" pos?] " | " [:value "1" pos?] " | " [:newline]
1557+
" |---+---+---|" [:newline]
1558+
" | " [:value "6" pos?] " | " [:value "6" pos?] " | " [:value "6" pos?] " | " [:newline]
1559+
" | " [:value "7" pos?] " | " [:value "7" pos?] " | " [:value "7" pos?] " | " [:newline]
1560+
" | " [:value "8" pos?] " | " [:value "8" pos?] " | " [:value "8" pos?] " | " [:newline]
1561+
[:newline]]
1562+
(section "Contents" rendered)))))
1563+
14531564
(deftest tap-test
14541565
(testing "tap-current-value"
14551566
(let [proof (atom [])

0 commit comments

Comments
 (0)