Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Kotlin/kotlinx-cli
Pure Kotlin implementation of a generic CLI parser.
https://github.com/Kotlin/kotlinx-cli
Last synced: 11 days ago
JSON representation
Pure Kotlin implementation of a generic CLI parser.
- Host: GitHub
- URL: https://github.com/Kotlin/kotlinx-cli
- Owner: Kotlin
- License: apache-2.0
- Created: 2017-09-20T13:07:21.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2023-09-01T16:05:12.000Z (about 1 year ago)
- Last Synced: 2024-05-18T19:24:03.360Z (6 months ago)
- Language: Kotlin
- Size: 342 KB
- Stars: 899
- Watchers: 36
- Forks: 67
- Open Issues: 35
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-cli-frameworks - kotlinx-cli
README
# kotlinx-cli
[![Kotlin Experimental](https://kotl.in/badges/experimental.svg)](https://kotlinlang.org/docs/components-stability.html)
[![JetBrains obsolete project](https://jb.gg/badges/obsolete.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-cli.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-cli)## This library is obsolete
It is effectively unmaintained. Please consider using other libraries.
## Description
Pure Kotlin implementation of a generic command-line parser.
* Declarative: describe what your commands and parameters are
* Platform-agnostic: core library has no platform-specific dependencies and can be used in any Kotlin project
* Hackable: build extensions on top of it however you like`kotlinx-cli` can be used to create user-friendly and flexible command-line interfaces
for Kotlin/JVM, Kotlin/Native, and any other Kotlin console applications.
Program defines what arguments are expected.
`kotlinx-cli` will figure out how to parse those, reporting errors if the program arguments are invalid,
and also generate help and usage messages as well.## Using in your projects
> Note that the library is experimental and the API is subject to change.
The library is published to Maven Central repository.
### Gradle
- Add the Maven Central repository if it is not already there:
```kotlin
repositories {
mavenCentral()
}
```In Kotlin multiplatform projects, add the following dependency to a source set (it may be a common or platform specific source set):
```groovy
kotlin {
sourceSets {
commonMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.6")
}
}
}
}
```### Maven
In Kotlin projects, add the following dependency to the `dependencies` element of `pom.xml`:
```xml
org.jetbrains.kotlinx
kotlinx-cli-jvm
0.3.6```
## Command line entities
There are 2 base entity: option and argument.*Option* - command line entity started with some prefix (-/--) and can have value as next entity in command line string.
*Argument* - command line entity which role is connected only with its position.
Command line entities can be several types:
* ArgType.Boolean
* ArgType.Int
* ArgType.String
* ArgType.Double
* ArgType.Choice (value can be only from predefined list)Custom types can be created.
### Example
```kotlin
import kotlinx.cli.*fun produce(result: List, format: String, outputFileName: String?) {
outputFileName.let {
// Print to file.
...
} ?: run {
// Print to stdout.
...
}
}fun readFrom(inputFileName: String): String {
...
}fun calculate(inputData: String, eps: Double, debug: Boolean = false): List {
...
}enum class Format {
HTML,
CSV,
}fun main(args: Array) {
val parser = ArgParser("example")
val input by parser.option(ArgType.String, shortName = "i", description = "Input file").required()
val output by parser.option(ArgType.String, shortName = "o", description = "Output file name")
val format by parser.option(ArgType.Choice(), shortName = "f",
description = "Format for output file").default(Format.CSV).multiple()
val stringFormat by parser.option(ArgType.Choice(listOf("html", "csv", "pdf"), { it }), shortName = "sf",
description = "Format as string for output file").default("csv").multiple()
val debug by parser.option(ArgType.Boolean, shortName = "d", description = "Turn on debug mode").default(false)
val eps by parser.option(ArgType.Double, description = "Observational error").default(0.01)parser.parse(args)
val inputData = readFrom(input)
val result = calculate(inputData, eps, debug)
format.forEach {
produce(result, it, output)
}
}
```It's also possible to use arguments in current example.
```kotlin
...
val input by parser.argument(ArgType.String, description = "Input file")
val output by parser.argument(ArgType.String, description = "Output file name").optional()
```Auto-generated help message for this example is
```
Usage: example options_list
Arguments:
input -> Input file { String }
output -> Output file name (optional) { String }
Options:
--format, -f [csv] -> Format for output file { Value should be one of [html, csv, pdf] }
--debug, -d [false] -> Turn on debug mode
--eps [0.01] -> Observational error { Double }
--help, -h -> Usage info
```## Subcommands
If application has rich command line interface and executes different actions with different arguments,
subcommands can be useful.
```kotlin
@file:OptIn(ExperimentalCli::class)import kotlinx.cli.*
fun main(args: Array) {
val parser = ArgParser("example")
val output by parser.option(ArgType.String, "output", "o", "Output file")
class Summary: Subcommand("summary", "Calculate summary") {
val invert by option(ArgType.Boolean, "invert", "i", "Invert results").default(false)
val addendums by argument(ArgType.Int, "addendums", description = "Addendums").vararg()
var result: Int = 0override fun execute() {
result = addendums.sum()
result = if (invert!!) -1 * result else result
}
}
class Multiply: Subcommand("mul", "Multiply") {
val numbers by argument(ArgType.Int, description = "Addendums").vararg()
var result: Int = 0override fun execute() {
result = numbers.reduce{ acc, it -> acc * it }
}
}
val summary = Summary()
val multiple = Multiply()
parser.subcommands(summary, multiple)parser.parse(args)
}
```Then help information will be available for each subcommand separately.
In case of `example summary -h` help info will be
```
Usage: example summary options_list
Arguments:
addendums -> Addendums { Int }
Options:
--invert, -i -> Invert results
--help, -h -> Usage info
```In case of `example mul -h` help info will be
```
Usage: example mul options_list
Arguments:
numbers -> Addendums { Int }
Options:
--help, -h -> Usage info
```
The boolean property `strictSubcommandOptionsOrder` defines the allowed order of options and arguments for subcommands.
When it is `false` (default), then the main program's options can be specified everywhere, even after the subcommand.
Otherwise, parameters can only be specified after the subcommands where they are defined. For example,```kotlin
@file:OptIn(ExperimentalCli::class)import kotlinx.cli.*
fun main(args: Array) {
val parser = ArgParser("example", strictSubcommandOptionsOrder = true)
val output by parser.option(ArgType.String, "output", "o", "Output file")class Multiply: Subcommand("mul", "Multiply") {
val numbers by argument(ArgType.Int, description = "Addendums").vararg()
var result: Int = 0override fun execute() {
result = numbers.reduce{ acc, it -> acc * it }
}
}
val multiple = Multiply()
parser.subcommands(summary, multiple)parser.parse(args)
}
```
`example -o out.txt mul 1 2 3 -o out.txt # OK``example mul 1 2 3 -o out.txt # fail in this case, but OK if strictSubcommandOptionsOrder is false`