From fe378f453db871fcf9fbee0036004dac031a3cdf Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 5 Aug 2017 13:41:24 -0400 Subject: [PATCH] Simple DSL for providing data --- src/main/kotlin/net/shadowfacts/ekt/EKT.kt | 41 ++++++++++++++------- src/test/kotlin/net/shadowfacts/ekt/Test.kt | 6 +-- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/net/shadowfacts/ekt/EKT.kt b/src/main/kotlin/net/shadowfacts/ekt/EKT.kt index 28f5b1f..80c1a07 100644 --- a/src/main/kotlin/net/shadowfacts/ekt/EKT.kt +++ b/src/main/kotlin/net/shadowfacts/ekt/EKT.kt @@ -35,7 +35,7 @@ _result.toString() ScriptEngineManager() } - fun render(template: String, data: Map, dumpGeneratedScript: File? = null): String { + fun render(template: String, dumpGeneratedScript: File? = null, dataProvider: DataProviderContext.() -> Unit): String { @Suppress("NAME_SHADOWING") var template = template template = template.replace("$", "\${'$'}") @@ -64,34 +64,47 @@ _result.toString() writeText(script) } - return eval(script, data) as String + val data = DataProviderContext() + data.dataProvider() + + return eval(script, data.map) as String } - fun render(template: File, data: Map, dumpGeneratedScript: File? = null): String { - return render(template.readText(), data, dumpGeneratedScript) + fun render(template: File, dumpGeneratedScript: File? = null, dataProvider: DataProviderContext.() -> Unit): String { + return render(template.readText(), dumpGeneratedScript, dataProvider) } - internal fun eval(script: String, data: Map = mapOf()): Any? { + internal fun eval(script: String, data: Map = mapOf()): Any? { val engine = manager.getEngineByExtension("kts") val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) bindings.putAll(data) // Hack to allow data to be accessed by name from template instead of via bindings map val unwrapBindings = data.keys.map { - val value = data[it]!! - if (value is Value) { - val type = value.type - "val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.Value).value as $type" - } else { - val type = value::class.qualifiedName - "val $it = bindings[\"$it\"] as $type" - } + val type = data[it]!!.type + "val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.TypedValue).value as $type" }.joinToString("\n") engine.eval(unwrapBindings) return engine.eval(script) } - data class Value(val value: Any, val type: String) + class DataProviderContext { + internal val map = mutableMapOf() + + infix fun String.to(value: Any) { + if (value is TypedValue) { + map[this] = value + } else { + map[this] = TypedValue(value, value::class.qualifiedName!!) + } + } + + infix fun Any.asType(type: String): TypedValue { + return TypedValue(this, type) + } + } + + data class TypedValue(val value: Any, val type: String) } \ No newline at end of file diff --git a/src/test/kotlin/net/shadowfacts/ekt/Test.kt b/src/test/kotlin/net/shadowfacts/ekt/Test.kt index a8bd0f0..8ad96d9 100644 --- a/src/test/kotlin/net/shadowfacts/ekt/Test.kt +++ b/src/test/kotlin/net/shadowfacts/ekt/Test.kt @@ -6,9 +6,9 @@ import java.io.File * @author shadowfacts */ fun main(args: Array) { - val res = EKT.render(File("template.ekt"), mapOf( - "list" to EKT.Value(listOf(1, 2, 3), "List") - ), dumpGeneratedScript = File("script.kts")) + val res = EKT.render(File("template.ekt"), dumpGeneratedScript = File("script.kts")) { + "list" to (listOf(1, 2, 3) asType "List") + } File("result.txt").apply { if (!exists()) createNewFile()