Skip to content

Commit 638e029

Browse files
committed
a proof of concept for issue #56
1 parent a28a380 commit 638e029

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

src/lib/devtools/formatters/printing.cljs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[devtools.protocols :refer [ITemplate IGroup ISurrogate IFormat]]
66
[devtools.formatters.state :refer [push-object-to-current-history! *current-state* get-current-state
77
is-circular? get-managed-print-level set-managed-print-level
8+
add-object-to-current-path-info! get-current-path-info
89
update-current-state!]]
910
[devtools.formatters.helpers :refer [cljs-value? expandable? abbreviated? directly-printable? should-render?]]))
1011

@@ -88,12 +89,19 @@
8889

8990
:else group))
9091

91-
(defn post-process-printed-output [output-group obj markup-db circular?]
92+
(defn wrap-group-with-path-annotation [group path-info]
93+
(if (and (pref :render-path-annotations)
94+
(some? path-info))
95+
[(concat ["annotation" {"path" (into-array path-info)}] group)]
96+
group))
97+
98+
(defn post-process-printed-output [output-group obj markup-db circular? path-info]
9299
(-> output-group
93100
(detect-edge-case-and-patch-it obj markup-db) ; an ugly hack
94101
(wrap-group-in-reference-if-needed obj markup-db)
95102
(wrap-group-in-circular-warning-if-needed markup-db circular?)
96-
(wrap-group-in-meta-if-needed obj markup-db)))
103+
(wrap-group-in-meta-if-needed obj markup-db)
104+
(wrap-group-with-path-annotation path-info)))
97105

98106
; -- alternative printer ----------------------------------------------------------------------------------------------------
99107

@@ -111,12 +119,14 @@
111119

112120
(defn alt-printer-impl [obj writer opts]
113121
(binding [*current-state* (get-current-state)]
122+
(add-object-to-current-path-info! obj)
114123
(let [{:keys [markup-db]} opts
115124
circular? (is-circular? obj)
116-
inner-writer (make-template-writer (:markup-db opts))]
125+
inner-writer (make-template-writer (:markup-db opts))
126+
path-info (get-current-path-info)]
117127
(push-object-to-current-history! obj)
118128
(alt-printer-job obj inner-writer opts)
119-
(.merge writer (post-process-printed-output (.get-group inner-writer) obj markup-db circular?)))))
129+
(.merge writer (post-process-printed-output (.get-group inner-writer) obj markup-db circular? path-info)))))
120130

121131
; -- common code for managed printing ---------------------------------------------------------------------------------------
122132

src/lib/devtools/formatters/state.cljs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,39 @@
4343
(let [history (get-current-history)]
4444
(some #(identical? % object) history)))
4545

46+
(defn get-last-object-from-current-history []
47+
(first (get-current-history))) ; note the list is reversed
48+
49+
(defn present-path-segment [v]
50+
(cond
51+
(string? v) v
52+
(keyword? v) (str v)
53+
(number? v) v
54+
:else "?"))
55+
56+
(defn seek-path-segment [coll val]
57+
(let [* (fn [[k v]]
58+
(if (identical? v val)
59+
(present-path-segment k)))]
60+
(some * coll)))
61+
62+
(defn build-path-segment [parent-object object]
63+
(cond
64+
(map? parent-object) (seek-path-segment (seq parent-object) object)
65+
(sequential? parent-object) (seek-path-segment (map-indexed (fn [i x] [i x]) parent-object) object)))
66+
67+
(defn extend-path-info [path-info object]
68+
(let [parent-object (get-last-object-from-current-history)]
69+
(if-some [path-segment (build-path-segment parent-object object)]
70+
(conj (or path-info []) path-segment)
71+
path-info)))
72+
73+
(defn add-object-to-current-path-info! [object]
74+
(update-current-state! update :path-info extend-path-info object))
75+
76+
(defn get-current-path-info []
77+
(:path-info (get-current-state)))
78+
4679
(defn ^bool prevent-recursion? []
4780
(boolean (:prevent-recursion (get-current-state))))
4881

src/lib/devtools/formatters/templating.cljs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@
106106
(make-group "object" #js {"object" object
107107
"config" sub-state}))))
108108

109+
(defn make-annotation [data markups]
110+
(apply make-group "annotation" (clj->js data) markups))
111+
109112
; -- JSON ML support --------------------------------------------------------------------------------------------------------
110113

111114
; a renderer from hiccup-like data markup to json-ml
@@ -162,6 +165,9 @@
162165
"reference" (let [obj (first args)
163166
converted-obj (if (surrogate-markup? obj) (render-json-ml* obj) obj)]
164167
(apply make-reference (concat [converted-obj] (rest args))))
168+
"annotation" (let [data (first args)
169+
converted-args (map render-json-ml* (rest args))]
170+
(make-annotation data converted-args))
165171
(assert-markup-error (str "no matching special tag name: '" name "'"))))
166172

167173
(defn emptyish? [v]

test/src/tests/devtools/tests/format.cljs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,3 +1089,55 @@
10891089
[:float-infinity-tag "##-Inf"]
10901090
"]"]])
10911091
(has-body? wrapped-infs false))))
1092+
1093+
(deftest test-issue-56
1094+
(testing "render path annotations"
1095+
(with-prefs {:render-path-annotations true}
1096+
(let [m {:k1 {:k2 "val"}}]
1097+
(is-header m
1098+
[:cljs-land-tag
1099+
[:header-tag
1100+
"{"
1101+
[:keyword-tag ":k1"]
1102+
:spacer
1103+
["annotation"
1104+
{"path" #js [":k1"]}
1105+
"{"
1106+
["annotation"
1107+
{"path" #js [":k1"]}
1108+
[:keyword-tag ":k2"]]
1109+
:spacer
1110+
["annotation"
1111+
{"path" #js [":k1" ":k2"]}
1112+
[:string-tag "\"val\""]]
1113+
"}"]
1114+
"}"]]))
1115+
(let [m ['first ["val"]]]
1116+
(is-header m
1117+
[:cljs-land-tag
1118+
[:header-tag
1119+
"["
1120+
["annotation"
1121+
{"path" #js [0]}
1122+
[:symbol-tag "first"]]
1123+
:spacer
1124+
["annotation"
1125+
{"path" #js [1]}
1126+
"["
1127+
["annotation"
1128+
{"path" #js [1 0]}
1129+
[:string-tag "\"val\""]]
1130+
"]"]
1131+
"]"]]))
1132+
(let [m {{} "val"}]
1133+
(is-header m
1134+
[:cljs-land-tag
1135+
[:header-tag
1136+
"{"
1137+
"{"
1138+
"}"
1139+
:spacer
1140+
["annotation"
1141+
{"path" #js ["?"]}
1142+
[:string-tag "\"val\""]]
1143+
"}"]])))))

0 commit comments

Comments
 (0)