Skip to content

Commit 23b6523

Browse files
committed
support apache velocity in file name
1 parent f320032 commit 23b6523

File tree

12 files changed

+128
-52
lines changed

12 files changed

+128
-52
lines changed

resources/META-INF/plugin.xml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<idea-plugin>
22
<id>com.dengzii.plugin.template</id>
33
<name>Generate Module From Template</name>
4-
<version>1.5.4</version>
4+
<version>1.6.4</version>
55
<vendor email="dengzii@foxmail.com" url="https://github.com/dengzii">dengzi</vendor>
66

77
<description><![CDATA[
@@ -10,17 +10,16 @@
1010
<a href="https://youtu.be/TyeXnbCcBP4">Video Tutorial - YouTube</a>
1111
<br>
1212
<b>Feature</b><br>
13-
0. Create module template from exists project irectory.<br>
1413
1. Custom directory/file tree structure.<br>
15-
2. Support placeholders, and replace it when you create a module.<br>
14+
2. Support placeholders / ApacheVelocity template lang in file name.<br>
1615
3. Specify file templates from IDE custom/build-in templates.<br>
1716
4. Passing placeholders to file template as variables.<br>
1817
5. Output/import template file. share your template with your partner.<br>
1918
<br>
2019
<b>Usage</b><br>
2120
1. Configure template in plugin settings: <b>File > Settings > Tools > Module Template Settings</b>.<br>
2221
2. Create directories from the 'Structure' tab, click the right mouse button to operate the file tree.<br>
23-
3. FileTree can use placeholders, the placeholder should like this -> <b>${YOUR_PLACEHOLDER_HERE}</b>.<br>
22+
3. FileTree can use placeholders or ApacheVelocity template lang, the placeholder should like this -> <b>${YOUR_PLACEHOLDER_HERE}</b>.<br>
2423
4. The 'File Template' tab lists which template the specified file uses, you can also use placeholders for FileName field.<br>
2524
5. The 'Placeholder' tab's table defines placeholders for replacing filenames and file templates<br>
2625
More information: <a href='https://github.com/dengzii/GenerateModuleFromTemplate/blob/master/README.md'>README</a><br>
@@ -43,15 +42,13 @@ Any question please <a href='https://github.com/dengzii/GenerateModuleFromTempla
4342
]]></description>
4443

4544
<change-notes><![CDATA[
46-
<b>Version 1.5.4 (2022/10/10)</b><br>
47-
0. Fix: default placeholder and file template cannot save.<br>
48-
1. Feat: support create module template from a directory.<br>
49-
2. Feat: support remove directory node and merge children to current's parent node.<br>
45+
<b>Version 1.6.4 (2023/07/06)</b><br>
46+
1. Feature: Support ApacheVelocity in file name.<br>
5047
<br>
5148
]]>
5249
</change-notes>
5350

54-
<idea-version since-build="191.8026.42"/>
51+
<idea-version since-build="203.5981.155"/>
5552

