rewrite-clj 2022-01-06

So in relation to the problem I described a few days ago, I wrote a function which attempts to determine whether some zloc is in the key position of a map. But I think it only works for the first map entry

(defn map-key?
  [zloc]
  (and
   (zip/map? (zip/up zloc))
   (zip/leftmost? zloc)))
Anyone know how this could be written to match a key in any map entry?

Or maybe it’s better to just identify the containing maps and replace them as a whole?

@cddr how I approached this in rewrite-edn: I just treated every nth element as a key and every n+1th element as a value

@cddr if you need to, you might also want to consider accounting for any #_ that might be present. Example {:a #_ ignored-thing 1}

Oh fortunately I don’t think I’ll need to worry about that but thanks for the headsup

👍 1

was wondering if anybody could help here, when I do this

(z/sexpr (z/of-string "{:db.sql/connection #profile\n {:prod {:jdbc-url #env JDBC_URL}}}"))
I end up with
#:db.sql{:connection (read-string "#profile\n{:prod {:jdbc-url #env JDBC_URL}}")}
is there a way to roundtrip this properly?

@yogthos you can do this by (binding [*print-namespace-maps* false] ...) , forgive me the bolded font, it's supposed to be earmuffed.

hmm, I can't find where *print-namespace-maps* is defined though

in clojure.core :)

the printing behavior you saw comes from clojure, not from rewrite-clj

haha I thought it was a rewrite-clj thing

these are corners of Clojure I haven't explored yet 🙂

hmm no dice

(binding [*print-namespace-maps* false]
    (z/sexpr (z/of-string "{:db.sql/connection #profile\n {:prod {:jdbc-url #env JDBC_URL}}}")))

it's this bit that's causing trouble (read-string "#profile\n{:prod {:jdbc-url #env JDBC_URL}}")

oh what does it say?

yeah not sure why it ends up getting wrapped with read-string

I think this is because you cannot convert #profile ..." to an s-expression without letting rewrite-clj know how to resolve that reader tag

why do you need the s-expressions, perhaps there is a better alternative?

I just need to inject a piece of edn into a file, so yeah maybe I'm barking up a wrong tree here

I use a zipper to find the target location, and then do this

(defn edn-merge-value [value]
  (fn [node]
    (if-let [inside-map (z/down node)]
      (-> inside-map
          (z/rightmost)
          (zipper-insert-kw-pairs (z/down value)))
      (z/replace node (z/node (format-zloc value))))))

I don't see sexpr in there?

you can use str instead to get back the string instead

sexpr should really be used with caution

but using str on a node will give a map containing the zipper

you first need to do (z/node ...)

and also z/root ... if you're not at the root of the zipper

ah ok, this looks like what I'm looking for

(binding [*print-namespace-maps* false]
    (str (z/node (z/of-string "{:db.sql/connection #profile\n {:prod {:jdbc-url #env JDBC_URL}}}"))))

so (-> zloc z/root z/node str)

thank you!

probably the print-namespace-maps binding isnt' necessary here

as rewrite-clj won't change the node representation

yeah I think I can drop that now

now I'll have to go back and check all the places I'm using z/sexpr, I think in most cases I intended to do (-> value z/node str)