rewrite-clj 2024-08-09

hi folks, I'm attempting to use rewrite-clj as part of a macro to rewrite some code, how do I properly start a zipper from a sexp? I tried z/of-node, it starts, but seems like its having problems to navigate, example:

(-> (z/of-node [1 2 3])
    (z/down)
    (z/node))
=> Execution error (NullPointerException) at rewrite-clj.custom-zipper.core/node (core.cljc:55).
Cannot invoke "clojure.lang.IFn.invoke(Object)" because "loc" is null
I would expect the output 1 from that (like it would be with a vector-zip) seems like its missing the line position (which really doesn't exist in this case), is there a way to use without caring for whitespaces?

@wilkerlucio a node in rewrite-clj speak is something like this:

(rewrite-clj.parser/parse-string "1")

$ bb -e '(rewrite-clj.parser/parse-string "1")'
<token: 1>

is there a way to get something I can work with from a sexp? because in my macro case I really dont care about whitespaces, but I want all the nice navigation/paredit helpers that rewrite-clj has to help me make this macro (its a quite complicated transformation process, and zippers can really help me here)

why don't you just use a normal clojure core zipper then? rewrite-clj is intended to be used with code parsed from strings, so that it can preserve the whitespace stuff

I guess you could first stringify your input and then create a zipper from that, if you must

is there a clojure primitive that can walk generic sexp? I dont know of it, but also for the paredit extras that rewrite-clj has

I'm trying to avoid the stringification path if possible (because that's extra overhead)

just feels like so close, and needing just less features 😛

I think there's no other way

hmm, maybe there is one other way. use (rewrite-clj.node/coerce expr)

👀 1

and then feed that to of-node

$ bb -e "(rewrite-clj.zip/of-node (rewrite-clj.node/coerce '(+ 1 2 3)))"
[<list: (+ 1 2 3)> {:l [], :pnodes [<forms: (+ 1 2 3)>], :ppath nil, :r nil}]

$ bb -e "(require '[rewrite-clj.zip :as z]) (-> (z/of-node (rewrite-clj.node/coerce '(+ 1 2 3))) z/down z/right z/sexpr)"
1

did some preliminary testing, seems like that does the job 😄

🤝 1

thank you very much @borkdude!

no problem. I kinda forgot about coerce, but I've been using that in clj-kondo a bunch :)

Oh, that's a good one, I should add it to the user guide!

💯 1