Skip to content

Commit 6c528f1

Browse files
author
dengzi
committed
config placeholder and file template
1 parent a3644cc commit 6c528f1

12 files changed

Lines changed: 269 additions & 214 deletions

src/com/dengzii/plugin/template/Config.kt

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.dengzii.plugin.template
33
import com.dengzii.plugin.template.model.FileTreeNode
44
import com.dengzii.plugin.template.model.Module
55
import com.dengzii.plugin.template.template.AucTemplate
6+
import com.dengzii.plugin.template.template.Template
67
import com.dengzii.plugin.template.utils.Logger
78
import com.google.gson.Gson
89
import com.intellij.ide.util.PropertiesComponent
@@ -20,27 +21,30 @@ import com.intellij.ide.util.PropertiesComponent
2021
object Config {
2122

2223
private const val KEY_TEMPLATES = "KEY_TEMPLATES"
24+
private const val KEY_INIT = "KEY_INIT"
2325

2426
private val GSON = Gson()
27+
private val STORE by lazy { PropertiesComponent.getInstance() }
2528

26-
val DEFAULT_MODULE_TEMPLATES = listOf(
27-
Module.create(AucTemplate.MODULE, "feature", "com.example", "Java", "Auc Feature Module"),
28-
Module.create(AucTemplate.APP, "app", "com.example", "Java", "Auc App Module"),
29-
Module.create(AucTemplate.PKG, "pkg", "com.example", "Java", "Auc Pkg Module"),
30-
Module.create(AucTemplate.EXPORT, "export", "com.example", "Java", "Auc Export Module")
29+
private val DEFAULT_MODULE_TEMPLATES = listOf(
30+
Module.create(AucTemplate.MODULE, "feature", "com.example", "Auc Feature Module"),
31+
Module.create(AucTemplate.APP, "app", "com.example", "Auc App Module"),
32+
Module.create(AucTemplate.PKG, "pkg", "com.example", "Auc Pkg Module"),
33+
Module.create(AucTemplate.EXPORT, "export", "com.example", "Auc Export Module")
3134
)
3235

33-
val MODULE_BLUEPRINT =
34-
Module.create(AucTemplate.MODULE, "feature", "com.example", "Java", "Auc Feature Module")
36+
val MODULE_ANDROID_APPLICATION =
37+
Module.create(Template.ANDROID_APP, "app", "com.example", "Android Application")
3538

36-
fun clear() {
37-
PropertiesComponent.getInstance().unsetValue(KEY_TEMPLATES)
38-
}
39+
fun clear() = STORE.unsetValue(KEY_TEMPLATES)
3940

4041
fun loadModuleTemplates(): MutableList<Module> {
4142
val result = mutableListOf<Module>()
42-
val arr = PropertiesComponent.getInstance().getValues(KEY_TEMPLATES)
43+
val arr = STORE.getValues(KEY_TEMPLATES)
4344

45+
if (STORE.getBoolean(KEY_INIT, true)) {
46+
result.addAll(DEFAULT_MODULE_TEMPLATES)
47+
}
4448
if (arr.isNullOrEmpty()) {
4549
return result
4650
}
@@ -56,6 +60,7 @@ object Config {
5660
return result
5761
}
5862
}
63+
5964
return result
6065
}
6166

@@ -65,7 +70,8 @@ object Config {
6570
t.add(GSON.toJson(it))
6671
Logger.d(Config::class.java.simpleName, "saveModuleTemplates ${t[t.lastIndex]}")
6772
}
68-
PropertiesComponent.getInstance().setValues(KEY_TEMPLATES, t.toTypedArray())
73+
STORE.setValues(KEY_TEMPLATES, t.toTypedArray())
74+
STORE.setValue(KEY_INIT, false)
6975
}
7076