5653
<depends>com.intellij.modules.platform</depends>
5754
<depends>com.intellij.modules.lang</depends>

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@ object Config {
3131
val arr = STORE.getValues(KEY_TEMPLATES)
3232

3333
if (STORE.getBoolean(KEY_INIT)) {
34-
Logger.i(TAG, "INIT... load AucFrame template")
35-
result.add(Module.getAucModule())
36-
result.add(Module.getAucApp())
37-
result.add(Module.getAucExport())
38-
result.add(Module.getAucPkg())
34+
Logger.i(TAG, "INIT... load sample template")
35+
result.add(Module.getAndroidApplication())
3936
}
4037
if (arr.isNullOrEmpty()) {
4138
return result

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

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import com.intellij.openapi.command.UndoConfirmationPolicy
99
import com.intellij.openapi.command.WriteCommandAction
1010
import com.intellij.openapi.vfs.VirtualFile
1111
import com.intellij.util.ThrowableRunnable
12+
import org.apache.velocity.VelocityContext
13+
import org.apache.velocity.util.StringUtils
1214

1315
/**
1416
* Create file tree.
@@ -21,9 +23,9 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
2123
private val TAG = FileWriteCommand::class.java.simpleName
2224
fun startAction(kit: PluginKit, module: Module) {
2325
WriteCommandAction.writeCommandAction(kit.project)
24-
.withGlobalUndo()
25-
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
26-
.run(FileWriteCommand(kit, module))
26+
.withGlobalUndo()
27+
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
28+
.run(FileWriteCommand(kit, module))
2729
}
2830
}
2931

@@ -39,46 +41,64 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
3941
fileTreeNode.expandPath()
4042
fileTreeNode.expandPkgName(true)
4143

44+
var context: VelocityContext? = null
45+
if (module.enableApacheVelocity) {
46+
context = VelocityContext().apply {
47+
put("StringUtils", StringUtils::class.java)
48+
fileTreeNode.getPlaceholderInherit()?.forEach { (k, v) ->
49+
put(k, v)
50+
}
51+
}
52+
}
53+
4254
val failedList = mutableListOf<FileTreeNode>()
4355
fileTreeNode.children.forEach {
44-
failedList.addAll(createFileTree(it, current))
56+
failedList.addAll(createFileTree(context, it, current))
4557
}
4658
if (failedList.isNotEmpty()) {
4759
val msg = failedList.joinToString("\n") { it.getRealName() }
48-
NotificationUtils.showError(msg, "The following file creation failed.")
60+
NotificationUtils.showError(msg, "The following files creation failed.")
4961
}
5062
}
5163

52-
private fun createFileTree(treeNode: FileTreeNode, currentDirectory: VirtualFile): List<FileTreeNode> {
64+
private fun createFileTree(
65+
context: VelocityContext?,
66+
treeNode: FileTreeNode,
67+
currentDirectory: VirtualFile
68+
): List<FileTreeNode> {
5369
Logger.d(TAG, "create node $treeNode")
5470
val failedList = mutableListOf<FileTreeNode>()
5571
if (treeNode.isDir) {
5672
Logger.d(TAG, "create dir ${treeNode.getPath()}")
57-
val dir = kit.createDir(treeNode.getRealName(), currentDirectory)
73+
val dir = kit.createDir(treeNode.getRealName(context), currentDirectory)
5874
if (dir == null) {
5975
failedList.add(treeNode)
60-
Logger.e(TAG, "create directory failure: ${treeNode.getRealName()}")
76+
Logger.e(TAG, "create directory failure: ${treeNode.getRealName(context)}")
6177
} else {
6278
treeNode.children.forEach {
63-
failedList.addAll(createFileTree(it, dir))
79+
failedList.addAll(createFileTree(context, it, dir))
6480
}
6581
}
6682
} else {
6783
val template = treeNode.getTemplateFile()
6884
if (template?.isNotBlank() == true) {
6985
val result = kit.createFileFromTemplate(
70-
treeNode.getRealName(),
71-
template,
72-
treeNode.getPlaceholderInherit().orEmpty(),
73-
currentDirectory)
86+
treeNode.getRealName(context),
87+
template,
88+
treeNode.getPlaceholderInherit().orEmpty(),
89+
currentDirectory
90+
)
7491
if (result == null || !result.isValid) {
7592
failedList.add(treeNode)
76-
Logger.e(TAG, "create file from template failed, file: ${treeNode.getRealName()} template:$template")
93+
Logger.e(
94+
TAG,
95+
"create file from template failed, file: ${treeNode.getRealName(context)} template:$template"
96+
)
7797
} else {
78-
Logger.d(TAG, "create file from template ${treeNode.getRealName()}")
98+
Logger.d(TAG, "create file from template ${treeNode.getRealName(context)}")
7999
}
80100
} else {
81-
if (!kit.createFile(treeNode.getRealName(), currentDirectory)) {
101+
if (!kit.createFile(treeNode.getRealName(context), currentDirectory)) {
82102
failedList.add(treeNode)
83103
}
84104
Logger.d(TAG, "create file ${treeNode.getPath()}")

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
package com.dengzii.plugin.template.model
44

55
import com.dengzii.plugin.template.utils.Logger
6+
import org.apache.velocity.VelocityContext
7+
import org.apache.velocity.app.Velocity
68
import java.io.File
9+
import java.io.StringWriter
710
import java.util.*
811
import java.util.regex.Pattern
912

@@ -141,17 +144,17 @@ open class FileTreeNode() {
141144
/**
142145
* get the real name replace with placeholder
143146
*/
144-
fun getRealName(): String {
145-
return getRealName(this.name)
147+
fun getRealName(velocityContext: VelocityContext? = null): String {
148+
return getRealNameInternal(velocityContext, this.name)
146149
}
147150

148-
private fun getRealName(fileName: String = this.name): String {
151+
private fun getRealNameInternal(velocityContext: VelocityContext? = null, fileName: String = this.name): String {
149152
return if (isDir) {
150-
val rn = replacePlaceholder(fileName, getPlaceholderInherit(), false)
153+
val rn = replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), false)
151154
if (getModuleInherit()?.lowercaseDir == true) rn.lowercase() else rn
152155
} else {
153156
val capitalize = getModuleInherit()?.capitalizeFile ?: false
154-
replacePlaceholder(fileName, getPlaceholderInherit(), capitalize)
157+
replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), capitalize)
155158
}
156159
}
157160

