Add templating script #11

Open
InsanusMokrassar wants to merge 1 commits from feature/templating_kts into dev
4 changed files with 230 additions and 1 deletions
Showing only changes of commit 8ce34cfd6e - Show all commits

View File

@ -226,3 +226,48 @@ the current time. The device is configurable via a simple TornadoFX-based contro
You can run a demo by executing `application/run` Gradle task. You can run a demo by executing `application/run` Gradle task.
The graphs are displayed using [plotly.kt](https://github.com/mipt-npm/plotly.kt) library. The graphs are displayed using [plotly.kt](https://github.com/mipt-npm/plotly.kt) library.
## Templates
**This feature required `kotlin` to be installed in your system. [Read more](https://kotlinlang.org/docs/command-line.html#install-the-compiler)**
**You may run gradle task `generateKTStemplates` instead of raw launch, but it will work slowly. Sample `./gradlew generateKTStemplates`**
This project supports generating of files from `.ktstemplate.` files. Current docs:
### Using
* Create file contains `.ktstemplate` in its name
* Write variables **before** the first `H*` (starting with `#`) section
* Launch `kotlin ${thisscriptname}` with required args
#### File sample
```markdown
first = hello
second = world
# Sample
This is sample of $first $second
```
Will have next result:
```markdown
# Sample
This is sample of hello world
```
### Launch
This script accept next args:
`[...paths] [--plain] [--recursive]`
Where:
* `...paths` - Paths to the files-templates or folders with files-templates
* `--plain` - will look only into the folders from `paths`
* `--recursive` - (default) will look into the folders from `paths` and recursively in subfolders

View File

@ -22,4 +22,12 @@ ksciencePublish {
sonatype("https://oss.sonatype.org") sonatype("https://oss.sonatype.org")
} }
readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md") readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
task("generateKTStemplates") {
doLast {
exec {
commandLine("kotlin", "ktstemplate_generator.kts")
}
}
}

View File

@ -0,0 +1,25 @@
package_group=space.kscience
package_name=controls-constructor
maven_url=https://maven.sciprog.center
# Module controls-constructor
A low-code constructor for composite devices simulation
## Usage
## Artifact:
The Maven coordinates of this project are `$package_group:$package_name:0.3.0`.
**Gradle Kotlin DSL:**
```kotlin
repositories {
maven("https://repo.kotlin.link")
mavenCentral()
}
dependencies {
implementation("$package_group:$package_name:0.3.0")
}
```

151
ktstemplate_generator.kts Normal file
View File

@ -0,0 +1,151 @@
/**
* # Generating files from templates script
*
* ## Using
*
* * Create file contains `.ktstemplate` in its name
* * Write variables **before** the first H* (starting with `#`) section
* * Launch `kotlin ${thisscriptname}` with required args
*
* ### File sample
*
* ```markdown
* first = hello
* second = world
*
* # Sample
*
* This is sample of $first $second
* ```
*
* Will have next result:
*
* ```markdown
* # Sample
*
* This is sample of hello world
* ```
*
* ## Launch
*
* This script accept next args:
*
* `[...paths] [--plain] [--recursive]`
*
* Where:
*
* * `...paths` - Paths to the files-templates or folders with files-templates
* * `--plain` - will look only into the folders from `paths`
* * `--recursive` - (default) will look into the folders from `paths` and recursively in subfolders
*/
import kotlin.collections.LinkedHashSet
import java.io.File
val templateEnding = Regex("\\.ktstemplate(\\.[^\\.]*)*$")
val templateOnlyEnding = Regex("\\.ktstemplate")
val singleArgumentRegex = Regex("^[\\w\\d]+$")
val splitterRegex = Regex("[ ]*=[ ]*")
sealed interface Mode {
fun filesList(folder: File): Sequence<File>
data object Recursive : Mode {
override fun filesList(folder: File): Sequence<File> {
return sequence {
val folders = mutableListOf<File>()
folders.add(folder)
while (folders.isNotEmpty()) {
val currentFolder = folders.removeAt(0)
currentFolder.listFiles().toList().forEach {
when {
it.isFile -> yield(it)
it.isDirectory -> folders.add(it)
}
}
}
}
}
}
data object Plain : Mode {
override fun filesList(folder: File): Sequence<File> {
return sequence {
folder.listFiles().forEach {
yield(it)
}
}
}
}
}
var mode: Mode = Mode.Recursive
val folders = args.mapNotNull {
if (it.startsWith("-")) { // assume some arg
when (it) {
"--plain" -> mode = Mode.Plain
"--recursive" -> mode = Mode.Recursive
"--help" -> {
println("[...pathnames] [--recursive] [--plain]")
println("...pathnames - Pass any count of folder or files paths")
println("--recursive - (default) Use recursive visiting of folders for each path in pathnames")
println("--plain - (default) Use plain (non-recursive) visiting of folders for each path in pathnames")
}
}
null
} else {
File(it)
}
}.ifEmpty {
listOf(File("./"))
}
fun String.replaceVariables(variables: Map<String, String>): String {
var currentLine = this
variables.forEach { (k, v) ->
currentLine = currentLine.replace("\${${k}}", v)
if (k.matches(singleArgumentRegex)) {
currentLine = currentLine.replace("\$${k}", v)
}
}
return currentLine
}
fun generateFromTemplate(folder: File, file: File) {
val targetFile = File(folder, file.name.replace(templateOnlyEnding, ""))
val variables = mutableMapOf<String, String>()
var writeVariables = true
var text = ""
file.readLines().forEach { line ->
when {
writeVariables && line.startsWith("#") -> {
writeVariables = false
}
writeVariables -> {
val splitted = line.split(splitterRegex)
if (splitted.size > 1) {
val k = splitted[0]
val v = splitted[1].replaceVariables(variables)
variables[k] = v
}
return@forEach
}
}
text += line.let {
line.replaceVariables(variables) + "\n"
}
}
targetFile.writeText(text)
println("${targetFile.absolutePath} has been recreated")
}
if (args.none { it == "--help" }) {
folders.forEach { folder ->
mode.filesList(folder).forEach { file ->
if (file.name.contains(templateEnding)) {
generateFromTemplate(file.parentFile, file)
}
}
}
}