Refactor TemplateEnvironment, add support for classpath templates

This commit is contained in:
Shadowfacts 2017-08-19 11:45:27 -04:00
parent df7f358399
commit c5f94ef738
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
7 changed files with 109 additions and 19 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@
/.gradle /.gradle
# idea # idea
/classes
/out /out
/run /run
/.idea /.idea

View File

@ -8,6 +8,7 @@ buildscript {
} }
plugins { plugins {
id "idea"
id "maven" id "maven"
} }
@ -23,6 +24,8 @@ dependencies {
compile group: "org.jetbrains.kotlin", name: "kotlin-script-util", version: kotlin_version compile group: "org.jetbrains.kotlin", name: "kotlin-script-util", version: kotlin_version
} }
idea.module.inheritOutputDirs = true
uploadArchives { uploadArchives {
repositories.mavenDeployer { repositories.mavenDeployer {
repository(url: "http://archiva.shadowfacts.net/repository/local/") { repository(url: "http://archiva.shadowfacts.net/repository/local/") {

View File

@ -27,9 +27,9 @@ object EKT {
private val scriptPrefix = """ private val scriptPrefix = """
val _env = bindings["_env"] as net.shadowfacts.ekt.EKT.TemplateEnvironment val _env = bindings["_env"] as net.shadowfacts.ekt.EKT.TemplateEnvironment
val _result = StringBuilder() val _result = StringBuilder()
fun echo(it: Any) { _result.append(it) } fun echo(it: Any?) { _result.append(it) }
fun include(include: String) { fun include(include: String) {
val env = net.shadowfacts.ekt.EKT.TemplateEnvironment(include, _env) val env = _env.createChild(include)
echo(net.shadowfacts.ekt.EKT.render(env, env.include)) echo(net.shadowfacts.ekt.EKT.render(env, env.include))
} }
""" """
@ -80,20 +80,36 @@ _result.toString()
return eval(script, env) return eval(script, env)
} }
fun render(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, data: Map<String, TypedValue>): String { fun renderFile(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, data: Map<String, TypedValue>): String {
return render(TemplateEnvironment(name, templateDir, includeDir, cacheDir, data)) return render(FileTemplateEnvironment(name, templateDir, includeDir, cacheDir, data))
} }
fun render(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, init: DataProvider.() -> Unit): String { fun renderFile(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, init: DataProvider.() -> Unit): String {
return render(TemplateEnvironment(name, templateDir, includeDir, cacheDir, init)) return render(FileTemplateEnvironment(name, templateDir, includeDir, cacheDir, init))
} }
fun render(name: String, dir: File, cacheScripts: Boolean = false, data: Map<String, TypedValue>): String { fun renderFile(name: String, dir: File, cacheScripts: Boolean = false, data: Map<String, TypedValue>): String {
return render(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, data) return renderFile(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, data)
} }
fun render(name: String, dir: File, cacheScripts: Boolean = false, init: DataProvider.() -> Unit): String { fun renderFile(name: String, dir: File, cacheScripts: Boolean = false, init: DataProvider.() -> Unit): String {
return render(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, init) return renderFile(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, init)
}
fun renderClasspath(name: String, templatePath: String, includePath: String, cacheDir: File? = null, data: Map<String, TypedValue>): String {
return render(ClasspathTemplateEnvironment(name, templatePath, includePath, cacheDir, data))
}
fun renderClasspath(name: String, templatePath: String, includePath: String, cacheDir: File? = null, init: DataProvider.() -> Unit): String {
return render(ClasspathTemplateEnvironment(name, templatePath, includePath, cacheDir, init))
}
fun renderClasspath(name: String, path: String, cacheDir: File? = null, data: Map<String, TypedValue>): String {
return renderClasspath(name, path, "$path/includes", cacheDir, data)
}
fun renderClasspath(name: String, path: String, cacheDir: File? = null, init: DataProvider.() -> Unit): String {
return renderClasspath(name, path, "$path/includes", cacheDir, init)
} }
internal fun eval(script: String, env: TemplateEnvironment): String { internal fun eval(script: String, env: TemplateEnvironment): String {
@ -112,22 +128,35 @@ _result.toString()
return engine.eval(script) as String return engine.eval(script) as String
} }
class TemplateEnvironment { interface TemplateEnvironment {
val rootName: String val rootName: String
val name: String val name: String
val templateDir: File
val includeDir: File
val cacheDir: File? val cacheDir: File?
val data: Map<String, TypedValue> val data: Map<String, TypedValue>
val template: String val template: String
get() = File(templateDir, "$name.ekt").readText(Charsets.UTF_8)
val include: String val include: String
get() = File(includeDir, "$name.ekt").readText(Charsets.UTF_8)
val cacheFile: File val cacheFile: File
get() = File(cacheDir!!, "$name.kts") get() = File(cacheDir!!, "$name.kts")
fun createChild(name: String): TemplateEnvironment
}
class FileTemplateEnvironment: TemplateEnvironment {
override val rootName: String
override val name: String
override val cacheDir: File?
override val data: Map<String, TypedValue>
val templateDir: File
val includeDir: File
override val template: String
get() = File(templateDir, "$name.ekt").readText(Charsets.UTF_8)
override val include: String
get() = File(includeDir, "$name.ekt").readText(Charsets.UTF_8)
constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, data: Map<String, TypedValue>) { constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, data: Map<String, TypedValue>) {
this.rootName = name this.rootName = name
this.name = name this.name = name
@ -140,7 +169,7 @@ _result.toString()
constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, init: DataProvider.() -> Unit): constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, init: DataProvider.() -> Unit):
this(name, templateDir, includeDir, cacheDir, DataProvider.init(init)) this(name, templateDir, includeDir, cacheDir, DataProvider.init(init))
constructor(name: String, parent: TemplateEnvironment, cacheDir: File? = parent.cacheDir) { constructor(name: String, parent: FileTemplateEnvironment, cacheDir: File? = parent.cacheDir) {
this.rootName = parent.rootName this.rootName = parent.rootName
this.name = name this.name = name
this.templateDir = parent.templateDir this.templateDir = parent.templateDir
@ -149,6 +178,51 @@ _result.toString()
this.data = parent.data this.data = parent.data
} }
override fun createChild(name: String): TemplateEnvironment {
return FileTemplateEnvironment(name, this)
}
}
class ClasspathTemplateEnvironment: TemplateEnvironment {
override val rootName: String
override val name: String
override val cacheDir: File?
override val data: Map<String, TypedValue>
val templatePath: String
val includePath: String
override val template: String
get() = EKT::class.java.getResourceAsStream("$templatePath/$name.ekt").bufferedReader(Charsets.UTF_8).readText()
override val include: String
get() = EKT::class.java.getResourceAsStream("$includePath/$name.ekt").bufferedReader(Charsets.UTF_8).readText()
constructor(name: String, templatePath: String, includePath: String, cacheDir: File?, data: Map<String, TypedValue>) {
this.rootName = name
this.name = name
this.templatePath = templatePath
this.includePath = includePath
this.cacheDir = cacheDir
this.data = data
}
constructor(name: String, templatePath: String, includePath: String, cacheDir: File?, init: DataProvider.() -> Unit):
this(name, templatePath, includePath, cacheDir, DataProvider.init(init))
constructor(name: String, parent: ClasspathTemplateEnvironment, cacheDir: File? = parent.cacheDir) {
this.rootName = parent.rootName
this.name = name
this.templatePath = parent.templatePath
this.includePath = parent.includePath
this.cacheDir = cacheDir
this.data = parent.data
}
override fun createChild(name: String): TemplateEnvironment {
return ClasspathTemplateEnvironment(name, this)
}
} }
class DataProvider { class DataProvider {

View File

@ -1 +1 @@
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory

View File

@ -6,7 +6,7 @@ import java.io.File
* @author shadowfacts * @author shadowfacts
*/ */
fun main(args: Array<String>) { fun main(args: Array<String>) {
val res = EKT.render("template", File("."), cacheScripts = true) { val res = EKT.renderClasspath("template", "/templates", cacheDir = File("cache")) {
"list" to (listOf(1, 2, 3) asType "List<Int>") "list" to (listOf(1, 2, 3) asType "List<Int>")
} }

View File

@ -0,0 +1,5 @@
---------
Classpath include
[= list =]
My name is: [= _env.name =]
Root name: [= _env.rootName =]

View File

@ -0,0 +1,7 @@
Environment type: [= _env::class.simpleName =]
[= list.joinToString("\n") =]
Sum: [= list.sum() =]
[: include("include") :]