rewrite-clj

2025-04-08T17:16:11.870149Z

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
lread 2025-04-08T17:18:10.422369Z

Lemme fire up my REPL... please hold.

2025-04-08T17:18:52.050289Z

lol no rush!

1
lread 2025-04-08T17:23:35.998699Z

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?

2025-04-08T17:26:54.939859Z

hmm

2025-04-08T17:26:57.573319Z

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

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

)

2025-04-08T17:27:07.130129Z

idk why my editor indented all those lines lol

2025-04-08T17:28:23.175729Z

soryr, that's incomprehensible

1
lread 2025-04-08T17:29:15.903749Z

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

lread 2025-04-08T17:29:24.623159Z

I'm confused.

2025-04-08T17:29:49.137029Z

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

2025-04-08T17:30:42.697159Z

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

2025-04-08T17:32:21.050309Z

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

lread 2025-04-08T17:36:27.009859Z

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?

2025-04-08T17:36:57.463689Z

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

2025-04-08T17:37:11.090989Z

but it does. thank you for your help

borkdude 2025-04-08T17:37:47.207719Z

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

lread 2025-04-08T17:45:13.757719Z

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

2025-04-08T17:46:48.679269Z

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

lread 2025-04-08T17:47:45.726599Z

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

borkdude 2025-04-08T17:48:45.603459Z

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

lread 2025-04-08T18:31:29.571419Z

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