|
57 | 57 | (number? v) v
|
58 | 58 | :else "?"))
|
59 | 59 |
|
60 |
| -(defn seek-path-segment [coll val] |
| 60 | +(defn seek-path-segment [coll val & [seq'd-map?]] |
61 | 61 | (let [* (fn [[k v]]
|
62 | 62 | (cond
|
63 | 63 | ;; we need to know the paths for keywords, these are clickable
|
64 |
| - (identical? k val) |
| 64 | + (and seq'd-map? (identical? k val)) |
65 | 65 | (present-path-segment k)
|
66 | 66 |
|
67 | 67 | (identical? v val)
|
|
70 | 70 |
|
71 | 71 | (defn build-path-segment [parent-object object]
|
72 | 72 | (cond
|
73 |
| - (map? parent-object) (seek-path-segment (seq parent-object) object) |
74 |
| - (sequential? parent-object) (seek-path-segment (map-indexed (fn [i x] [i x]) parent-object) object))) |
| 73 | + (map? parent-object) (seek-path-segment (seq parent-object) object true) |
| 74 | + (sequential? parent-object) (seek-path-segment (map-indexed (fn [i x] [i x]) parent-object) object) |
| 75 | + (and (set? parent-object) |
| 76 | + (contains? parent-object object) |
| 77 | + (or (string? object) |
| 78 | + (keyword? object) |
| 79 | + (integer? object))) object ;; if set has the simple object, return the object instead. |
| 80 | + (and (set? parent-object) ;; in composite objects in sets, return the index in the set. |
| 81 | + (contains? parent-object object)) (seek-path-segment (map-indexed (fn [i x] [i x]) parent-object) object))) |
75 | 82 |
|
76 | 83 | ;; This function checks a unique situation of looping an immediate child element `obj` of a parent element `history`
|
77 | 84 | ;; say we have a general map {:a 2 :b {:gh 45} :c 4}
|
|
85 | 92 | ;; get the first item in the vector which is the path.
|
86 | 93 | (defn mapping?
|
87 | 94 | [history obj]
|
88 |
| - (let [obj-kw (when (and (vector? obj) |
89 |
| - (= (count obj) 2) |
90 |
| - ;; the map keys must always be one of these |
91 |
| - (or |
92 |
| - (-> obj first keyword?) |
93 |
| - (-> obj first string?) |
94 |
| - (-> obj first number?))) |
95 |
| - (first obj))] |
96 |
| - (when (and (map? history) obj-kw) |
97 |
| - (contains? history obj-kw)))) |
| 95 | + (let [first-kw (when (and (vector? obj) |
| 96 | + (map? history)) |
| 97 | + (nth obj 0 nil)) |
| 98 | + valid-kw? (and first-kw |
| 99 | + (or (keyword? first-kw) |
| 100 | + (string? first-kw) |
| 101 | + (number? first-kw)) |
| 102 | + ;; intentionally delaying realizing the whole vector |
| 103 | + (= (count obj) 2))] |
| 104 | + (when valid-kw? |
| 105 | + (contains? history first-kw)))) |
| 106 | + |
| 107 | +(defn ignore-path-in-fake-vector |
| 108 | + [history obj path] |
| 109 | + ;; if the current item we are looping at is an artificial vector (explained at `mapping` above), |
| 110 | + ;; don't append to the path |
| 111 | + (when (mapping? history obj) |
| 112 | + (or path []))) |
| 113 | + |
| 114 | +(defn find-path-in-fake-vector |
| 115 | + [history path] |
| 116 | + (let [second-last-history (get-second-last-object-from-current-history)] |
| 117 | + ;; if the previous item is an artificial vector, lets append to the path info but take the first item |
| 118 | + ;; in the artificial vector as the path. (Explained in `mapping` above) |
| 119 | + (when (mapping? second-last-history history) |
| 120 | + (conj (or path []) (nth history 0 nil))))) |
| 121 | + |
| 122 | +(defn find-path |
| 123 | + [history obj path] |
| 124 | + (let [path-segment (build-path-segment history obj)] |
| 125 | + (when (some? path-segment) |
| 126 | + (conj (or path []) path-segment)))) |
98 | 127 |
|
99 | 128 | (defn extend-path-info [path-info object]
|
100 | 129 | (let [parent-object (get-last-object-from-current-history)]
|
101 |
| - (cond |
102 |
| - ;; if the current item we are looping at is an artificial vector (explained at `mapping` above), |
103 |
| - ;; dont append to the path |
104 |
| - (and (map? parent-object) (mapping? parent-object object)) |
105 |
| - path-info |
106 |
| - ;; if the previous item is an artificial vector, lets append to the path info but take the first item |
107 |
| - ;; in the vector as the path. (Explained in `mapping` above) |
108 |
| - (and (map? (get-second-last-object-from-current-history)) |
109 |
| - (mapping? (get-second-last-object-from-current-history) parent-object)) |
110 |
| - (conj (or path-info []) (first parent-object)) |
111 |
| - ;; the current object is an item within the parent object |
112 |
| - (some? (build-path-segment parent-object object)) |
113 |
| - (conj (or path-info []) (build-path-segment parent-object object)) |
114 |
| - :else path-info))) |
| 130 | + (or (ignore-path-in-fake-vector parent-object object path-info) |
| 131 | + (find-path-in-fake-vector parent-object path-info) |
| 132 | + (find-path parent-object object path-info) |
| 133 | + path-info))) |
115 | 134 |
|
116 | 135 | (defn add-object-to-current-path-info! [object]
|
117 | 136 | (update-current-state! update :path-info extend-path-info object))
|
|
0 commit comments