7177
private fun setParent(node: FileTreeNode) {

src/com/dengzii/plugin/template/FileWriteCommand.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
5656
createFileTree(it, dir)
5757
}
5858
} else {
59-
if (treeNode.hasTemplate()) {
59+
if (treeNode.hasFileTemplate()) {
6060
val result = kit.createFileFromTemplate(
6161
treeNode.name,
6262
treeNode.getTemplateName()!!,

src/com/dengzii/plugin/template/model/FileTreeNode.kt

Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@file:Suppress("unused")
2+
13
package com.dengzii.plugin.template.model
24

35
import com.dengzii.plugin.template.template.Placeholder
@@ -16,14 +18,21 @@ import java.util.*
1618
</pre> */
1719
open class FileTreeNode private constructor() {
1820

21+
// the backing field is 'realName'
1922
var name: String
2023
get() = realName.replacePlaceholder(placeHolderMap)
2124
set(value) {
2225
realName = value
2326
}
2427

2528
var isDir = true
26-
var children = mutableListOf<FileTreeNode>()
29+
var children
30+
set(value) {
31+
realChildren = value
32+
realChildren.forEach { labeledChildren[it.getLabel()] = it }
33+
}
34+
get() = realChildren
35+
2736
var placeHolderMap: MutableMap<String, String>? = null
2837
get() = field ?: parent?.placeHolderMap
2938

@@ -34,8 +43,11 @@ open class FileTreeNode private constructor() {
3443
var fileTemplates: MutableMap<String, String>? = null
3544
get() = field ?: parent?.fileTemplates
3645

46+
private var realChildren = mutableSetOf<FileTreeNode>()
3747
// the origin name with original placeholder
3848
private var realName: String = ""
49+
// the label composed by 'name' and 'isDir'.
50+
private val labeledChildren = mutableMapOf<String, FileTreeNode>()
3951
@Transient
4052
var parent: FileTreeNode? = null
4153

@@ -72,12 +84,28 @@ open class FileTreeNode private constructor() {
7284

7385
fun removeFromParent(): Boolean {
7486
if (parent != null) {
87+
parent!!.labeledChildren.remove(getLabel())
7588
parent!!.children.remove(this)
7689
return true
7790
}
7891
return false
7992
}
8093

94+
fun addChild(child: FileTreeNode, override: Boolean = false): Boolean {
95+
if (hasChild(child.getLabel())) {
96+
if (override) {
97+
Logger.d(TAG, "node has already exists $child")
98+
return false
99+
} else {
100+
Logger.d(TAG, "override node ${child.getPath()}")
101+
}
102+
}
103+
child.parent = this
104+
children.add(child)
105+
labeledChildren[child.getLabel()] = child
106+
return true
107+
}
108+
81109
fun hasChild(name: String, isDir: Boolean): Boolean {
82110
children.forEach {
83111
if (it.isDir == isDir && it.realName == name) {
@@ -87,6 +115,14 @@ open class FileTreeNode private constructor() {
87115
return false
88116
}
89117

118+
fun hasChild(label: String): Boolean {
119+
return labeledChildren.containsKey(label)
120+
}
121+
122+
/**
123+
* get the origin name without replace with placeholder
124+
* real name is the value when you set field 'name'
125+
*/
90126
fun getRealName(): String {
91127
return realName
92128
}
@@ -98,19 +134,23 @@ open class FileTreeNode private constructor() {
98134
fileTemplates!![fileName] = template
99135
}
100136

101-
fun hasTemplate(): Boolean {
137+
fun hasFileTemplate(): Boolean {
102138
return template != null || fileTemplates?.containsKey(realName) == true
103139
}
104140

105141
fun getTemplateName(): String? {
106142
return template ?: fileTemplates?.get(realName)
107143
}
108144

109-
fun placeholder(placeholder: Placeholder, value: String) {
145+
fun placeholder(name: String, value: String) {
110146
if (this.placeHolderMap == null) {
111147
this.placeHolderMap = kotlin.collections.mutableMapOf()
112148
}
113-
placeHolderMap!![placeholder.getPlaceholder()] = value
149+
placeHolderMap!![name] = value
150+
}
151+
152+
fun placeholder(placeholder: Placeholder) {
153+
placeholder(placeholder.placeholder, placeholder.value)
114154
}
115155

116156
/**
@@ -153,43 +193,56 @@ open class FileTreeNode private constructor() {
153193
}
154194

155195
/**
156-
* merge all children of another node to 'this.children'.
196+
* merge all children of another node to this.
157197
*/
158-
fun include(other: FileTreeNode) {
198+
fun include(other: FileTreeNode, override: Boolean = false) {
159199
if (!isDir) return
160200
other.children.forEach {
161-
val child = it.clone()
162-
child.parent = this
163-
children.add(child)
201+
addChild(it.clone(), override)
164202
}
165203
}
166204

205+
/**
206+
* create directory nodes from the path
207+
*
208+
* @param path The dir path
209+
* @param block The child node domain
210+
*/
167211
fun dir(path: String, block: FileTreeNode.() -> Unit = {}) {
168212
if (!isDir) return
169213
val dirs = path.split("/").filter { it.isNotBlank() }.toMutableList()
170214
createDirs(dirs, this)(block)
171215
}
172216

217+
/**
218+
* create directories tree from a list
219+
* the larger the index, the deeper the directory
220+
*
221+
* @param dirs The dirs list to create tree
222+
* @param parent The parent of current node
223+
*/
173224
private fun createDirs(dirs: MutableList<String>, parent: FileTreeNode): FileTreeNode {
174225
if (dirs.isEmpty()) {
175226
return parent
176227
}
177228
val current = dirs[0]
178229
dirs.removeAt(0)
179230
val dirNode = FileTreeNode(parent, current, true)
180-
parent.children.add(dirNode)
231+
addChild(dirNode)
181232
return createDirs(dirs, dirNode)
182233
}
183234

184235
fun file(name: String) {
185236
if (!isDir) return
186-
children.add(FileTreeNode(this, name, false))
237+
addChild(FileTreeNode(this, name, false))
187238
}
188239

189240
/**
190241
* get path of current node.
191242
* if the current node is the root node, it will return absolute path,
192243
* otherwise return relative path.
244+
*
245+
* @return The intact path of current node
193246
*/
194247
fun getPath(): String {
195248
if (isRoot() || parent == null || parent!!.name == "") {
@@ -206,16 +259,28 @@ open class FileTreeNode private constructor() {
206259
return getNodeGraph().toString()
207260
}
208261

262+
/**
263+
* clone current node, the following fields will be copied:
264+
* name, isDir, fileTemplates, placeHolderMap, children
265+
*
266+
* the parent will not be cloned
267+
*/
209268
fun clone(): FileTreeNode {
210-
val cl = FileTreeNode(null, name, isDir)
211-
cl.fileTemplates = fileTemplates?.toMutableMap()
212-
cl.placeHolderMap = placeHolderMap?.toMutableMap()
269+
val clone = FileTreeNode(null, name, isDir)
270+
clone.fileTemplates = fileTemplates?.toMutableMap()
271+
clone.placeHolderMap = placeHolderMap?.toMutableMap()
213272
children.forEach {
214-
val child = it.clone()
215-
child.parent = cl
216-
cl.children.add(child)
273+
clone.addChild(it.clone())
217274
}
218-
return cl
275+
return clone
276+
}
277+
278+
private fun removeChild(label: String): FileTreeNode? {
279+
if (hasChild(label)) {
280+
children.remove(labeledChildren[label])
281+
return labeledChildren.remove(label)
282+
}
283+
return null
219284
}
220285

221286
private fun getNodeGraph(head: Stack<String> = Stack(), str: StringBuilder = StringBuilder()): StringBuilder {
@@ -263,7 +328,11 @@ open class FileTreeNode private constructor() {
263328
}
264329
}
265330

331+
private fun getLabel(): String {
332+
return "name_$isDir"
333+
}
334+
266335
override fun toString(): String {
267-
return "FileTreeNode(path='${getPath()}')"
336+
return "FileTreeNode(path='${getPath()}' isDir=$isDir)"
268337
}
269338
}

src/com/dengzii/plugin/template/model/Module.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ class Module(
1616

1717
companion object {
1818
fun create(template: FileTreeNode, moduleName: String,
19-
packageName: String, language: String, templateName: String): Module {
19+
packageName: String, templateName: String): Module {
2020
Logger.i(Module::class.java.simpleName, "create module. $template moduleName=$moduleName, templateName=$templateName")
21-
return Module(template, moduleName, packageName, language, templateName)
21+
return Module(template, moduleName, packageName, "java", templateName)
2222
}
2323

2424
fun getLangList() = Language.values().map { it.name.toLowerCase() }.toTypedArray()

src/com/dengzii/plugin/template/template/AndroidModuleTempateExtensions.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ val Node.res: Node get() = dirNode("res")
2929
val Node.app: Node get() = dirNode("app")
3030
val Node.pkg: Node get() = dirNode("pkg")
3131
val Node.export: Node get() = dirNode("export")
32-
val Node.pkg_name: Node get() = dirNode(Placeholder.PACKAGE_NAME.getPlaceholder())
33-
val Node.module_name: Node get() = dirNode(Placeholder.MODULE_NAME.getPlaceholder())
32+
val Node.pkg_name: Node get() = dirNode(Placeholder.PACKAGE_NAME.placeholder)
33+
val Node.module_name: Node get() = dirNode(Placeholder.MODULE_NAME.placeholder)
3434
val Node.layout: Node get() = dirNode("layout")
3535
val Node.values: Node get() = dirNode("values")
3636
val Node.drawable: Node get() = dirNode("drawable")
@@ -40,7 +40,7 @@ val Node.AndroidManifest: FileNode get() = fileNode("AndroidManifest")
4040
val Node.proguard_rules: FileNode get() = fileNode("proguard-rules")
4141
val Node.gitignore: FileNode get() = fileNode(".gitignore")
4242
val Node.build: FileNode get() = fileNode("build")
43-
val Node.app_name: FileNode get() = fileNode(Placeholder.APPLICATION_NAME.getPlaceholder())
43+
val Node.app_name: FileNode get() = fileNode(Placeholder.APPLICATION_NAME.placeholder)
4444

4545
val FileNode.gradle: FileNode get() = nodeSuffix(".gradle")
4646
val FileNode.java: FileNode get() = nodeSuffix(".java")

0 commit comments

Comments
 (0)