Open lread opened 5 months ago
I vote for the proposed solution. rewrite-clj seems overly protective in this area and prevents otherwise valid use cases. I understand why it was overprotective, but in hindsight it seems like this check could be removed to open up the unforeseen use cases.
I still prefer our proposed solution but for completeness, another alternative is to do nothing but document how to satisfy this use case using node metadata on a non-position-tracking-zipper. Example I shared on Slack:
(require '[rewrite-clj.node :as n]
'[rewrite-clj.zip :as z])
(def s (str "(some code here
that I want
to change)"))
;; some locations found by an external tool
(def locs [[1 7] ;; code
[2 1] ;; that
[2 6] ;; I
[3 4] ;; change
])
;; one way to write a find-by-pos for a non-tracking zipper
(defn find-by-pos [zloc [frow fcol]]
(z/find zloc z/next (fn [zloc]
(let [{:keys [row col]} (meta (z/node zloc))]
(and (= frow row)
(= fcol col))))))
(def zloc (z/of-string s))
;; for demo purposes make each item at loc a fn call with loc as as args
(z/print-root (reduce (fn [zloc loc]
(let [zloc (find-by-pos zloc loc)]
(z/replace zloc (n/list-node [(z/node zloc)
(n/spaces 1)
(first loc)
(n/spaces 1)
(second loc)]))))
zloc
locs))
Outputs:
(some (code 1 7) here
(that 2 1) (I 2 6) want
to (change 3 4))
Problem/Opportunity
Currently
rewrite-clj.zip/find-last-by-pos
requires a position tracking zipper. The position tracking zipper tracks and updates positions as the zipper is changed.A use case came on Slack today where someone wanted to use
find-last-by-pos
but with a list of locations found by an external tool. The flow is:This won't work on a position-tracking zipper. When the zipper is changed, it will update the row/col positions, and therefore, only the first
ex-poses
will be found.And it won't work on a non-position because rewrite-clj throws if you attempt to use a
find-last-by-pos
on a non-position tracking zipper.Proposed Solution
Allow
find-last-by-pos
to work on a non-position tracking zipper to support the use above use case.Alternative Solutions
Additional context
find-last-by-pos
and updated accordingly.pos
fns on a non-position-tracking zipper vs a position-tracking zipper. Docstrings will need to be updated. Explicit examples in the user guide will also be helpful.Action
I can follow up by looking into this and, eventually, write up a PR.