This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-23
Channels
- # announcements (26)
- # babashka (8)
- # babashka-sci-dev (3)
- # beginners (93)
- # biff (44)
- # calva (1)
- # cider (7)
- # clj-kondo (13)
- # cljdoc (1)
- # clojure (121)
- # clojure-australia (2)
- # clojure-europe (18)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (1)
- # clojurescript (35)
- # conjure (1)
- # core-async (2)
- # datalevin (6)
- # datomic (28)
- # emacs (25)
- # events (1)
- # fulcro (5)
- # introduce-yourself (2)
- # jobs (8)
- # leiningen (2)
- # off-topic (13)
- # other-languages (1)
- # podcasts-discuss (1)
- # polylith (7)
- # rdf (6)
- # re-frame (1)
- # reagent (53)
- # releases (3)
- # rewrite-clj (7)
- # scittle (5)
- # shadow-cljs (63)
- # specter (1)
- # squint (5)
- # tools-build (5)
- # xtdb (7)
I want to get a seq of every top-level form that starts with a specific token/symbol in a file. Which is to say, I want a seq (lazy or realized) that is every (defcard ...)
in my file, and I want to spit it out into a new file with a prepended (in-ns 'game.cards.agendas)
form. Is that something rewrite-clj can give me? How is the best way to do it? If I was writing a macro, I'd probably do something like (->> forms (filter #(= 'defcard (first %))) (run! save-to-new-file))
i figured out a solution, but it's late, so i'll post it in the morning
Yeah, I think rewrite-clj is a good choice for this. Looking forward to seeing what you came up with!
not sure if this works 100% of the times but it feels simple, just working at strings level with no parsing :
(->> "(ns ...) (defn ...) (defcard 1) (defn ...) (defcard 2)" ;; replace by (slurp "file.clj")
(re-seq #"(\(defcard.+?\))")
(map (fn [[dc-form-str]]
(str "(in-ns 'game.cards.agendas)\n" dc-form-str "\n")))
(apply str)
(println)) ;; replace by (spit "output.clj")
(in-ns 'game.cards.agendas)
(defcard 1)
(in-ns 'game.cards.agendas)
(defcard 2)
Yeah, I tried doing string parsing, but I ran into issues with incorrect whitespace or similar issues, so seemed better to reach for the correct tool
This has been edited for clarity:
(loop [zloc (z/of-file (format "src/clj/game/cards/%s.clj" card-type))]
(when-not (z/end? zloc)
(let [form (z/next zloc)]
(when (= 'defcard (z/sexpr form))
(let [card-name (-> form z/next z/sexpr)
filename (str (slugify card-name "_") ".clj")]
(spit (format "src/clj/game/cards/%s/%s" card-type filename)
(n/string (n/forms-node
[(p/parse-string-all (format "(in-ns 'game.cards.%s)"
card-type))
(n/newlines 2)
(z/node (z/up form))
(n/newlines 1)])))))
(recur (z/right zloc)))))
Loop over the top-level forms with z/right
, get the z/next
token and see if it matches 'defcard
, then "slugify" the card name (defcard "Day Job"
-> "day_job", then create a new "forms" node containing the node (in-ns 'game.cards.X)
and the whole defcard
node (`(z/node (z/up form))`), plus some newlines and stuff, and spit out out to a file named for the slugyeah, the regex solution will not work at all now I think a little bit more about it