Kotlin cocok untuk membangun CLI tool karena standard library-nya kaya dan sintaksnya ringkas. CLI tool modern seperti git, kubectl, atau gh mengikuti pola yang konsisten: sub-command, argumen posisional, opsi, dan exit code yang terdefinisi. Pada bab ini kita akan merancang struktur CLI tool utuh menggunakan parsing argumen manual, mendefinisikan exit code yang berarti, dan menyediakan bantuan otomatis. Library seperti kotlinx-cli bisa dipakai bila skala CLI sudah besar, namun memahami parsing manual tetap penting agar kita tahu apa yang terjadi di balik layar.
Struktur CLI Tool #
CLI tool Kotlin biasanya terdiri dari tiga lapis: entry point yang menerima args, dispatcher yang memetakan sub-command ke function handler, dan handler yang melakukan pekerjaan sebenarnya. Struktur ini memungkinkan penambahan command baru tanpa mengubah kode yang sudah ada.
fun main(args: Array<String>) {
val command = args.firstOrNull() ?: "help"
val params = args.drop(1).toTypedArray()
when (command) {
"hello" -> cmdHello(params)
"add" -> cmdAdd(params)
"help" -> cmdHelp()
else -> {
println("Perintah tidak dikenal: $command")
kotlin.system.exitProcess(2)
}
}
}args.firstOrNull() menangani skenario CLI dipanggil tanpa argumen. drop(1) memisahkan sub-command dari parameternya. Pemisahan ini membuat handler fokus pada parameter saja.
Exit Code yang Berarti #
Exit code adalah kontrak antara CLI tool dan pemanggil (shell, skrip lain, atau CI). Nilai 0 berarti sukses, nilai selain 0 menandakan kesalahan. Standar umum yang dipakai banyak tool:
| Code | Arti |
|---|---|
| 0 | Sukses |
| 1 | Kesalahan input pengguna |
| 2 | Perintah tidak dikenal |
| 126 | File tidak executable |
| 130 | Dibatalkan oleh Ctrl+C |
Bash memakai exit code untuk kontrol alur (if my_cli; then ...), jadi konsistensi sangat penting.
CLI Utility Lengkap #
Cuplikan berikut memodelkan CLI tool utuh dengan tiga sub-command (hello, add, help) dan exit code yang terdefinisi. Saat dipanggil tanpa argumen, program memasuki demo mode yang menjalankan semua command contoh:
// Demo CLI sederhana dengan sub-command dan exit code.
// Memodelkan struktur CLI tool seperti git/kubectl: command + args.
// Contoh pemakaian (saat dipanggil tanpa argumen, memakai demo mode):
// java -jar cli.jar hello Budi
// java -jar cli.jar add 3 5
// java -jar cli.jar help
import kotlin.system.exitProcess
fun main(args: Array<String>) {
if (args.isEmpty()) {
// Demo mode untuk keperluan tutorial — menampilkan output deterministik
println("=== Demo Command-Line Utility ===")
println()
runCommand(arrayOf("hello", "Budi"))
println()
runCommand(arrayOf("add", "3", "5"))
println()
runCommand(arrayOf("add", "10", "20", "30"))
println()
runCommand(arrayOf("help"))
println()
runCommand(arrayOf("tidakada"))
println("Exit code perintah terakhir: 2")
return
}
val code = runCommand(args)
exitProcess(code)
}
fun runCommand(args: Array<String>): Int {
val command = args.firstOrNull() ?: "help"
val params = args.drop(1).toTypedArray()
return when (command) {
"hello" -> cmdHello(params)
"add" -> cmdAdd(params)
"help" -> cmdHelp()
else -> {
println("Perintah tidak dikenal: $command")
println("Ketik 'help' untuk daftar perintah yang tersedia.")
2
}
}
}
fun cmdHello(params: Array<String>): Int {
if (params.isEmpty()) {
println("Halo, dunia!")
} else {
println("Halo, ${params.joinToString(" ")}!")
}
return 0
}
fun cmdAdd(params: Array<String>): Int {
if (params.isEmpty()) {
println("Error: tidak ada angka untuk dijumlahkan.")
println("Pemakaian: add <angka1> <angka2> ...")
return 1
}
val angka = params.mapNotNull { it.toIntOrNull() }
if (angka.size != params.size) {
val invalid = params.filter { it.toIntOrNull() == null }
println("Error: input bukan angka: ${invalid.joinToString(", ")}")
return 1
}
println("Input: ${angka.joinToString(" + ")}")
println("Hasil: ${angka.sum()}")
return 0
}
fun cmdHelp(): Int {
println("Pemakaian: cli <perintah> [args]")
println()
println("Perintah yang tersedia:")
println(" hello [nama] Menyapa pengguna (default: 'dunia')")
println(" add <a> <b> ... Menjumlahkan daftar angka")
println(" help Menampilkan bantuan ini")
println()
println("Exit codes:")
println(" 0 Sukses")
println(" 1 Kesalahan input pengguna")
println(" 2 Perintah tidak dikenal")
return 0
}Output yang Dihasilkan:
=== Demo Command-Line Utility ===
Halo, Budi!
Input: 3 + 5
Hasil: 8
Input: 10 + 20 + 30
Hasil: 60
Pemakaian: cli <perintah> [args]
Perintah yang tersedia:
hello [nama] Menyapa pengguna (default: 'dunia')
add <a> <b> ... Menjumlahkan daftar angka
help Menampilkan bantuan ini
Exit codes:
0 Sukses
1 Kesalahan input pengguna
2 Perintah tidak dikenal
Perintah tidak dikenal: tidakada
Ketik 'help' untuk daftar perintah yang tersedia.
Exit code perintah terakhir: 2Mari kita bedah bagian-bagian kunci dari kode di atas:
runCommanddispatcher: function ini menerima seluruhargs, mengambil elemen pertama sebagai command, dandrop(1)menghasilkan array parameter. Pemisahan ini membuat handlercmdHello,cmdAdd, dancmdHelpfokus pada logika bisnis tanpa harus mengurai argumen lagi.cmdAddvalidasi angka:mapNotNull { it.toIntOrNull() }mencoba mengkonversi setiap argumen keInt. Bila jumlah angka hasil konversi tidak sama dengan jumlah input, berarti ada argumen non-numerik. Validasi ini menjaga agar tidak terjadiNumberFormatExceptionruntime.- Exit code konsisten: setiap handler mengembalikan
Int.main()memanggilexitProcess(code)yang meneruskan kode ke shell.0artinya sukses,1artinya input invalid,2artinya command tidak dikenal. - Demo mode: bila
argskosong, program menjalankan semua command contoh untuk keperluan tutorial. Pada CLI production, mode ini bisa diganti dengan menampilkan help default.
Menggunakan Library kotlinx-cli #
Untuk CLI berskala besar, library kotlinx-cli mengurangi boilerplate. Kita mendeklarasikan argumen dan opsi sebagai property, lalu library memparse dan memvalidasi.
import kotlinx.cli.*
fun main(args: Array<String>) {
val parser = ArgParser("aplikasi")
val nama by parser.argument(ArgType.String, description = "Nama pengguna")
val verbose by parser.option(ArgType.Boolean, fullName = "verbose", shortName = "v").default(false)
parser.parse(args)
if (verbose) println("Mode verbose aktif")
println("Halo, $nama!")
}Library ini menangani --help, validasi tipe, dan pesan error otomatis. Cocok bila CLI akan tumbuh menjadi 10+ sub-command.
Referensi Lanjutan #
- Kotlin Command Line
— panduan resmi
kotlincdankotlinCLI untuk menjalankan utilitas baris perintah - kotlinx.cli
— halaman GitHub
kotlinx-cliuntuk parsing argumen CLI yang terstruktur
Selanjutnya #
CLI tool sekarang punya struktur. Bab berikutnya membahas parsing argumen secara mendalam: posisional vs flags, format --key=value, dan pola help text yang baik. Materi tersebut ada di chapter Command-Line Argument Parsing.