-
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathnew.clj
143 lines (127 loc) · 5.79 KB
/
new.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
;; copyright (c) 2021 sean corfield, all rights reserved
(ns org.corfield.new
"The next generation of clj-new. Uses tools.build and
tools.deps.alpha heavily to provide a simpler 'shim'
around template processing."
{:org.babashka/cli {:coerce {:overwrite :keyword}}}
(:require [clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.spec.alpha :as s]
[clojure.tools.build.api :as b]
[org.corfield.new.impl :as impl]))
(set! *warn-on-reflection* true)
(s/def ::root string?)
(s/def ::description string?)
(s/def ::data-fn symbol?)
(s/def ::template-fn symbol?)
(s/def ::files (s/map-of string? string?))
(s/def ::open-close (s/tuple string? string?))
(s/def ::opts #{:only :raw})
(s/def ::dir-spec (s/cat :src string?
:target (s/? string?)
:files (s/? ::files)
:delims (s/? ::open-close)
:opts (s/* ::opts)))
(s/def ::transform (s/coll-of ::dir-spec :min-count 1))
(s/def ::template (s/keys :opt-un [::data-fn ::description ::root ::template-fn ::transform]))
(comment
(s/conform ::transform [["root"]])
(s/conform ::transform [["raw" "images" {} :raw]])
(s/conform ::transform [["raw" "images" {} :only :raw]])
(s/conform ::template {:transform [["resources" "resources"]
["images" "img" {"logo.png" "{{logo}}/main.png"} :raw]]})
)
(defn create
"Exec function to create a new project from a template.
`:template` -- a symbol (or string) identifying the template,
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- optional string identifying the directory to
create the new project in,
`:overwrite` -- whether to overwrite an existing directory or,
for `:delete`, to delete it first; if `:overwrite` is `nil`
or `false`, an existing directory will not be overwritten."
[opts]
(let [{:keys [template] :as basic-opts}
(impl/preprocess-options opts)
[dir edn-file] (impl/find-root template)
_
(when-not dir
(throw (ex-info (str "Unable to find template.edn for " template) {})))
[{:keys [target-dir template-dir overwrite] :as final-opts} edn]
(impl/apply-template-fns dir
basic-opts
;; this may throw for invalid EDN:
(-> edn-file (slurp) (edn/read-string)))
data (impl/->subst-map final-opts)
edn' (s/conform ::template edn)]
(when (s/invalid? edn')
(throw (ex-info (str edn-file " is not a valid template file\n\n"
(s/explain-str ::template edn))
(s/explain-data ::template edn))))
(when (.exists (io/file target-dir))
(if overwrite
(when (= :delete overwrite)
(println "Deleting old" target-dir)
(b/delete {:path target-dir}))
(throw (ex-info (str target-dir " already exists (and :overwrite was not true).") {}))))
(println "Creating project from" template "in" target-dir)
(impl/copy-template-dir template-dir target-dir {:src (:root edn' "root")} data)
(run! #(impl/copy-template-dir template-dir target-dir % data) (:transform edn'))))
(defn app
"Exec function to create an application project.
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- optional string identifying the directory to
create the new project in,
`:overwrite` -- whether to overwrite an existing directory or,
for `:delete`, to delete it first; if `:overwrite` is `nil`
or `false`, an existing directory will not be overwritten."
[opts]
(create (assoc opts :template 'app)))
(defn lib
"Exec function to create a library project.
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- optional string identifying the directory to
create the new project in,
`:overwrite` -- whether to overwrite an existing directory or,
for `:delete`, to delete it first; if `:overwrite` is `nil`
or `false`, an existing directory will not be overwritten."
[opts]
(create (assoc opts :template 'lib)))
(defn template
"Exec function to create a template project.
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- optional string identifying the directory to
create the new project in,
`:overwrite` -- whether to overwrite an existing directory or,
for `:delete`, to delete it first; if `:overwrite` is `nil`
or `false`, an existing directory will not be overwritten."
[opts]
(create (assoc opts :template 'template)))
(defn pom
"Exec function to create just a `pom.xml` file.
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- a string identifying the directory in which
to create the `pom.xml` file,
`:overwrite` -- defaults to `true` since you _do_ want to
write into an existing directory!"
[opts]
(create (-> (merge {:overwrite true} opts)
(assoc :template 'pom))))
(defn scratch
"Exec function to create a minimal 'scratch' project.
`:name` -- a symbol (or string) identifying the project name,
`:target-dir` -- optional string identifying the directory to
create the new project in,
`:overwrite` -- whether to overwrite an existing directory or,
for `:delete`, to delete it first; if `:overwrite` is `nil`
or `false`, an existing directory will not be overwritten."
[opts]
(create (assoc opts :template 'scratch)))
(comment
(let [[_dir edn] (impl/find-root 'org.corfield.new/app)]
(s/conform ::template (edn/read-string (slurp edn))))
(create {:template 'org.corfield.new/app
:name 'org.bitbucket.wsnetworks/example
:target-dir "new-out"
:overwrite :delete})
)