Reputation: 2268
I have a bunch of strings like these in my already existing and quit big template file:
Hello $World I say hello to $User, too
I was thinking I could somehow let kotlin parse/search&replace this file as a kotlin string, and I'd just have to set the variables World
and User
to get an evaluated string... How is this possible?
This is not a kotlin source file, but a file that's beeing read by my kotlin program.
Why I want to do this? I used bash's envsubst
before, and had to move away from this, since things were getting too complicated. But now I have no easy way to replace strings in a file anymore...
Thanks
Upvotes: 1
Views: 2953
Reputation: 13690
Warning: Please see my other answer first: you probably don't want to run a full Kotlin script just to parse some text file with variables... use a template engine for that.
It's possible to execute Kotlin scripts, i.e. eval
Kotlin code, but it requires that you basically ship the Kotlin compiler with your application.
This GitHub project, KtsRunner, for example, does that, so you can do this:
val scriptContent = "5 + 10"
val fromScript: Int = KtsObjectLoader().load<Int>(scriptContent))
println(fromScript)
// >> 15
It requires some hacking though, is very slow and it uses a bunch of Kotlin "internal" APIs to work.
See the full list of libraries this project uses here:
https://github.com/s1monw1/KtsRunner/blob/master/lib/build.gradle.kts#L21
A "proper" KEEP proposal (discussion here) exists to add first-class support for this in Kotlin, but it's not finalized yet.
Currently, it looks something like this:
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate<MainKtsScript>()
return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConfiguration, evaluationConfiguration)
}
But it'll probably change before being released.
Upvotes: 0
Reputation: 13690
What you want is called a template engine.
You don't really need an eval (which would allow running a full Kotlin application from a String) in this case.
For example, FreeMarker templates use a syntax that's similar to Kotlin template Strings, so a template may look like this:
<h1>Welcome ${user}!</h1>
Then, from Kotlin, you can evaluate the template with a Map
holding the template bindings (variables the template can use) like this:
val user = "joe"
val bindings = mapOf("user" to user)
val cfg = new Configuration(Configuration.VERSION_2_3_29)
cfg.directoryForTemplateLoading = File("/where/you/store/templates")
val template = cfg.getTemplate("test.ftlh")
// write the resolved template to stdout
val out = OutputStreamWriter(System.out)
template.process(bindings, out)
See a Java example here: https://freemarker.apache.org/docs/pgui_quickstart_all.html
There are many other template engines, and the KTor site lists a few:
https://ktor.io/docs/working-with-views.html
If you're using KTor, BTW, it makes it much easier to use template engines... your framework may even have similar.
Upvotes: 1