Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ed8bef2d7 | |||
| 0e67234d2d | |||
| 96340afb0a | |||
| ae3d0c387c | |||
| f8aeb13980 | |||
| fd23d0b19c | |||
| 438d7f03a8 | |||
| ca49a5a8d5 | |||
| 80ba97abac | |||
| 524efaf199 | |||
| b521520965 | |||
| f383e397e6 | |||
| 6d52f12b68 | |||
| e0e7327b15 | |||
| d47039d7b9 | |||
| 82b9694552 |
|
|
@ -26,10 +26,8 @@ tasks.getByName<org.jetbrains.intellij.tasks.PatchPluginXmlTask>("patchPluginXml
|
|||
<h3>[1.2]</h3>
|
||||
|
||||
<ul>
|
||||
<li>Single New menu action to access filename template configurations</li>
|
||||
<li>Simplify template configuration with placeholder auto completion</li>
|
||||
<li>New templates are active by default</li>
|
||||
<li>Combine name and description into title</li>
|
||||
</ul>
|
||||
|
||||
<h3>[1.1]</h3>
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
|
|
@ -1,4 +1,4 @@
|
|||
kotlin.code.style=official
|
||||
|
||||
pluginVersion = 1.2.0-211
|
||||
platformVersion = 2021.1
|
||||
pluginVersion = 1.2.0-182
|
||||
platformVersion = 2018.2
|
||||
|
|
|
|||
|
|
@ -3,121 +3,30 @@ package de.idetools.filename_template
|
|||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.ide.actions.CreateFileAction
|
||||
import com.intellij.ide.ui.newItemPopup.NewItemPopupUtil
|
||||
import com.intellij.lang.LangBundle
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.InputValidatorEx
|
||||
import com.intellij.openapi.util.Trinity
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiElement
|
||||
import de.idetools.filename_template.placeholders.*
|
||||
import de.idetools.filename_template.settings.FilenameTemplateSettingsState
|
||||
import java.awt.event.InputEvent
|
||||
import java.util.function.Consumer
|
||||
import kotlin.math.max
|
||||
import de.idetools.filename_template.placeholders.PlaceholderProcessor
|
||||
|
||||
class CreateFileWithFilenameTemplateAction :
|
||||
CreateFileAction("Filename Template", "Create a new file based on template", AllIcons.Actions.AddFile) {
|
||||
class CreateFileWithFilenameTemplateAction(
|
||||
text: String,
|
||||
description: String,
|
||||
private val placeholderProcessor: PlaceholderProcessor
|
||||
) :
|
||||
CreateFileAction(text, description, AllIcons.FileTypes.Unknown) {
|
||||
|
||||
private val placeholders: List<Placeholder> = listOf(
|
||||
EpochPlaceholder(),
|
||||
DatePlaceholder(),
|
||||
ProjectPlaceholder(),
|
||||
SequencePlaceholder(),
|
||||
HostPlaceholder(),
|
||||
UserPlaceholder(),
|
||||
DefaultPlaceholder()
|
||||
)
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
if (FilenameTemplateSettingsState.instance.filenameTemplates.isEmpty()) {
|
||||
e.presentation.isEnabledAndVisible = false
|
||||
} else {
|
||||
super.update(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invokeDialog(
|
||||
project: Project,
|
||||
directory: PsiDirectory,
|
||||
elementsConsumer: Consumer<Array<PsiElement?>?>
|
||||
) {
|
||||
val settings: FilenameTemplateSettingsState = FilenameTemplateSettingsState.instance
|
||||
settings.filenameTemplates.forEach {
|
||||
if (it.title.isBlank()) {
|
||||
it.title = if (it.description.isBlank()) it.name else "${it.name} - ${it.description}"
|
||||
}
|
||||
it.name = ""
|
||||
it.description = ""
|
||||
}
|
||||
|
||||
val templates = settings.filenameTemplates
|
||||
.filter { it.isActive }
|
||||
.map {
|
||||
Trinity(it.title, AllIcons.Actions.AddFile, processTemplate(it.template, project, directory))
|
||||
}
|
||||
override fun invokeDialog(project: Project, directory: PsiDirectory): Array<PsiElement> {
|
||||
val validator: MyInputValidator = MyValidator(project, directory)
|
||||
val contentPanel = CreateWithFilenameTemplateDialogPanel(templates)
|
||||
val nameField = contentPanel.textField
|
||||
val popup = NewItemPopupUtil.createNewItemPopup(IdeBundle.message("title.new.file"), contentPanel, nameField)
|
||||
|
||||
contentPanel.setApplyAction { event: InputEvent? ->
|
||||
val name = nameField.text
|
||||
if (validator.checkInput(name) && validator.canClose(name)) {
|
||||
popup.closeOk(event)
|
||||
elementsConsumer.accept(validator.createdElements)
|
||||
} else {
|
||||
val errorMessage =
|
||||
if (validator is InputValidatorEx)
|
||||
(validator as InputValidatorEx).getErrorText(name)
|
||||
else
|
||||
LangBundle.message("incorrect.name")
|
||||
contentPanel.setError(errorMessage)
|
||||
}
|
||||
}
|
||||
popup.showCenteredInCurrentWindow(project)
|
||||
}
|
||||
|
||||
private fun processTemplate(template: String, project: Project, directory: PsiDirectory): String {
|
||||
var placeholderLevel = 0
|
||||
var placeholder = ""
|
||||
|
||||
val context = PlaceholderContext(project, directory)
|
||||
|
||||
for (character in template) {
|
||||
when (character) {
|
||||
'{' -> {
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
}
|
||||
|
||||
placeholderLevel += 1
|
||||
}
|
||||
'}' -> {
|
||||
if (placeholderLevel == 1) {
|
||||
context.filename += placeholders
|
||||
.first { it.supports(placeholder) }
|
||||
.process(placeholder, context)
|
||||
placeholder = ""
|
||||
}
|
||||
|
||||
placeholderLevel = max(0, placeholderLevel - 1)
|
||||
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
} else {
|
||||
context.filename += character
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return context.filename
|
||||
val processedTemplate = placeholderProcessor.processTemplate(project, directory)
|
||||
Messages.showInputDialog(
|
||||
project,
|
||||
IdeBundle.message("prompt.enter.new.file.name"),
|
||||
IdeBundle.message("title.new.file"),
|
||||
null,
|
||||
processedTemplate.filename,
|
||||
validator
|
||||
)
|
||||
return validator.createdElements
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
package de.idetools.filename_template
|
||||
|
||||
import com.intellij.ide.actions.newclass.CreateWithTemplatesDialogPanel
|
||||
import com.intellij.openapi.util.Trinity
|
||||
import javax.swing.Icon
|
||||
|
||||
class CreateWithFilenameTemplateDialogPanel(templates: List<Trinity<String, Icon, String>>) :
|
||||
CreateWithTemplatesDialogPanel(templates, templates.first().first) {
|
||||
|
||||
init {
|
||||
updateSelectedText()
|
||||
myTemplatesList.addListSelectionListener { updateSelectedText() }
|
||||
}
|
||||
|
||||
private fun updateSelectedText() {
|
||||
val selectedValue = myTemplatesList.selectedValue
|
||||
if (selectedValue != null) {
|
||||
var filename = selectedValue.third
|
||||
val caretPosition = determineCaretPosition(filename)
|
||||
filename = filename.replace("{|}", "")
|
||||
|
||||
myTextField.text = filename
|
||||
nameField.caretPosition = caretPosition
|
||||
}
|
||||
}
|
||||
|
||||
private fun determineCaretPosition(filename: String): Int = when {
|
||||
filename.indexOf("{|}") != -1 -> filename.indexOf("{|}")
|
||||
filename.indexOfFirst { it == '.' } != -1 -> filename.indexOfFirst { it == '.' }
|
||||
else -> filename.length
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package de.idetools.filename_template
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager
|
||||
import com.intellij.openapi.actionSystem.Anchor
|
||||
import com.intellij.openapi.actionSystem.Constraints
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.StartupActivity
|
||||
import de.idetools.filename_template.placeholders.DatePlaceholder
|
||||
import de.idetools.filename_template.placeholders.DefaultPlaceholder
|
||||
import de.idetools.filename_template.placeholders.EpochPlaceholder
|
||||
import de.idetools.filename_template.placeholders.HostPlaceholder
|
||||
import de.idetools.filename_template.placeholders.PlaceholderProcessor
|
||||
import de.idetools.filename_template.placeholders.ProjectPlaceholder
|
||||
import de.idetools.filename_template.placeholders.SequencePlaceholder
|
||||
import de.idetools.filename_template.placeholders.UserPlaceholder
|
||||
import de.idetools.filename_template.settings.FilenameTemplateSettingsState
|
||||
|
||||
class InitializeFilenameTemplateActivity : StartupActivity {
|
||||
override fun runActivity(project: Project) {
|
||||
initializeActions()
|
||||
}
|
||||
|
||||
internal fun initializeActions() {
|
||||
val settings: FilenameTemplateSettingsState = FilenameTemplateSettingsState.instance
|
||||
|
||||
val placeholders = listOf(
|
||||
EpochPlaceholder(),
|
||||
DatePlaceholder(),
|
||||
ProjectPlaceholder(),
|
||||
HostPlaceholder(),
|
||||
SequencePlaceholder(),
|
||||
UserPlaceholder(),
|
||||
DefaultPlaceholder()
|
||||
)
|
||||
|
||||
val actionManager = ActionManager.getInstance()
|
||||
val newGroup = actionManager.getAction("NewGroup") as DefaultActionGroup
|
||||
|
||||
actionManager.getActionIds("FilenameTemplate").forEach {
|
||||
newGroup.remove(actionManager.getAction(it))
|
||||
actionManager.unregisterAction(it)
|
||||
}
|
||||
|
||||
var anchorId = "NewFile"
|
||||
settings.filenameTemplates.filter { it.isActive }.forEach {
|
||||
val action = CreateFileWithFilenameTemplateAction(
|
||||
it.name,
|
||||
it.description,
|
||||
PlaceholderProcessor(it.template, placeholders)
|
||||
)
|
||||
val actionId = "FilenameTemplate.${it.name}"
|
||||
actionManager.registerAction(actionId, action)
|
||||
newGroup.addAction(action, Constraints(Anchor.AFTER, anchorId))
|
||||
anchorId = actionId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package de.idetools.filename_template.placeholders
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import kotlin.math.max
|
||||
|
||||
class PlaceholderProcessor(private val template: String, private val placeholders: List<Placeholder>) {
|
||||
|
||||
fun processTemplate(project: Project, directory: PsiDirectory): ProcessedTemplate {
|
||||
var placeholderLevel = 0
|
||||
var placeholder = ""
|
||||
|
||||
val context = PlaceholderContext(project, directory)
|
||||
|
||||
for (character in template) {
|
||||
when (character) {
|
||||
'{' -> {
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
}
|
||||
|
||||
placeholderLevel += 1
|
||||
}
|
||||
'}' -> {
|
||||
if (placeholderLevel == 1) {
|
||||
context.filename += placeholders
|
||||
.first { it.supports(placeholder) }
|
||||
.process(placeholder, context)
|
||||
placeholder = ""
|
||||
}
|
||||
|
||||
placeholderLevel = max(0, placeholderLevel - 1)
|
||||
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (0 < placeholderLevel) {
|
||||
placeholder += character
|
||||
} else {
|
||||
context.filename += character
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val caretPosition = when {
|
||||
context.filename.indexOf("{|}") != -1 -> context.filename.indexOf("{|}")
|
||||
context.filename.indexOfFirst { it == '.' } != -1 -> context.filename.indexOfFirst { it == '.' }
|
||||
else -> context.filename.length
|
||||
}
|
||||
context.filename = context.filename.replace("{|}", "")
|
||||
|
||||
return ProcessedTemplate(context.filename, caretPosition)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package de.idetools.filename_template.settings
|
|||
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.options.ConfigurationException
|
||||
import de.idetools.filename_template.InitializeFilenameTemplateActivity
|
||||
import org.jetbrains.annotations.Nls
|
||||
import javax.swing.JComponent
|
||||
|
||||
|
|
@ -11,16 +12,8 @@ class FilenameTemplateConfigurable : Configurable {
|
|||
|
||||
init {
|
||||
val settings: FilenameTemplateSettingsState = FilenameTemplateSettingsState.instance
|
||||
settings.filenameTemplates.forEach {
|
||||
if (it.title.isBlank()) {
|
||||
it.title = if (it.description.isBlank()) it.name else "${it.name} - ${it.description}"
|
||||
}
|
||||
it.name = ""
|
||||
it.description = ""
|
||||
}
|
||||
|
||||
component = FilenameTemplateSettingsComponent(ArrayList(settings.filenameTemplates.map {
|
||||
FilenameTemplateModel(it.isActive, it.title, it.name, it.description, it.template)
|
||||
FilenameTemplateModel(it.isActive, it.name, it.description, it.template)
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -39,8 +32,9 @@ class FilenameTemplateConfigurable : Configurable {
|
|||
return settings.filenameTemplates.size != component.filenameTemplates.size ||
|
||||
settings.filenameTemplates.withIndex().any {
|
||||
component.filenameTemplateTable.getValueAt(it.index, 0) != it.value.isActive
|
||||
|| component.filenameTemplateTable.getValueAt(it.index, 1) != it.value.title
|
||||
|| component.filenameTemplateTable.getValueAt(it.index, 2) != it.value.template
|
||||
|| component.filenameTemplateTable.getValueAt(it.index, 1) != it.value.name
|
||||
|| component.filenameTemplateTable.getValueAt(it.index, 2) != it.value.description
|
||||
|| component.filenameTemplateTable.getValueAt(it.index, 3) != it.value.template
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,12 +45,12 @@ class FilenameTemplateConfigurable : Configurable {
|
|||
settings.filenameTemplates.addAll(component.filenameTemplates.map {
|
||||
FilenameTemplateModel(
|
||||
it.isActive,
|
||||
it.title,
|
||||
it.name,
|
||||
it.description,
|
||||
it.template
|
||||
)
|
||||
})
|
||||
InitializeFilenameTemplateActivity().initializeActions()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
|
|
@ -65,7 +59,6 @@ class FilenameTemplateConfigurable : Configurable {
|
|||
component.filenameTemplates.addAll(settings.filenameTemplates.map {
|
||||
FilenameTemplateModel(
|
||||
it.isActive,
|
||||
it.title,
|
||||
it.name,
|
||||
it.description,
|
||||
it.template
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package de.idetools.filename_template.settings
|
|||
|
||||
data class FilenameTemplateModel(
|
||||
var isActive: Boolean = true,
|
||||
var title: String = "",
|
||||
var name: String = "",
|
||||
var description: String = "",
|
||||
var template: String = ""
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class FilenameTemplateSettingsComponent(val filenameTemplates: ArrayList<Filenam
|
|||
activeColumn.resizable = false
|
||||
activeColumn.maxWidth = determineRequiredWidth(activeColumn)
|
||||
|
||||
val templateColumn = filenameTemplateTable.columnModel.getColumn(2)
|
||||
val templateColumn = filenameTemplateTable.columnModel.getColumn(3)
|
||||
templateColumn.cellEditor = PlaceholderCompletionCellEditor()
|
||||
|
||||
val filenameTemplateTableScrollPane = JBScrollPane(filenameTemplateTable)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import javax.swing.table.AbstractTableModel
|
|||
|
||||
class FilenameTemplateTableModel(private val filenameTemplates: ArrayList<FilenameTemplateModel>) :
|
||||
AbstractTableModel() {
|
||||
private val header: List<String> = listOf("Active", "Title", "Template")
|
||||
private val header: List<String> = listOf("Active", "Name", "Description", "Template")
|
||||
|
||||
override fun getRowCount(): Int = filenameTemplates.size
|
||||
|
||||
|
|
@ -14,8 +14,9 @@ class FilenameTemplateTableModel(private val filenameTemplates: ArrayList<Filena
|
|||
override fun getValueAt(row: Int, column: Int): Any {
|
||||
return when (column) {
|
||||
0 -> filenameTemplates[row].isActive
|
||||
1 -> filenameTemplates[row].title
|
||||
2 -> filenameTemplates[row].template
|
||||
1 -> filenameTemplates[row].name
|
||||
2 -> filenameTemplates[row].description
|
||||
3 -> filenameTemplates[row].template
|
||||
else -> throw ArrayIndexOutOfBoundsException()
|
||||
}
|
||||
}
|
||||
|
|
@ -23,8 +24,9 @@ class FilenameTemplateTableModel(private val filenameTemplates: ArrayList<Filena
|
|||
override fun setValueAt(value: Any?, row: Int, column: Int) {
|
||||
when (column) {
|
||||
0 -> filenameTemplates[row].isActive = value as Boolean
|
||||
1 -> filenameTemplates[row].title = value as String
|
||||
2 -> filenameTemplates[row].template = value as String
|
||||
1 -> filenameTemplates[row].name = value as String
|
||||
2 -> filenameTemplates[row].description = value as String
|
||||
3 -> filenameTemplates[row].template = value as String
|
||||
else -> throw ArrayIndexOutOfBoundsException()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
<ol>
|
||||
<li>Settings -> Tools -> Filename Template</li>
|
||||
<li>Configure filename templates</li>
|
||||
<li>Create new file: New -> Filename Template</li>
|
||||
<li>Choose filename template</li>
|
||||
<li>Create new file: New -> <i>Template name</i></li>
|
||||
<li>Complete the file name with return</li>
|
||||
</ol>
|
||||
|
||||
|
|
@ -22,10 +21,13 @@
|
|||
|
||||
<dl>
|
||||
<dt>Active</dt>
|
||||
<dd>Only active filename templates are available in the template selection list.</dd>
|
||||
<dd>Only active filename templates will be shown in the menu.</dd>
|
||||
|
||||
<dt>Title</dt>
|
||||
<dd>The title is displayed in the template selection list below the file name input field.</dd>
|
||||
<dt>Name</dt>
|
||||
<dd>The name will be shown in the menu.</dd>
|
||||
|
||||
<dt>Description</dt>
|
||||
<dd>The description will be shown in the status bar when hovering the menu entry.</dd>
|
||||
|
||||
<dt>Template</dt>
|
||||
<dd>
|
||||
|
|
@ -90,13 +92,11 @@
|
|||
instance="de.idetools.filename_template.settings.FilenameTemplateConfigurable"
|
||||
id="de.idetools.filename_template.settings.FilenameTemplateConfigurable"
|
||||
displayName="Filename Template"/>
|
||||
<postStartupActivity
|
||||
implementation="de.idetools.filename_template.InitializeFilenameTemplateActivity"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
<action id="de.idetools.filename_template.CreateFileWithFilenameTemplateAction"
|
||||
class="de.idetools.filename_template.CreateFileWithFilenameTemplateAction" text="NewFilenameTemplate"
|
||||
description="Create a new file based on a filename template" icon="/META-INF/pluginIcon-small.png">
|
||||
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewFile"/>
|
||||
</action>
|
||||
<!-- Add your actions here -->
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 369 B |
Binary file not shown.
|
Before Width: | Height: | Size: 365 B |
Loading…
Reference in New Issue
Block a user