rewrite-clj 2025-04-08

i have a string "\n(ns foo)\n(+ 1 2 3\n 4 5 6)\n\n\n" which replaces an existing node. when i print the root node, it prints with the \n instead of actual line breaks. this is probably not due to rewrite-clj but i'm not sure how to make the linebreaks "real" linebreaks in a string literal.

✅ 1

Lemme fire up my REPL... please hold.

Ok. Hopefully I've understood your goal. Here's one way to achieve it:

(require '[rewrite-clj.parser :as p]
         '[rewrite-clj.zip :as z])

(-> "[:a :b :c]"
    z/of-string
    z/down
    z/right ;; navigate to :b
    (z/replace (p/parse-string-all "\n(ns foo)\n(+ 1 2 3\n   4 5 6)\n\n\n"))
    z/root-string)
;; => "[:a \n(ns foo)\n(+ 1 2 3\n   4 5 6)\n\n\n :c]"
Does that concept work for you?

(def example
  "
(ns foo)
(+ 1 2 3
   4 5 6)
")

(compare-output
 (println example)
 
(ns foo)
(+ 1 2 3
   4 5 6)

)

idk why my editor indented all those lines lol

soryr, that's incomprehensible

1

Oh... are you trying to replace with a string node?

i have

(def example
  "
(ns foo)
(+ 1 2 3
   4 5 6)
")

(compare-output
 (println example)
 "hello\n")
and i would like to replace "hello\n" with the output of (println example). i have the macro set up to read the file, find the position by the metadata of the compare-output call, and replace the "hello\n" node with the output

i'd like to replace it with a string node that treats each newline as an visual newline

if i could wrap the output of parse-string-all with quotes, then this would be ideal

Oh. Like you mean like this?

(require '[rewrite-clj.node :as n]
         '[rewrite-clj.parser :as p]
         '[rewrite-clj.zip :as z])

(-> "[:a :b :c]"
    z/of-string
    z/down
    z/right ;; navigate to :b
    (z/replace (n/string-node "\n(ns foo)\n(+ 1 2 3\n   4 5 6)\n\n\n"))
    z/print-root)
Which outputs:
[:a "
(ns foo)
(+ 1 2 3
   4 5 6)


" :c]
Is that what you'd like?

oh, lol. i thought i tried this and it didn't work

but it does. thank you for your help

n/coerce would probably also have worked (amounting in a call to string-node)

I vaguely remember nuances around multi-line strings and coercion... but memory is foggy.

oh, i just used the string directly, i ddin't actually call node/string-node

Yeah, I think you need the node/string-node for your use case.

hmm yeah, there is some difference:

user=> (println (str (n/coerce "foo
bar")))
"foo\nbar"
nil
user=> (println (str (n/string-node "foo
bar")
)
)
"foo
bar"
nil

Yeah, rewrite-clj.zip/replace automatically coerced that string, but not in a way that Noah wanted.