Skip to content

Commit f3ba2be

Browse files
committed
# Conflicts: # src/com/dengzii/plugin/template/ui/ConfigDialog.form # src/com/dengzii/plugin/template/ui/ConfigDialog.java
2 parents b6b22ff + 9214282 commit f3ba2be

21 files changed

Lines changed: 661 additions & 272 deletions

resources/META-INF/plugin.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@
1717
]]>
1818
</change-notes>
1919

20-
<idea-version since-build="182.711"/>
20+
<idea-version since-build="183.2153.8"/>
2121

2222
<depends>com.intellij.modules.java</depends>
2323
<depends>org.jetbrains.kotlin</depends>
2424

2525
<extensions defaultExtensionNs="com.intellij">
2626
<fileTemplateGroup implementation="com.dengzii.plugin.template.template.FileTemplateFactory" order="first"/>
2727
<internalFileTemplate name="AndroidManifest" id="com.dengzii.plugin.template.ft.manifest"/>
28+
<applicationConfigurable groupId="tools" displayName="Template Module Generator"
29+
id="preferences.ModuleTemplateConfig"
30+
instance="com.dengzii.plugin.template.ui.ConfigurePanel"/>
2831
</extensions>
2932

3033
<actions>
3134
<!-- Add your actions here -->
3235
<action id="com.dengzii.plugin.template.gen" class="com.dengzii.plugin.template.CreateModuleAction"
33-
text="Template Module Generator"
36+
text="Create Module From Template"
3437
description="Create module from template">
3538
<add-to-group group-id="ProjectViewPopupMenu" anchor="first"/>
3639
</action>

resources/META-INF/pluginIcon.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ${PACKAGE_NAME};
2+
3+
import ${BASE_APPLICATION};
4+
5+
public class ${CLASS_NAME} extends BaseApplication{
6+
7+
public void onCreate(){
8+
9+
}
10+
}

resources/fileTemplates/Template Application.java.ft

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package ${PACKAGE_NAME};
22

33
import ${BASE_APPLICATION};
44

