1
+ #! /usr/bin/env bb
2
+
3
+ (require '[cheshire.core :as json]
4
+ '[babashka.fs :as fs]
5
+ '[clojure.string :as str]
6
+ '[clojure.edn :as edn])
7
+
8
+ (comment
9
+ (def slug " list-ops" ))
10
+
11
+ (def data
12
+ (let [url " https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/" ]
13
+ {:canonical-data (json/parse-string (slurp (str url " /" slug " /canonical-data.json" )) true )
14
+ :description (slurp (str url " /" slug " /description.md" ))
15
+ :metadata (slurp (str url " /" slug " /metadata.toml" ))}))
16
+
17
+ (second
18
+ (str/split (:metadata data) #"=" ))
19
+
20
+ (defn get-meta
21
+ " Returns a vector containing the exercise title and blurb"
22
+ [data]
23
+ (mapv last
24
+ (map #(map str/trim (str/split % #"=" ))
25
+ (str/split-lines (:metadata data)))))
26
+
27
+ (defn init-deps! [data]
28
+ (fs/create-dirs (fs/path " exercises" " practice"
29
+ (:exercise (:canonical-data data)) " src" ))
30
+ (spit (str (fs/file " exercises" " practice"
31
+ (:exercise (:canonical-data data))
32
+ " deps.edn" ))
33
+ " {:aliases {:test {:extra-paths [\" test\" ]
34
+ :extra-deps {io.github.cognitect-labs/test-runner
35
+ {:git/url \" https://github.com/cognitect-labs/test-runner.git\"
36
+ :sha \" 705ad25bbf0228b1c38d0244a36001c2987d7337\" }}
37
+ :main-opts [\" -m\" \" cognitect.test-runner\" ]
38
+ :exec-fn cognitect.test-runner.api/test}}}" ))
39
+
40
+ (comment
41
+ (init-deps! data)
42
+ )
43
+
44
+ (defn init-lein! [data]
45
+ (let [slug (:exercise (:canonical-data data))]
46
+ (spit (str (fs/file " exercises" " practice"
47
+ (:exercise (:canonical-data data)) " project.clj" ))
48
+ (str " (defproject " slug " \" 0.1.0-SNAPSHOT\"
49
+ :description \" " slug " exercise.\"
50
+ :url \" https://github.com/exercism/clojure/tree/main/exercises/" slug " \"
51
+ :dependencies [[org.clojure/clojure \" 1.10.0\" ]])
52
+ " ))))
53
+
54
+ (comment
55
+ (init-lein! data)
56
+ )
57
+
58
+ (defn test-ns-form [data]
59
+ (str " (ns " (:exercise data) " -test
60
+ (:require [clojure.test :refer [deftest testing is]]\n "
61
+ (:exercise data) " ))\n\n " ))
62
+
63
+ (defn src-ns-form [data]
64
+ (str " (ns " (:exercise data) " )\n\n " ))
65
+
66
+ (defn trans-fn [s]
67
+ (let [[args body] (str/split s #"->" )
68
+ arg-strs (mapv str (edn/read-string args))
69
+ [arg1 op arg2] (str/split (str/trim body) #"\s " )]
70
+ (str " (fn [" (apply str (interpose " " arg-strs)) " ] "
71
+ " (" op " " arg1 " " arg2 " ))" )))
72
+
73
+ (comment
74
+ (trans-fn " (x) -> x + 1" )
75
+ (trans-fn " (x, y) -> x * y" )
76
+ (trans-fn " (acc, el) -> el * acc" )
77
+ )
78
+
79
+ (defn testing-form [slug test-case]
80
+ (let [property (symbol (str slug " /" (:property test-case)))
81
+ input (:input test-case)
82
+ args (map #(get input %) (keys input))]
83
+ (str " (testing \" " (:description test-case) " \"
84
+ (is (= " (:expected test-case) " "
85
+ (reverse (into (list property) args)) " )))" )))
86
+
87
+ (comment
88
+ (testing-form " list-ops" (first (:cases (first (:cases (:canonical-data data))))))
89
+ )
90
+
91
+ (defn testing-forms
92
+ " Outputs a sequence of the test cases for a given property name
93
+ given its name as a string and the canonical data."
94
+ [property data]
95
+ (let [test-cases (filter #(= property (:property %))
96
+ (mapcat :cases
97
+ (:cases (:canonical-data data))))]
98
+ (map #(testing-form (:exercise (:canonical-data data)) %) test-cases)))
99
+
100
+ (comment
101
+ (testing-forms " append" data)
102
+ )
103
+
104
+ (defn deftest-forms [data]
105
+ (for [property (distinct (map :property (mapcat :cases
106
+ (:cases (:canonical-data data)))))]
107
+ (str " (deftest " property " -test\n "
108
+ (apply str (interpose " \n "
109
+ (testing-forms property data)))
110
+ " )" )))
111
+
112
+ (comment
113
+ (deftest-forms data )
114
+ )
115
+
116
+ (defn init-tests! [data]
117
+ (let [path (fs/path " exercises" " practice"
118
+ (:exercise (:canonical-data data)) " test" )]
119
+ (when-not (fs/directory? path)
120
+ (fs/create-dir path))
121
+ (spit (str (fs/file " exercises" " practice"
122
+ (:exercise (:canonical-data data)) " test"
123
+ (str (str/replace (:exercise (:canonical-data data)) " -" " _" )
124
+ " _test.clj" )))
125
+ (str (test-ns-form (:canonical-data data))
126
+ (apply str (interpose " \n\n "
127
+ (deftest-forms data )))))))
128
+
129
+ (comment
130
+ (init-tests! data)
131
+ )
132
+
133
+ (defn init-src! [data]
134
+ (spit (str (fs/file " exercises" " practice" (:exercise (:canonical-data data)) " src"
135
+ (str (str/replace (:exercise (:canonical-data data))
136
+ " -" " _" ) " .clj" )))
137
+ (str (src-ns-form (:canonical-data data))
138
+ (apply str (interpose " \n\n "
139
+ (for [property (distinct (map :property (mapcat :cases
140
+ (:cases (:canonical-data data)))))]
141
+ (str " (defn " property " []\n )" )))))))
142
+
143
+ (comment
144
+ (init-src! data)
145
+ )
146
+
147
+ (defn init-description! [data]
148
+ (let [path [" exercises" " practice" (:exercise (:canonical-data data)) " .docs" ]]
149
+ (when-not (fs/directory? (apply fs/path path))
150
+ (fs/create-dir (apply fs/path path))
151
+ (spit (str (apply fs/file (conj path " instructions.md" )))
152
+ (:description data)))))
153
+
154
+ (comment
155
+ (init-description! data)
156
+ )
157
+
158
+ (defn config [data author blurb]
159
+ (let [slug (:exercise (:canonical-data data))]
160
+ {:authors [author],
161
+ :contributors [],
162
+ :files {:solution [(str " src/" (str/replace slug " -" " _" ) " .clj" )],
163
+ :test [(str " test/" (str/replace slug " -" " _" ) " _test.clj" )],
164
+ :example [" .meta/src/example.clj" ]},
165
+ :blurb blurb}))
166
+
167
+ (defn init-config! [data]
168
+ (let [path [" exercises" " practice" (:exercise (:canonical-data data)) " .meta" ]]
169
+ (when-not (fs/directory? (apply fs/path path))
170
+ (fs/create-dirs (apply fs/path (conj path " src" )))
171
+ (spit (str (apply fs/file (conj path " config.json" )))
172
+ (json/generate-string (config data " porkostomus" (last (get-meta data)))
173
+ {:pretty true })))))
174
+
175
+ (comment
176
+ (init-config! data)
177
+ )
0 commit comments