如何使用 Kotlin Multiplatform 编写命令行工具
能够编写自己的命令行工具是一项很棒的技能:可以自动化所有的事情!
不幸的是,编写 CLI 工具仍然主要使用 Bash。我强烈认为(虽然不太确定)只有两种好的 Bash 脚本:
幸运的是,淘汰 Bash 非常简单:你只需要使用你最喜欢的编程语言即可!
我尝试过 Kotlin Multiplatform,不仅用它构建了一个很酷的 CLI 工具,而且还将它打包为一个模板项目,您可以利用它更快地开始使用!
在 Kotlin Multiplatform 中构建命令行工具的启动项目
包含真实世界 CLI 工具的重新实现:git-standup

安装
您可以使用下面列出的选项之一进行安装
来源 |
命令 |
节点 |
npm install -g kotlin-cli-starter |
安装程序 |
curl -L https://raw.githubusercontent.com/jmfayard/kotlin-cli-starter/main/installer.sh | sudo sh |
测试 |
./gradlew allTests |
Kotlin 所有平台 |
跑步./gradlew allRun |
Kotlin JVM |
跑步./gradlew run |
Kotlin 原生 |
./gradlew install 然后运行$ git standup |
Kotlin Node.JS |
跑步./gradlew jsNodeRun |
为什么?
能够编写自己的命令行工具是一项很棒的技能。让所有事情自动化!
您可以使用 Kotlin 编写 CLI 工具,并享受使用的好处
- 一种现代编程语言
- 现代 IDE 支持
- 单元测试和持续集成等现代实践
- 利用 Kotlin 多平台库
- 在 JVM 上运行代码并受益于丰富的 Java 库
- 或者构建一个本机可执行文件,它启动非常快并且……
git-standup,Kotlin 多平台版本
git-standup是一款智能小工具,适合像我这样经常在站会前感到恐慌的人。我昨天到底做了什么?这个命令可以浏览所有 git 仓库并打印我昨天的提交,让我重新思考。试试看,它很可能会成为你工作流程的一部分。
克隆仓库:
git clone https://github.com/jmfayard/kotlin-cli-starter
cd kotlin-cli-starter
./gradlew install
git standup
./gradlew install
将会安装该工具作为本机可执行文件。
还有两个可用选项:
./gradlew run
将在 JVM 上运行它
./gradlew jsNodeRun
将在 Node.js 上运行它
相同的通用代码,多个平台。

现代编程实践
传统的 Bash 脚本包含
- 一种你记不住如何执行 for 循环的 if/else 语句的语法
- 由于Code Golf导致代码无法读取:
ztf -P -c -D -a
- 没有依赖管理(除了错误消息
ztf not found
:)
- 一个文件完成所有工作
- 没有构建系统
- 不支持 IDE(
vim
对每个人来说应该足够了)
- 没有单元测试
- 没有 CI/CD
通过选择 Kotlin 这样的现代编程语言,我们可以
- 现代语法
- 可读代码
- 多个函数、文件、类和包中的关注点分离
- 像 Gradle 这样的现代构建系统
- 依赖管理(这里使用gradle refreshVersions)
- 像 JetBrains IntelliJ 这样的现代 IDE
- 单元测试。在这里,它们在所有平台上运行,
./gradlew allRun
- CI-CD。单元测试在 GitHub Actions 上运行。参见工作流程
这听起来可能很明显,但人们仍然用 Bash 编写他们的 CLI 工具,所以值得重复。
为什么要支持多平台?
这三个平台具有不同的特点,通过使您的代码在所有平台上可用,您可以决定哪一个更适合您:
但更重要的是,这是一个学习 Kotlin/Multiplatform 的好机会。Kotlin/Multiplatform 是一项引人入胜的技术,但也可能相当复杂。使用 Kotlin/Multiplatform 编写 CLI 工具,您可以从简单的事情入手。
编写 Kotlin Multiplatform 代码是什么样的?
一旦您有了所需的抽象,它就感觉像常规的 Kotlin 一样,而您所需要的只是修改commonMain。
当您必须使用预期/实际机制连接到特定于平台的 API时,事情会变得有趣。
例如,我需要检查一个文件是否存在:
// commonMain
expect fun fileIsReadable(filePath: String): Boolean
在 JVM 上实现这一点很简单
// jvmMain
actual fun fileIsReadable(filePath: String): Boolean =
File(filePath).canRead()
但是如何使用 Kotlin Native 实现这一点?
由于 Kotlin Native 让我们可以访问底层 C API,那么问题是:他们如何在 C 中做到这一点?
让我们谷歌一下“如何检查一个文件是否可读 C”。
第一个答案是关于访问系统调用。
我们用man access阅读友好的手册:

