如何在Kotlin/Java中运行Kotlin-Script (.kts)文件?

45

我注意到IntelliJ可以将.kts文件解析为Kotlin代码,并且代码编辑器将它们识别为自由漂浮的Kotlin文件。您也可以像运行带有main方法的Kotlin文件一样在IntelliJ中运行脚本。该脚本按照从上到下的顺序执行。

如果我知道一种简单的方法可以从Java或Kotlin中使用它们,那么这种形式对我正在开发的项目来说是完美的。

什么是运行这些脚本的惯用方式?从Java或Kotlin中运行这些脚本的方法是什么?


2
你可以查看 https://github.com/cypressious/KotlinW。基本上,你需要使用 -script 参数调用编译器。 - Kirill Rakhman
@KirillRakhman 谢谢,但这不会影响性能吗?您也无法从 Kotlin/Java 中引用函数、类等。 - Jire
如果这个不存在,是否可以通过生成一个类的字节码来实现,该类的名称与文件名相同,并包含一个名为“run”的函数来存储内容? - Jire
3
请查看 https://dev59.com/hZnga4cB1Zd3GeqPYWyf#48281513。 - Ilya Serbis
请查看与Kotlin脚本相关的路线图问题 - Mahozad
5个回答

39

请注意,Kotlin中的脚本文件支持仍然处于实验阶段。这是一个未记录的特性,我们仍在设计过程中。今天可用的功能可能会在明天更改、破裂或消失。

话虽如此,目前有两种方式可以调用脚本。您可以使用命令行编译器:

kotlinc -script foo.kts <args>

或者您可以直接从IntelliJ IDEA中调用脚本,通过在编辑器或项目视图上右键单击.kts文件并选择“Run ...”:

从IntelliJ IDEA运行.kts


2
感谢官方提供的提示。我可能会着手开发一些工具来生成这些脚本的正确字节码,使其在Java或Kotlin中执行变得轻松无比。 - Jire
@Alexander 有没有在运行时应用程序中使用 Kotlin 脚本的最新消息?如果可能的话,我们希望用 Kotlin 替换 Groovy 运行时脚本 :) - Dodge
@Dodge 目前正在进行使用 JSR 223(Java 脚本引擎 API)在运行时运行 Kotlin 脚本的工作。您可以在 https://github.com/JetBrains/kotlin/tree/master/libraries/examples/kotlin-jsr223-local-example 找到今天可以实现的示例。一旦实现并适当记录,我将尽快更新我的答案。 - Alexander Udalov

13

KtsRunner

我发布了一个简单的库,可以让你从常规的 Kotlin 程序中运行脚本。

https://github.com/s1monw1/KtsRunner

示例

  1. 示例类:

    data class ClassFromScript(val x: String)
    
  2. .kts文件

  3. import de.swirtz.ktsrunner.objectloader.ClassFromScript
    
    ClassFromScript("I was created in kts")
    
  4. 加载该类的代码

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

    如上所示,KtsObjectLoader类可用于执行一个 .kts 脚本并返回其结果。该示例演示了一个脚本,该脚本创建了一个 ClassFromScript 类的实例,该类通过 KtsObjectLoader 加载,然后在常规程序中进行处理。


10
截至2020年(Kotlin 1.3.70),你可以直接使用简单的
kotlin script.main.kts

请注意,使用文件扩展名.main.kts而不是.kts似乎很重要
请注意,对我来说,如果定义了main()函数,似乎无法运行它,我必须在顶层添加手动调用main()
Kotlin脚本的优点之一是能够在单个文件中声明代码和依赖项(使用@file:DependsOn,例如这里)。

如果我没记错的话,.main.kts 文件中的代码实际上嵌入在文件外定义的 main 函数内(可能来自隐式的 kotlin-main-kts 依赖项?)。因此,总是定义了一个 main 函数,只是你看不到它。这很有道理,因为它旨在成为一个脚本。如果你可以定义自己的 main 函数,那么它将成为一个可执行程序,而不是一个脚本,我想。 - tjalling
请注意,它的设置方式允许您定义自己的脚本运行器。因此,您可以创建一个脚本运行器,以处理 .myownthing.kts 文件,并确定隐含范围和执行方式。例如,如果您已经创建了基于 Kotlin 的 DSL,则 .myownthing.kts 运行器可以确保该 DSL 的编译时和运行时依赖项始终存在于 .myownthing.kts 文件中,以便用户可以直接在其脚本中使用您的 DSL。至少这是我的理解,我自己还没有尝试过。 - tjalling
“似乎很重要”的部分是我所缺失的一块拼图,终于结束了我不断搜索的过程。谢谢! - undefined

5

0

jgo可以从Maven存储库获取并运行代码,因此可以用来调用https://github.com/scijava/scijava-commonhttps://github.com/scripting-kotlin来执行本地的Foo.kt,如下所示:

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

如果没有提供 Foo.kt,它将启动 Kotlin REPL。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接