87 lines
3.0 KiB
Kotlin
87 lines
3.0 KiB
Kotlin
package scaffold.commands
|
|
|
|
import com.github.ajalt.clikt.core.CliktCommand
|
|
import com.github.ajalt.clikt.core.ProgramResult
|
|
import com.github.ajalt.clikt.parameters.arguments.argument
|
|
import com.github.ajalt.clikt.parameters.options.convert
|
|
import com.github.ajalt.clikt.parameters.options.option
|
|
import com.github.ajalt.clikt.parameters.options.required
|
|
import com.mitchellbosecke.pebble.PebbleEngine
|
|
import com.mitchellbosecke.pebble.loader.FileLoader
|
|
import com.mitchellbosecke.pebble.template.PebbleTemplate
|
|
import scaffold.Generator
|
|
import scaffold.Generators
|
|
import scaffold.PromptType
|
|
import scaffold.loadConfig
|
|
import java.io.StringWriter
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
|
|
class GenerateCommand(private val generators: Generators) : CliktCommand("generate") {
|
|
private val name by argument(help = "generator name")
|
|
private val output by option().convert { Path.of(it) }.required()
|
|
|
|
override fun run() {
|
|
checkPreconditions()
|
|
|
|
val generator = Generator(generators.configDirectory, name)
|
|
val config = generator.loadConfig()
|
|
|
|
val templateContext = mutableMapOf<String, Any?>()
|
|
|
|
for ((path, prompts) in config.prompts) {
|
|
val map = mutableMapOf<String, Any>()
|
|
templateContext[path] = map
|
|
for ((name, info, default, type) in prompts) {
|
|
if (type != PromptType.String) TODO()
|
|
|
|
val value = prompt(
|
|
text = info ?: "$path.$name",
|
|
default = default
|
|
)!!
|
|
map[name] = value
|
|
}
|
|
}
|
|
|
|
val pebble = PebbleEngine.Builder()
|
|
.autoEscaping(false)
|
|
.newLineTrimming(false)
|
|
.loader(FileLoader().apply { prefix = generator.treeRoot.toString() })
|
|
.build()!!
|
|
|
|
for (template in config.templates) {
|
|
val templatePath = generator.treeRoot.relativize(template).toString()
|
|
val renderedTemplate = pebble.getTemplate(templatePath)(templateContext)
|
|
val outputPath = output.resolve(templatePath)
|
|
Files.createDirectories(outputPath.parent)
|
|
Files.writeString(outputPath, renderedTemplate)
|
|
}
|
|
|
|
for (inputFile in config.files) {
|
|
val relativeFile = generator.treeRoot.relativize(inputFile)
|
|
val outputFile = output.resolve(relativeFile)
|
|
|
|
Files.createDirectories(outputFile.parent)
|
|
Files.copy(inputFile, outputFile)
|
|
}
|
|
|
|
echo("Generated project in $output")
|
|
}
|
|
|
|
private fun checkPreconditions() {
|
|
if (Files.exists(output)) {
|
|
if (Files.list(output).findAny().isPresent) {
|
|
echo("Output path `$output` is not empty")
|
|
throw ProgramResult(1)
|
|
}
|
|
}
|
|
|
|
if (!generators.isValid(name)) {
|
|
echo("Generator not found")
|
|
throw ProgramResult(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
operator fun PebbleTemplate.invoke(context: Map<String, Any?>): String =
|
|
StringWriter().also { evaluate(it, context) }.toString() |