Given some hiccup like structure I want to find all things with a tag and a "particular" path to get to the thing. I have a solution but I am not too keen its use of collected.
(require '[com.rpl.specter :as S])
(require '[com.rpl.specter.impl :as i])
(require '[com.rpl.specter.util-macros :as sum])
(defn tag?
[tag-name]
#(and (vector? %) (= tag-name (first %))))
;; Based on INDEXED-VALS
(S/defnav
INDEXED-HEADLINES
[]
(select* [this structure next-fn]
;; could be more efficient with a primitive mutable field
(let [ih (i/mutable-cell -1)
io (i/mutable-cell -1)]
(sum/doseqres S/NONE [e structure]
(let [cell (if ((tag? :headline) e) ih io)]
(i/update-cell! cell inc)
(next-fn [(i/get-cell cell) e])))))
;; TODO: update this like the select*. Outside of scope
(transform* [this structure next-fn]
(throw (ex-info "not implemented" {}))))
;; Based on code from
(def headline-path-walker
(S/recursive-path [] p
(S/if-path sequential?
[INDEXED-HEADLINES
(S/if-path [S/LAST (tag? :headline)]
(S/multi-path
[(S/collect-one S/FIRST)
S/LAST]
[(S/collect-one S/FIRST)
S/LAST
p])
[(S/collect-one S/FIRST) S/LAST p])])))
So evaluating
(let [s [:doc
[:ignore-this]
[:headline
[:title [:text [:text-normal "headline"]]]
[:section]
[:headline
[:title [:text [:text-normal "child"]]]
[:section]
[:headline
[:title [:text [:text-normal "grandchild"]]]
[:section]]
[:headline
[:title [:text [:text-normal "grandchild2"]]]
[:section]]]]
[:headline
[:title [:text [:text-normal "other headline"]]]
[:section]]]]
(S/select [headline-path-walker
(S/nthpath 1)]
s))
Results in
[[0 [:title [:text [:text-normal "headline"]]]]
[0 0 [:title [:text [:text-normal "child"]]]]
[0 0 0 [:title [:text [:text-normal "grandchild"]]]]
[0 0 1 [:title [:text [:text-normal "grandchild2"]]]]
[1 [:title [:text [:text-normal "other headline"]]]]]
One issue I have is that headline-path-walker results in stuff getting added to collected. I would prefer if it used collect internally but returned a collection of [[0 1 2 ...] [:headline ...]]. Is there any way to do this? I have played around with S/transformed but to no avail.