Simple DSL for providing data

This commit is contained in:
Shadowfacts 2017-08-05 13:41:24 -04:00
parent 86de475391
commit fe378f453d
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
2 changed files with 30 additions and 17 deletions

View File

@ -35,7 +35,7 @@ _result.toString()
ScriptEngineManager()
}
fun render(template: String, data: Map<String, Any>, 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<String, Any>, 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<String, Any> = mapOf()): Any? {
internal fun eval(script: String, data: Map<String, TypedValue> = 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<String, TypedValue>()
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)
}

View File

@ -6,9 +6,9 @@ import java.io.File
* @author shadowfacts
*/
fun main(args: Array<String>) {
val res = EKT.render(File("template.ekt"), mapOf(
"list" to EKT.Value(listOf(1, 2, 3), "List<String>")
), dumpGeneratedScript = File("script.kts"))
val res = EKT.render(File("template.ekt"), dumpGeneratedScript = File("script.kts")) {
"list" to (listOf(1, 2, 3) asType "List<Int>")
}
File("result.txt").apply {
if (!exists()) createNewFile()