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() for ((path, prompts) in config.prompts) { val map = mutableMapOf() 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 = StringWriter().also { evaluate(it, context) }.toString()