这直接引导我们实现这个功能:
// nativeMain
actual fun fileIsReadable(filePath: String): Boolean =
access(filePath, R_OK ) == 0
有趣、奇怪的感觉,我们正在用 Kotlin 编写 C。
它有效,但是等等,还有更好的解决方案!
使用现有的 Kotlin Multiplatform 库
我后来发现okio已经实现了我处理文件所需的多平台原语。
我很高兴我可以删除我平台特定的代码:
// commonMain
expect val fileSystem: FileSystem
fun fileIsReadable(filePath: String): Boolean =
fileSystem.exists(filePath.toPath())
fun readAllText(filePath: String): String =
fileSystem.read(filePath.toPath()) {
readUtf8()
}
fun writeAllText(filePath: String, text: String): Unit =
fileSystem.write(filePath.toPath()) {
writeUtf8(text)
}
查看提交
我应该了解哪些多平台库?
Kotlin Multiplatform 库涵盖了最常见的用例:解析参数、JSON、数据库、IO、DI、协程和测试。
为这些库添加书签:
我特别喜欢用CliKt来解析参数。它有一个杀手级功能,不仅可以自动生成帮助信息,还可以自动生成 Bash、Zsh 和 Fish 的 shell 补全。
缺点:设置一切需要时间
构建这个项目很有趣,我学到了很多东西,但也花费了很多时间。
如果我没有那么多时间,下次我该怎么办?
回到 Bash?
kotlin-cli-starter:构建 CLI 工具的启动项目
我真的不想回到 Bash。
这时我决定走另一条路,将我的实验转变为一个我和每个人都可以重复使用的启动项目。
单击“使用此模板”,您就可以开始编写自己的 CLI 工具。

我已在所有需要自定义的地方添加了以CUSTOMIZE_ME开头的评论
使用以下方式查找Edit > File > Find in Files

结论
使用命令行工具自动化您的工作流程。但在像上个世纪那样使用 Bash 之前,请三思。Kotlin 和其他现代编程语言可能是更优的解决方案。
使用 Kotlin Multiplatform 可以让您获得每个平台的优势,例如丰富的 JVM 库、本机可执行文件的快速启动以及 Node.js 的包管理器 (npm)。
这不是绝对必要的,但如果您想学习 Kotlin Multiplatform,这是一个很好的起点。
不过,从头开始设置可能需要一段时间。
这就是我将我的项目转换为可以重复使用的启动项目/ GitHub 模板的原因。
在 Kotlin Multiplatform 中构建命令行工具的启动项目
包含真实世界 CLI 工具的重新实现:git-standup

安装
您可以使用下面列出的选项之一进行安装
为什么?
能够编写自己的命令行工具是一项很棒的技能。让所有事情自动化!
您可以使用 Kotlin 编写 CLI 工具,并享受使用的好处
- 一种现代编程语言
- 现代 IDE 支持
- 单元测试和持续集成等现代实践
- 利用 Kotlin 多平台库
- 在 JVM 上运行代码并受益于丰富的 Java 库
- 或者构建一个本机可执行文件,它启动非常快并且……
如果您使用 kotlin-cli-starter 构建了某些东西,我会很高兴地告诉了我!
文章来源:https://dev.to/jmfayard/how-to-write-a-command-line-tool-with-kotlin-multiplatform-45g2