@@ -422,8 +425,8 @@ open class FileTreeNode() {
422425
*
423426
* @return The tree graph of node
424427
*/
425-
fun getTreeGraph(): String {
426-
return getNodeGraph().toString()
428+
fun getTreeGraph(context: VelocityContext? = null): String {
429+
return getNodeGraph(context).toString()
427430
}
428431

429432
/**
@@ -451,7 +454,11 @@ open class FileTreeNode() {
451454
return null
452455
}
453456

454-
private fun getNodeGraph(head: Stack<String> = Stack(), str: StringBuilder = StringBuilder()): StringBuilder {
457+
private fun getNodeGraph(
458+
context: VelocityContext?,
459+
head: Stack<String> = Stack(),
460+
str: StringBuilder = StringBuilder()
461+
): StringBuilder {
455462

456463
head.forEach {
457464
str.append(it)
@@ -468,13 +475,13 @@ open class FileTreeNode() {
468475
}
469476
}
470477
)
471-
str.append(getRealName())
478+
str.append(getRealName(context))
472479
if (isDir) {
473480
// str.append("\tplaceholder: ").append(placeholders)
474481
}
475482
str.append("\n")
476483

477-
if (!realChildren.isEmpty()) {
484+
if (realChildren.isNotEmpty()) {
478485
head.push(
479486
when {
480487
parent == null -> ""
@@ -483,7 +490,7 @@ open class FileTreeNode() {
483490
}
484491
)
485492
realChildren.forEach {
486-
str.append(it.getNodeGraph(head))
493+
str.append(it.getNodeGraph(context, head))
487494
}
488495
head.pop()
489496
}
@@ -535,10 +542,17 @@ open class FileTreeNode() {
535542
}
536543

537544
private fun replacePlaceholder(
545+
velocityContext: VelocityContext? = null,
538546
origin: String,
539547
placeholders: Map<String, String>?,
540548
capitalize: Boolean = false
541549
): String {
550+
if (velocityContext != null) {
551+
val writer = StringWriter()
552+
Velocity.evaluate(velocityContext, writer, "FileTreeNode", origin)
553+
return writer.toString()
554+
}
555+
542556
var after = origin
543557
if (placeholders.isNullOrEmpty()) {
544558
return origin
@@ -556,7 +570,7 @@ open class FileTreeNode() {
556570
return if (after == origin || !after.contains('$')) {
557571
after
558572
} else {
559-
replacePlaceholder(after, placeholders, capitalize)
573+
replacePlaceholder(velocityContext, after, placeholders, capitalize)
560574
}
561575
}
562576
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ class Module(
1111
var templateName: String,
1212
var lowercaseDir: Boolean = true,
1313
var capitalizeFile: Boolean = true,
14-
var packageNameToDir: Boolean = true
14+
var packageNameToDir: Boolean = true,
15+
var enableApacheVelocity: Boolean = false,
1516
) {
1617

1718
companion object {

src/com/dengzii/plugin/template/ui/ConfigurePanel.form

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@
200200
<text value="Replace placeholder"/>
201201
</properties>
202202
</component>
203+
<component id="a98e" class="javax.swing.JCheckBox" binding="cbEnableVelocity">
204+
<constraints/>
205+
<properties>
206+
<text value="Enable ApacheVelocity (?)"/>
207+
<toolTipText value="Caclculate the file name use ApacheVelocity"/>
208+
</properties>
209+
</component>
203210
</children>
204211
</grid>
205212
</children>

src/com/dengzii/plugin/template/ui/ConfigurePanel.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ public class ConfigurePanel extends JPanel {
2929
JCheckBox cbLowercaseDir;
3030
JCheckBox cbCapitalizeFile;
3131
JCheckBox cbExpandPkgName;
32+
JCheckBox cbEnableVelocity;
3233
}

src/com/dengzii/plugin/template/ui/FileDialog.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ private void initFileTemplateList() {
6666
&& PluginKit.Companion.getFileTemplate(fileNode.getTemplateFile()) != null) {
6767
cbTemplate.setSelectedItem(fileNode.getTemplateFile());
6868
}
69+
cbTemplate.addItemListener(e -> {
70+
if (cbTemplate.getSelectedIndex() == 0 || fileTemplates.length == 0) {
71+
tfName.setText("");
72+
return;
73+
}
74+
FileTemplate selected = fileTemplates[cbTemplate.getSelectedIndex() - 1];
75+
if (selected != null && !selected.getFileName().isBlank()) {
76+
tfName.setText(selected.getFileName() + "." + selected.getExtension());
77+
}
78+
});
6979
}
7080

7181
private void onConfirm() {

src/com/dengzii/plugin/template/ui/PreviewPanel.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.intellij.ui.ColoredTreeCellRenderer
1212
import com.intellij.ui.components.JBCheckBox
1313
import com.intellij.ui.components.JBScrollPane
1414
import com.intellij.ui.treeStructure.Tree
15+
import org.apache.velocity.VelocityContext
1516
import java.awt.BorderLayout
1617
import java.awt.event.KeyAdapter
1718
import java.awt.event.KeyEvent
@@ -34,6 +35,10 @@ class PreviewPanel(preview: Boolean) : JPanel() {
3435
private var onTreeUpdateListener: (() -> Unit)? = null
3536
private var onPlaceholderUpdateListener: (() -> Unit)? = null
3637

38+
private var context: VelocityContext = VelocityContext().apply {
39+
put("StringUtils", org.apache.velocity.util.StringUtils::class.java)
40+
}
41+
3742
// render tree node icon, title
3843
private val treeCellRenderer = object : ColoredTreeCellRenderer() {
3944
override fun customizeCellRenderer(
@@ -43,7 +48,7 @@ class PreviewPanel(preview: Boolean) : JPanel() {
4348
val node = value.userObject
4449
if (node is FileTreeNode) {
4550
val name = if (replacePlaceholder) {
46-
node.getRealName()
51+
node.getRealName(context)
4752
} else {
4853
node.name
4954
}
@@ -94,6 +99,12 @@ class PreviewPanel(preview: Boolean) : JPanel() {
9499
Logger.i("PreviewPanel", "setModuleConfig")
95100
this.module = module
96101
fileTree.model = getTreeModel(this.module.template)
102+
context.apply {
103+
put("StringUtils", org.apache.velocity.util.StringUtils::class.java)
104+
module.template.getPlaceholderInherit()?.forEach {
105+
put(it.key, it.value)
106+
}
107+
}
97108
fileTree.doLayout()
98109
fileTree.updateUI()
99110
expandAll(fileTree, TreePath(fileTree.model.root), true)
@@ -107,7 +118,8 @@ class PreviewPanel(preview: Boolean) : JPanel() {
107118
}
108119

109120
private fun getIconByFileName(fileName: String): Icon {
110-
return FileTypeManager.getInstance().getFileTypeByExtension(fileName.split(".").last()).icon ?: AllIcons.FileTypes.Text
121+
return FileTypeManager.getInstance().getFileTypeByExtension(fileName.split(".").last()).icon
122+
?: AllIcons.FileTypes.Text
111123
}
112124

113125
/**

src/com/dengzii/plugin/template/ui/RealConfigurePanel.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ class RealConfigurePanel : ConfigurePanel() {
121121
currentConfig?.capitalizeFile = cbCapitalizeFile.isSelected
122122
panelPreview.updateTree()
123123
}
124+
cbEnableVelocity.addChangeListener {
125+
currentConfig?.enableApacheVelocity = cbEnableVelocity.isSelected
126+
panelPreview.updateTree()
127+
}
124128
cbExpandPkgName.addChangeListener {
125129
currentConfig?.packageNameToDir = cbExpandPkgName.isSelected
126130
}
@@ -215,6 +219,7 @@ class RealConfigurePanel : ConfigurePanel() {
215219
cbCapitalizeFile.isSelected = capitalizeFile
216220
cbLowercaseDir.isSelected = lowercaseDir
217221
cbExpandPkgName.isSelected = packageNameToDir
222+
cbEnableVelocity.isSelected = enableApacheVelocity
218223
// update tree, file template and placeholder table
219224
panelPreview.setModuleConfig(this)
220225
tableFileTemp.setPairData(template.fileTemplates)

0 commit comments

Comments
 (0)