rewrite-clj

André Camargo 2025-02-27T16:42:57.151259Z

Hello friends, just a sanity check. This is wrong, right?

;;   12345678901
(-> "(get {}) :a"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 11}
I expected :end-col to be 12. 🤔

André Camargo 2025-02-27T16:48:12.959559Z

Testing other value types, :end-col matches with my expectations.

;;   123456789 0123 4
(-> "(get {}) \"foo\""
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 15}

;;   1234567890
(-> "(get []) 0"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 11}

;;   12345678901
(-> "(get []) 'a"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 12}

;;   12345678901
(-> "(get []) {}"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 12}

;;   12345678901
(-> "(get []) ()"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 12}

;;   1234567890123
(-> "(get []) #_{}"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 14}
Oh wait, there's an issue with namespaced keywords as well
;;   12345678901234
(-> "(get {}) ::b/c"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 14}
Yeah, the issue seems to be with keywords
;;   12345
(-> ":a :b"
    z/of-string
    z/root
    meta) ;; => {:row 1, :col 1, :end-row 1, :end-col 5}

lread 2025-02-27T17:13:54.315509Z

I'll read all this... fire up my REPL and explore with you...

lread 2025-02-27T17:35:37.354619Z

The metadata you are seeing is added by clojure tools reader. Perhaps it has a wee issue with the last element parsed. The :end-col is exclusive, except for the last element parsed, it seems:

;12345
(->> ":a :b"
     z/of-string
     (iterate z/next*)
     (take-while (complement z/end?))
     (mapv (fn [zloc] [ (-> zloc z/node meta) (z/string zloc)])))
;; => [[{:row 1, :col 1, :end-row 1, :end-col 3} ":a"]
;;     [{:row 1, :col 3, :end-row 1, :end-col 4} " "]
;;     [{:row 1, :col 4, :end-row 1, :end-col 5} ":b"]]
(note to reader: edited some typos below!) Seems to be fine for symbol:
;12345678
(->> ":a boo"
     z/of-string
     (iterate z/next*)
     (take-while (complement z/end?))
     (mapv (fn [zloc] [ (-> zloc z/node meta) (z/string zloc)])))
;; => [[{:row 1, :col 1, :end-row 1, :end-col 3} ":a"]
;;     [{:row 1, :col 3, :end-row 1, :end-col 4} " "]
;;     [{:row 1, :col 4, :end-row 1, :end-col 7} "boo"]]
What about a position tracking zipper? How does it do on the last elem?
;123456
(->> (z/of-string* ":a :b" {:track-position? true}) 
     (iterate z/next*)
     (take-while (complement z/end?))
     (mapv (fn [zloc] [ (z/position-span zloc) (z/string zloc)])))
;; => [[[[1 1] [1 6]] ":a :b"]
;;     [[[1 1] [1 3]] ":a"]
;;     [[[1 3] [1 4]] " "]
;;     [[[1 4] [1 6]] ":b"]]
It seems OK. So @andreribeirocamargo, is this rewrite-clj quirk causing you problems?

lread 2025-02-27T17:39:41.364809Z

Oh. Lemme try some of your other examples... please hold...

lread 2025-02-27T17:43:05.722059Z

Right... so only a problem for certain constructs. Like you showed, this works fine:

;1234567890
(->> "(get []) 0"
     z/of-string
     (iterate z/next*)
     (take-while (complement z/end?))
     (mapv (fn [zloc] [ (-> zloc z/node meta) (z/string zloc)])))
;; => [[{:row 1, :col 1, :end-row 1, :end-col 9} "(get [])"]
;;     [{:row 1, :col 2, :end-row 1, :end-col 5} "get"]
;;     [{:row 1, :col 5, :end-row 1, :end-col 6} " "]
;;     [{:row 1, :col 6, :end-row 1, :end-col 8} "[]"]
;;     [{:row 1, :col 9, :end-row 1, :end-col 10} " "]
;;     [{:row 1, :col 10, :end-row 1, :end-col 11} "0"]]
And in position tracking zipper, fine too:
(->> (z/of-string "(get []) 0" {:track-position? true})
     (iterate z/next*)
     (take-while (complement z/end?))
     (mapv (fn [zloc] [ (z/position-span zloc) (z/string zloc)])))
;; => [[[[1 1] [1 9]] "(get [])"]
;;     [[[1 2] [1 5]] "get"]
;;     [[[1 5] [1 6]] " "]
;;     [[[1 6] [1 8]] "[]"]
;;     [[[1 9] [1 10]] " "]
;;     [[[1 10] [1 11]] "0"]]

lread 2025-02-27T17:48:58.410969Z

I'm guessing rewrite-clj is picking up a behaviour from clojure tools.reader, but would have to verify.

lread 2025-02-27T18:26:19.437309Z

Hmm... I think the issue is in rewrite-clj. I'll raise an issue.

lread 2025-02-27T18:50:24.272679Z

(I had a number of typos in my response and edited to fix)

lread 2025-02-27T18:59:16.597969Z

https://github.com/clj-commons/rewrite-clj/issues/367

👏 1