Scaffold/app/src/commands/GenerateCommand.kt

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()