rewrite-clj

wilkerlucio 2024-08-09T20:16:05.503509Z

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?

borkdude 2024-08-09T20:19:58.131609Z

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

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

borkdude 2024-08-09T20:20:21.480809Z

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

wilkerlucio 2024-08-09T20:21:18.104959Z

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)

borkdude 2024-08-09T20:21:58.986869Z

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

borkdude 2024-08-09T20:22:37.975219Z

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

wilkerlucio 2024-08-09T20:22:39.683409Z

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

wilkerlucio 2024-08-09T20:22:58.171729Z

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

wilkerlucio 2024-08-09T20:23:44.343649Z

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

borkdude 2024-08-09T20:25:35.414289Z

I think there's no other way

borkdude 2024-08-09T20:28:05.291879Z

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

👀 1
borkdude 2024-08-09T20:28:11.414839Z

and then feed that to of-node

borkdude 2024-08-09T20:29:04.261929Z

$ 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}]

borkdude 2024-08-09T20:29:53.606719Z

$ 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

wilkerlucio 2024-08-09T20:30:16.734979Z

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

🤝 1
wilkerlucio 2024-08-09T20:33:44.414359Z

thank you very much @borkdude!

borkdude 2024-08-09T20:34:27.780109Z

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

lread 2024-08-10T13:42:25.199169Z

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

💯 1