45

I noticed that IntelliJ can parse .kts files as Kotlin and the code editor picks them up as free-floating Kotlin files. You are also able to run the script in IntelliJ as you would a Kotlin file with a main method. The script executes from top to bottom.

This form is PERFECT for the project I'm working on, if only I knew an easy way to use them from within Java or Kotlin.

What's the idiomatic way to "run" these scripts from Java or Kotlin?

Jire
  • 9,680
  • 14
  • 52
  • 87
  • 2
    You can take a look at https://github.com/cypressious/KotlinW. Basically you invoke the compiler with the -script parameter. – Kirill Rakhman Jan 24 '16 at 10:54
  • @KirillRakhman Thank you, but would this not have performance implications? You also wouldn't be able to reference functions, classes and more from within Kotlin/Java. – Jire Jan 24 '16 at 10:55
  • If this doesn't exist, would it be possible to implement by generating bytecode of a class with the file's name and a function like `run` that would house the content? – Jire Jan 24 '16 at 11:01
  • 3
    take a look at https://stackoverflow.com/a/48281513/355438 – Ilya Serbis Jan 24 '18 at 21:59
  • See Kotlin scripting related [roadmap issue](https://youtrack.jetbrains.com/issue/KT-49511). – Mahozad Dec 11 '21 at 09:50

5 Answers5

39

Note that script files support in Kotlin is still pretty much experimental. This is an undocumented feature which we're still in the process of designing. What's working today may change, break or disappear tomorrow.

That said, currently there are two ways to invoke a script. You can use the command line compiler:

kotlinc -script foo.kts <args>

Or you can invoke the script directly from IntelliJ IDEA, by right-clicking in the editor or in the project view on a .kts file and selecting "Run ...":

Run .kts from IntelliJ IDEA

Alexander Udalov
  • 31,429
  • 6
  • 80
  • 66
  • 2
    Thanks for the official heads up. I might work on something to generate proper bytecode for these scripts to make executing them in Java or Kotlin a breeze. – Jire Jan 24 '16 at 12:16
  • @Alexander any news on scripting with kotlin in runtime apps? We'd like to replace groovy runtime scripts with kotlin if possible :) – Dodge Mar 26 '17 at 12:02
  • @Dodge running Kotlin scripts at runtime by the means of JSR 223 (Java scripting engines API) is currently work in progress. You can find an example of what can be achieved today at https://github.com/JetBrains/kotlin/tree/master/libraries/examples/kotlin-jsr223-local-example. I'll update my answer as soon as it's implemented and properly documented. – Alexander Udalov Mar 28 '17 at 11:41
14

KtsRunner

I've published a simple library that let's you run scripts from regular Kotlin programs.

https://github.com/s1monw1/KtsRunner

Example

  1. The example class

    data class ClassFromScript(val x: String)
    
  2. The .kts file

    import de.swirtz.ktsrunner.objectloader.ClassFromScript
    
    ClassFromScript("I was created in kts")
    
  3. The code to load the class

    val scriptReader =  Files.newBufferedReader(Paths.get("path/classDeclaration.kts"))
    val loadedObj: ClassFromScript = KtsObjectLoader().load<ClassFromScript>(scriptReader)
    println(loadedObj.x) // >> I was created in kts
    

As shown, the KtsObjectLoader class can be used for executing a .kts script and return its result. The example shows a script that creates an instance of the ClassFromScript type that is loaded via KtsObjectLoader and then processed in the regular program.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
8

As of 2020 (Kotlin 1.3.70), you can just use the straightforward

kotlin script.main.kts

Note that using the file extension .main.kts instead of .kts seems to be important.

Note that for me this does not seem to run the main() function if defined, I had to add a manual call to main() at the top level.

One of the advantages of Kotlin script is the ability to declare code and dependencies inside a single file (with @file:DependsOn, see for example here)

xjcl
  • 12,848
  • 6
  • 67
  • 89
  • If I recall correctly, the code in a `.main.kts` file is effectively embedded inside a main function that is defined outside of the file (it probably comes from the implicit `kotlin-main-kts` dependency?). So there's always a main function defined, you just cannot see it. Which makes sense, because it's meant to be a script. If you could define your own main function, it would be an executable program, rather than a script, I think. – tjalling Feb 21 '23 at 13:50
  • Note that it's set up in a way that allows you to define your own script runners. So you could make a script runner that takes `.myownthing.kts` files, for which you can determine what is implicitly in scope and how it's executed. For example, if you've created your own kotlin-based DSL, your `.myownthing.kts` runner could ensure that the compile-time and runtime dependencies for that DSL are always present for `.myownthing.kts` files, so that your users can directly use your DSL in their scripts. That's my understanding, at least. I haven't tried it myself. – tjalling Feb 21 '23 at 14:00
4

early 2020ies kscript that you find at https://github.com/holgerbrandl/kscript seems to be the most convenient and well supported way to go ...

Dirk Hoffmann
  • 1,444
  • 17
  • 35
0

jgo can fetch and run code from Maven repositories, so can be used to invoke https://github.com/scijava/scijava-common and https://github.com/scripting-kotlin to execute a local Foo.kt like so:

jgo --repository scijava.public=maven.scijava.org/content/groups/public org.scijava:scijava-common:@ScriptREPL+org.scijava:scripting-kotlin Foo.kt

If no Foo.kt is provided, it launches a Kotlin REPL.

John Vandenberg
  • 474
  • 6
  • 16