5-
public class ${APPLICATION_NAME} extends BaseApplication{
5+
public class ${CLASS_NAME} extends BaseApplication{
66

77
public void onCreate(){
88

resources/fileTemplates/Template Application.kt.ft

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package ${PACKAGE_NAME}
22

33
import ${BASE_APPLICATION}
44

5-
public class App extends BaseApplication{
5+
class ${CLASS_NAME}:BaseApplication(){
66

7-
public void onCreate(){
7+
fun onCreate(){
88

99
}
1010
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dependencies{
2+
3+
}
Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.dengzii.plugin.template
22

3-
import com.dengzii.plugin.template.model.ModuleConfig
3+
import com.dengzii.plugin.template.model.FileTreeNode
4+
import com.dengzii.plugin.template.model.Module
45
import com.dengzii.plugin.template.template.AucTemplate
6+
import com.dengzii.plugin.template.utils.Logger
7+
import com.google.gson.Gson
58
import com.intellij.ide.util.PropertiesComponent
69

710
/**
@@ -18,22 +21,58 @@ object Config {
1821

1922
private const val KEY_TEMPLATES = "KEY_TEMPLATES"
2023

21-
val DEFAULT_TEMPLATE = listOf(
22-
ModuleConfig.create(AucTemplate.MODULE, "feature", "com.example.feature", "Java", "Auc Feature Module"),
23-
ModuleConfig.create(AucTemplate.APP, "app", "com.example.feature", "Java", "Auc App Module"),
24-
ModuleConfig.create(AucTemplate.PKG, "pkg", "com.example.feature", "Java", "Auc Pkg Module"),
25-
ModuleConfig.create(AucTemplate.EXPORT, "export", "com.example.feature", "Java", "Auc Export Module")
24+
private val GSON = Gson()
25+
val DEFAULT_MODULE_TEMPLATE = listOf(
26+
Module.create(AucTemplate.MODULE, "feature", "com.example.feature", "Java", "Auc Feature Module"),
27+
Module.create(AucTemplate.APP, "app", "com.example.feature", "Java", "Auc App Module"),
28+
Module.create(AucTemplate.PKG, "pkg", "com.example.feature", "Java", "Auc Pkg Module"),
29+
Module.create(AucTemplate.EXPORT, "export", "com.example.feature", "Java", "Auc Export Module")
2630
)
2731

32+
2833
fun clear() {
2934
PropertiesComponent.getInstance().unsetValue(KEY_TEMPLATES)
3035
}
3136

32-
fun loadTemplates(): List<ModuleConfig> {
33-
return DEFAULT_TEMPLATE
37+
fun loadModuleTemplates(): MutableList<Module> {
38+
val result = mutableListOf<Module>()
39+
val arr = PropertiesComponent.getInstance().getValues(KEY_TEMPLATES)
40+
41+
if (arr.isNullOrEmpty()) {
42+
return result
43+
}
44+
Logger.d(Config::class.java.simpleName, "loadModuleTemplates")
45+
arr.forEach {
46+
try {
47+
val module = GSON.fromJson(it, Module::class.java)
48+
setParent(module.template)
49+
println(module.template.getTreeGraph())
50+
result.add(module)
51+
} catch (e: Exception) {
52+
clear()
53+
e.printStackTrace()
54+
return result
55+
}
56+
}
57+
result.addAll(DEFAULT_MODULE_TEMPLATE)
58+
return result
3459
}
3560

36-
fun saveTemplates() {
61+
fun saveModuleTemplates(templates: List<Module>) {
62+
val t = mutableListOf<String>()
63+
templates.forEach {
64+
t.add(GSON.toJson(it))
65+
Logger.d(Config::class.java.simpleName, "saveModuleTemplates ${t[t.lastIndex]}")
66+
}
67+
PropertiesComponent.getInstance().setValues(KEY_TEMPLATES, t.toTypedArray())
68+
}
3769

70+
private fun setParent(node: FileTreeNode) {
71+
node.children.forEach {
72+
it.parent = node
73+
if (it.isDir) {
74+
setParent(it)
75+
}
76+
}
3877
}
3978
}
Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.dengzii.plugin.template
22

33
import com.dengzii.plugin.template.model.FileTreeNode
4-
import com.dengzii.plugin.template.model.ModuleConfig
4+
import com.dengzii.plugin.template.model.Module
55
import com.dengzii.plugin.template.utils.Logger
66
import com.dengzii.plugin.template.utils.PluginKit
77
import com.intellij.openapi.command.UndoConfirmationPolicy
@@ -18,15 +18,15 @@ import com.intellij.util.ThrowableRunnable
1818
* desc :
1919
* </pre>
2020
*/
21-
class FileWriteCommand(private var kit: PluginKit, private var moduleConfig: ModuleConfig) : ThrowableRunnable<Exception> {
21+
class FileWriteCommand(private var kit: PluginKit, private var module: Module) : ThrowableRunnable<Exception> {
2222

2323
companion object {
2424
private val TAG = FileWriteCommand::class.java.simpleName
25-
fun startAction(kit: PluginKit, moduleConfig: ModuleConfig) {
25+
fun startAction(kit: PluginKit, module: Module) {
2626
WriteCommandAction.writeCommandAction(kit.project)
2727
.withGlobalUndo()
2828
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
29-
.run(FileWriteCommand(kit, moduleConfig))
29+
.run(FileWriteCommand(kit, module))
3030
}
3131
}
3232

@@ -37,26 +37,37 @@ class FileWriteCommand(private var kit: PluginKit, private var moduleConfig: Mod
3737
Logger.i(TAG, "Current target is not directory.")
3838
return
3939
}
40-
val fileTreeNode = moduleConfig.template
40+
val fileTreeNode = module.template
4141
Logger.d(TAG, fileTreeNode.placeHolderMap.toString())
4242
fileTreeNode.children.forEach {
4343
createFileTree(it, current)
4444
}
4545
}
4646

47-
private fun createFileTree(treeNode: FileTreeNode, current: VirtualFile?) {
48-
if (current == null) {
49-
Logger.e(TAG, "The parent of ${treeNode.getPath()} is null")
50-
return
51-
}
47+
private fun createFileTree(treeNode: FileTreeNode, currentDirectory: VirtualFile) {
5248
Logger.i(TAG, "Create ${treeNode.getPath()}")
5349
if (treeNode.isDir) {
54-
kit.createDir(treeNode.name, current)
50+
val dir = kit.createDir(treeNode.name, currentDirectory)
51+
if (dir == null) {
52+
Logger.e(TAG, "create directory failure: ${treeNode.name}")
53+
return
54+
}
5555
treeNode.children.forEach {
56-
createFileTree(it, current.findChild(treeNode.name))
56+
createFileTree(it, dir)
5757
}
5858
} else {
59-
kit.createFile(treeNode.name, current)
59+
if (treeNode.hasTemplate()) {
60+
val result = kit.createFileFromTemplate(
61+
treeNode.name,
62+
treeNode.getTemplateName()!!,
63+
treeNode.placeHolderMap.orEmpty(),
64+
currentDirectory)
65+
if (result == null) {
66+
Logger.e(TAG, "create file from template failed, file: ${treeNode.name} template:${treeNode.getTemplateName()}")
67+
}
68+
} else {
69+
kit.createFile(treeNode.name, currentDirectory)
70+
}
6071
}
6172
}
6273
}

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

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.dengzii.plugin.template.template.Placeholder
44
import com.dengzii.plugin.template.template.replacePlaceholder
55
import com.dengzii.plugin.template.utils.Logger
66
import java.io.File
7+
import java.util.*
78

89
/**
910
* <pre>
@@ -22,15 +23,24 @@ open class FileTreeNode private constructor() {
2223
}
2324

2425
var isDir = true
25-
val children by lazy { mutableListOf<FileTreeNode>() }
26-
var placeHolderMap: MutableMap<Placeholder, String>? = null
26+
var children = mutableListOf<FileTreeNode>()
27+
var placeHolderMap: MutableMap<String, String>? = null
2728
get() = field ?: parent?.placeHolderMap
2829

30+
// template for node, higher priority than fileTemplates
31+
var template: String? = null
32+
33+
// template of filename
34+
var fileTemplates: MutableMap<String, String>? = null
35+
get() = field ?: parent?.fileTemplates
36+
2937
// the origin name with original placeholder
3038
private var realName: String = ""
31-
private var parent: FileTreeNode? = null
39+
@Transient
40+
var parent: FileTreeNode? = null
3241

3342
companion object {
43+
3444
private val TAG = FileTreeNode::class.java.simpleName
3545

3646
fun root(path: String): FileTreeNode {
@@ -60,11 +70,30 @@ open class FileTreeNode private constructor() {
6070
return this
6171
}
6272

73+
fun getRealName(): String {
74+
return realName
75+
}
76+
77+
fun fileTemplate(fileName: String, template: String) {
78+
if (this.fileTemplates == null) {
79+
this.fileTemplates = mutableMapOf()
80+
}
81+
fileTemplates!![fileName] = template
82+
}
83+
84+
fun hasTemplate(): Boolean {
85+
return template != null || fileTemplates?.containsKey(realName) == true
86+
}
87+
88+
fun getTemplateName(): String? {
89+
return template ?: fileTemplates?.get(realName)
90+
}
91+
6392
fun placeholder(placeholder: Placeholder, value: String) {
6493
if (this.placeHolderMap == null) {
6594
this.placeHolderMap = kotlin.collections.mutableMapOf()
6695
}
67-
placeHolderMap!![placeholder] = value
96+
placeHolderMap!![placeholder.getPlaceholder()] = value
6897
}
6998

7099
/**
@@ -112,16 +141,27 @@ open class FileTreeNode private constructor() {
112141
fun include(other: FileTreeNode) {
113142
if (!isDir) return
114143
other.children.forEach {
115-
it.parent = this
116-
children.add(it)
144+
val child = it.clone()
145+
child.parent = this
146+
children.add(child)
117147
}
118148
}
119149

120-
fun dir(name: String, block: FileTreeNode.() -> Unit = {}) {
150+
fun dir(path: String, block: FileTreeNode.() -> Unit = {}) {
121151
if (!isDir) return
122-
val dir = FileTreeNode(this, name, true)
123-
children.add(dir)
124-
dir(block)
152+
val dirs = path.split("/").filter { it.isNotBlank() }.toMutableList()
153+
createDirs(dirs, this)(block)
154+
}
155+
156+
private fun createDirs(dirs: MutableList<String>, parent: FileTreeNode): FileTreeNode {
157+
if (dirs.isEmpty()) {
158+
return parent
159+
}
160+
val current = dirs[0]
161+
dirs.removeAt(0)
162+
val dirNode = FileTreeNode(parent, current, true)
163+
parent.children.add(dirNode)
164+
return createDirs(dirs, dirNode)
125165
}
126166

127167
fun file(name: String) {
@@ -141,18 +181,50 @@ open class FileTreeNode private constructor() {
141181
return parent!!.getPath() + "/" + name
142182
}
143183

144-
145184
fun isRoot(): Boolean {
146185
return this == parent
147186
}
148187

149188
fun getTreeGraph(): String {
150-
val strBuilder = StringBuilder()
151-
traversal({ i, dep ->
152-
val head = if (i.isRoot()) "" else if (children.last() == i) "" else ""
153-
strBuilder.append("".repeat(dep) + "$head" + i.name)
189+
return getNodeGraph().toString()
190+
}
191+
192+
fun clone(): FileTreeNode {
193+
val cl = FileTreeNode(null, name, isDir)
194+
cl.fileTemplates = fileTemplates?.toMutableMap()
195+
cl.placeHolderMap = placeHolderMap?.toMutableMap()
196+
children.forEach {
197+
val child = it.clone()
198+
child.parent = cl
199+
cl.children.add(child)
200+
}
201+
return cl
202+
}
203+
204+
private fun getNodeGraph(head: Stack<String> = Stack(), str: StringBuilder = StringBuilder()): StringBuilder {
205+
206+
head.forEach {
207+
str.append(it)
208+
}
209+
str.append(when (this) {
210+
parent?.children?.last() -> "└─"
211+
parent?.children?.first() -> "├─"
212+
else -> if (parent?.parent != null) "├─" else "┌─"
154213
})
155-
return strBuilder.toString()
214+
str.append(name).append("\n")
215+
216+
if (!children.isNullOrEmpty()) {
217+
head.push(when {
218+
parent == null -> ""
219+
parent?.children?.last() != this -> "\t"
220+
else -> "\t"
221+
})
222+
children.forEach {
223+
str.append(it.getNodeGraph(head))
224+
}
225+
head.pop()
226+
}
227+
return str
156228
}
157229

158230
private fun createChild() {

0 commit comments

Comments
 (0)