rewrite-clj

https://github.com/clj-commons/rewrite-clj
vemv 2020-12-21T16:52:11.255500Z

The lread-ns-kw-map branch lgtm (for the superficial judgement I can make) I noticed that the following forms don't have test coverage (?):

^::foo
^::foo/bar
^{::foo ...}
^{::foo/bar ...}
...although they appear to just work :) --- I constructed those with base/of-string but I'm not entirely sure of how one would build them with rewrite-cljc.node.meta which I think would be a more frequent use case for me. e.g., let's say I want to replace x with ^::foo x, how would that be done? The doc might be scarce yet on that front (note that ^::foo x is textually different from ^{::foo true} x, even if functionally equivalent. One should be able to specify one or the other resulting format)

lread 2020-12-21T17:50:48.258100Z

Very interesting @vemv thanks for sharing! This will definitely result in improvements, at the very least to the docs! Let’s start with: > let’s say I want to replace `x` with `^::foo x`, how would that be done? The doc might be scarce yet on that front Here is one way:

(require '[rewrite-cljc.zip :as z]
         '[rewrite-cljc.node :as n])

(let [zloc (z/of-string  "x")]
  (-> zloc
      (z/replace (n/meta-node [(n/keyword-node :foo true)
                               (n/whitespace-node " ")
                               (z/node zloc)]))
      z/root-string))
;; => "^::foo x"

lread 2020-12-21T18:15:47.259900Z

As for: > (note that `^::foo x` is textually different from `^{::foo true} x`, even if functionally equivalent. One should be able to specify one or the other resulting format) Here’s one way to create the nodes from the node API:

(require '[rewrite-cljc.node :as n])

(def n1 (n/meta-node (n/keyword-node :foo true) (n/token-node 'x)))
(n/string n1)
;; => "^::foo x"

(def n2 (n/meta-node (n/map-node [(n/keyword-node :foo true)
                                  (n/whitespace-node " ")
                                  (n/token-node 'true)])
                     (n/token-node 'x)))
(n/string n2)
;; => "^{::foo true} x"

(meta (n/sexpr n1))
;; => #:user{:foo true}
(meta (n/sexpr n2))
;; => #:user{:foo true}
(= (meta (n/sexpr n1)) (meta (n/sexpr n2)))
;; => true

vemv 2020-12-21T18:28:35.260800Z

Fantastic, thank you! Tried out. I'd be happy if these were added to the test suite as I'm writing a program that would depend on this feature

lread 2020-12-21T18:45:22.264300Z

Great stuff! Yeah, I think that adding some tests makes good sense. The above examples, or something similar, would be good to add to the introduction document. The node creation fn docstrings could use some love/examples too. I certainly found them mysterious when first looking at them.

vemv 2020-12-21T19:35:58.264400Z

> The node creation fn docstrings could use some love/examples too. I certainly found them mysterious when first looking at them. yeah this was my impression when using xsc/rewrite-clj - I wasn't all sure if rewrite-clj.node.meta was a ns supposed to be used. especially when there was a ^:no-doc :)

lread 2020-12-21T19:40:02.264700Z

That maybe more import-vars confusion… the node creation functions are exposed via the rewrite-clj.node namespace.

🙂 1
lread 2020-12-21T19:42:42.264900Z

I was thinking of maybe adjusting the tests to hit the public APIs rather than internal namespaces. That might help folks who refer to tests for usage, to hit the public APIs.

👍 1