Merge branch 'idea-193' into idea-192
This commit is contained in:
commit
f383e397e6
|
|
@ -23,6 +23,12 @@ intellij {
|
||||||
}
|
}
|
||||||
tasks.getByName<org.jetbrains.intellij.tasks.PatchPluginXmlTask>("patchPluginXml") {
|
tasks.getByName<org.jetbrains.intellij.tasks.PatchPluginXmlTask>("patchPluginXml") {
|
||||||
changeNotes("""
|
changeNotes("""
|
||||||
|
<h3>[1.1]</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Placeholders for: date, hostname, project name, username, sequential numbers, and caret position</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h3>[1.0]</h3>
|
<h3>[1.0]</h3>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
|
||||||
pluginVersion = 1.0.0-192
|
pluginVersion = 1.1.0-192
|
||||||
platformVersion = 2019.2
|
platformVersion = 2019.2
|
||||||
|
|
|
||||||
|
|
@ -7,31 +7,26 @@ import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.Messages
|
import com.intellij.openapi.ui.Messages
|
||||||
import com.intellij.psi.PsiDirectory
|
import com.intellij.psi.PsiDirectory
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import java.time.LocalDateTime
|
import de.idetools.filename_template.placeholders.PlaceholderProcessor
|
||||||
import java.time.ZoneOffset
|
|
||||||
|
|
||||||
class CreateFileWithFilenameTemplateAction(
|
class CreateFileWithFilenameTemplateAction(
|
||||||
text: String,
|
text: String,
|
||||||
description: String,
|
description: String,
|
||||||
private val template: String
|
private val placeholderProcessor: PlaceholderProcessor
|
||||||
) :
|
) :
|
||||||
CreateFileAction(text, description, AllIcons.FileTypes.Unknown) {
|
CreateFileAction(text, description, AllIcons.FileTypes.Unknown) {
|
||||||
|
|
||||||
override fun invokeDialog(project: Project?, directory: PsiDirectory?): Array<PsiElement> {
|
override fun invokeDialog(project: Project, directory: PsiDirectory): Array<PsiElement> {
|
||||||
val validator: MyInputValidator = MyValidator(project, directory)
|
val validator: MyInputValidator = MyValidator(project, directory)
|
||||||
|
val processedTemplate = placeholderProcessor.processTemplate(project, directory)
|
||||||
Messages.showInputDialog(
|
Messages.showInputDialog(
|
||||||
project,
|
project,
|
||||||
IdeBundle.message("prompt.enter.new.file.name"),
|
IdeBundle.message("prompt.enter.new.file.name"),
|
||||||
IdeBundle.message("title.new.file"),
|
IdeBundle.message("title.new.file"),
|
||||||
null,
|
null,
|
||||||
processTemplate(template),
|
processedTemplate.filename,
|
||||||
validator
|
validator
|
||||||
)
|
)
|
||||||
return validator.createdElements
|
return validator.createdElements
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processTemplate(template: String): String {
|
|
||||||
val epoch = LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC)
|
|
||||||
return template.replace("{EPOCH}", epoch.toString())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,14 @@ import com.intellij.openapi.actionSystem.Constraints
|
||||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.startup.StartupActivity
|
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
|
import de.idetools.filename_template.settings.FilenameTemplateSettingsState
|
||||||
|
|
||||||
class InitializeFilenameTemplateActivity : StartupActivity {
|
class InitializeFilenameTemplateActivity : StartupActivity {
|
||||||
|
|
@ -16,6 +24,16 @@ class InitializeFilenameTemplateActivity : StartupActivity {
|
||||||
internal fun initializeActions() {
|
internal fun initializeActions() {
|
||||||
val settings: FilenameTemplateSettingsState = FilenameTemplateSettingsState.instance
|
val settings: FilenameTemplateSettingsState = FilenameTemplateSettingsState.instance
|
||||||
|
|
||||||
|
val placeholders = listOf(
|
||||||
|
EpochPlaceholder(),
|
||||||
|
DatePlaceholder(),
|
||||||
|
ProjectPlaceholder(),
|
||||||
|
HostPlaceholder(),
|
||||||
|
SequencePlaceholder(),
|
||||||
|
UserPlaceholder(),
|
||||||
|
DefaultPlaceholder()
|
||||||
|
)
|
||||||
|
|
||||||
val actionManager = ActionManager.getInstance()
|
val actionManager = ActionManager.getInstance()
|
||||||
val newGroup = actionManager.getAction("NewGroup") as DefaultActionGroup
|
val newGroup = actionManager.getAction("NewGroup") as DefaultActionGroup
|
||||||
|
|
||||||
|
|
@ -29,7 +47,7 @@ class InitializeFilenameTemplateActivity : StartupActivity {
|
||||||
val action = CreateFileWithFilenameTemplateAction(
|
val action = CreateFileWithFilenameTemplateAction(
|
||||||
it.name,
|
it.name,
|
||||||
it.description,
|
it.description,
|
||||||
it.template
|
PlaceholderProcessor(it.template, placeholders)
|
||||||
)
|
)
|
||||||
val actionId = "FilenameTemplate.${it.name}"
|
val actionId = "FilenameTemplate.${it.name}"
|
||||||
actionManager.registerAction(actionId, action)
|
actionManager.registerAction(actionId, action)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
class DatePlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder.startsWith("DATE")
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String {
|
||||||
|
val date = LocalDateTime.now()
|
||||||
|
val datePattern = placeholder.substringAfter(":", "")
|
||||||
|
val formatter =
|
||||||
|
if (datePattern.isBlank()) {
|
||||||
|
DateTimeFormatter.ISO_DATE
|
||||||
|
} else {
|
||||||
|
DateTimeFormatter.ofPattern(datePattern)
|
||||||
|
}
|
||||||
|
return date.format(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
class DefaultPlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = true
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String =
|
||||||
|
"{$placeholder}"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
|
class EpochPlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder == "EPOCH"
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String =
|
||||||
|
LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC).toString()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
import java.net.InetAddress
|
||||||
|
|
||||||
|
class HostPlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder == "HOST"
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String =
|
||||||
|
InetAddress.getLocalHost().hostName
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
interface Placeholder {
|
||||||
|
fun supports(placeholder: String): Boolean
|
||||||
|
fun process(placeholder: String, context: PlaceholderContext): String
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiDirectory
|
||||||
|
|
||||||
|
data class PlaceholderContext(
|
||||||
|
val project: Project,
|
||||||
|
val directory: PsiDirectory,
|
||||||
|
var filename: String = ""
|
||||||
|
)
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
data class ProcessedTemplate(
|
||||||
|
val filename: String,
|
||||||
|
val caretPosition: Int
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
class ProjectPlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder == "PROJECT"
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String =
|
||||||
|
context.project.name
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
|
||||||
|
class SequencePlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder.matches("^\\d+$".toRegex())
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String {
|
||||||
|
var value = Integer.parseInt(placeholder)
|
||||||
|
while (sequenceValueExists(context.directory.files, context.filename + formatSequence(value, placeholder.length))) {
|
||||||
|
value++
|
||||||
|
}
|
||||||
|
return formatSequence(value, placeholder.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sequenceValueExists(files: Array<PsiFile>, sequence: String): Boolean {
|
||||||
|
return files.any { it.name.startsWith(sequence) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatSequence(value: Int, length: Int) =
|
||||||
|
value.toString().padStart(length, '0')
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package de.idetools.filename_template.placeholders
|
||||||
|
|
||||||
|
class UserPlaceholder : Placeholder {
|
||||||
|
override fun supports(placeholder: String): Boolean = placeholder == "USER"
|
||||||
|
|
||||||
|
override fun process(placeholder: String, context: PlaceholderContext): String =
|
||||||
|
System.getProperty("user.name")
|
||||||
|
}
|
||||||
|
|
@ -35,8 +35,38 @@
|
||||||
<br/>
|
<br/>
|
||||||
<p>A template might contain following place holders:</p>
|
<p>A template might contain following place holders:</p>
|
||||||
<dl>
|
<dl>
|
||||||
|
<dt>{DATE:FORMAT}</dt>
|
||||||
|
<dd>
|
||||||
|
The formatted date. If the format is omitted "yyyy-MM-dd" is used by default.<br />
|
||||||
|
See the java documentation for supported patterns: <a href="https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/time/format/DateTimeFormatter.html">Patterns for Formatting and Parsing</a>
|
||||||
|
</dd>
|
||||||
|
|
||||||
<dt>{EPOCH}</dt>
|
<dt>{EPOCH}</dt>
|
||||||
<dd>The current unix time stamp: Seconds since the Unix Epoch on January 1st, 1970 at UTC.</dd>
|
<dd>The current unix time stamp: Seconds since the Unix Epoch on January 1st, 1970 at UTC.</dd>
|
||||||
|
|
||||||
|
<dt>{HOST}</dt>
|
||||||
|
<dd>
|
||||||
|
The computers hostname.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>{PROJECT}</dt>
|
||||||
|
<dd>
|
||||||
|
The name of the current project.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>{USER}</dt>
|
||||||
|
<dd>
|
||||||
|
The username of the user running the IDE.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>{###}</dt>
|
||||||
|
<dd>
|
||||||
|
The first available sequential number. Define the initial value and desired leading zeros in the template.
|
||||||
|
Example: notes({042}).md => notes(042).md, notes(043).md, ...
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>{|}</dt>
|
||||||
|
<dd>The caret position. If omitted the caret is positioned before the first '.' if available or at the end.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user