From 5ee4fb26f121cfa07edba61454558cd584781984 Mon Sep 17 00:00:00 2001 From: LepilkinaElena Date: Thu, 12 Mar 2020 19:02:53 +0300 Subject: [PATCH] Updated kotlinx.cli (v0.2.1) (#3967) --- .../src/main/kotlin/kotlinx/cli/ArgParser.kt | 15 ++++++- .../kotlinx.cli/src/tests/HelpTests.kt | 44 ++++++++++++++++++- .../kotlinx.cli/src/tests/SubcommandsTests.kt | 12 ++--- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt b/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt index a9faa17b713..6546b649770 100644 --- a/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt +++ b/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt @@ -71,11 +71,14 @@ interface ArgumentValueDelegate { * Abstract base class for subcommands. */ @ExperimentalCli -abstract class Subcommand(val name: String): ArgParser(name) { +abstract class Subcommand(val name: String, val actionDescription: String): ArgParser(name) { /** * Execute action if subcommand was provided. */ abstract fun execute() + + val helpMessage: String + get() = " $name - $actionDescription\n" } /** @@ -309,7 +312,7 @@ open class ArgParser( * * @param message error message. */ - fun printError(message: String): Nothing { + fun printError(message: String): Nothing { error("$message\n${makeUsage()}") } @@ -373,6 +376,7 @@ open class ArgParser( protected fun parse(args: List): ArgParserResult { check(parsingState == null) { "Parsing of command line options can be called only once." } + // Add help option. val helpDescriptor = if (useDefaultHelpShortName) OptionDescriptor( optionFullFormPrefix, @@ -513,6 +517,13 @@ open class ArgParser( internal fun makeUsage(): String { val result = StringBuilder() result.append("Usage: ${fullCommandName.joinToString(" ")} options_list\n") + if (subcommands.isNotEmpty()) { + result.append("Subcommands: \n") + subcommands.forEach { (_, subcommand) -> + result.append(subcommand.helpMessage) + } + result.append("\n") + } if (arguments.isNotEmpty()) { result.append("Arguments: \n") arguments.forEach { diff --git a/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt b/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt index 973a0cd4197..31ca3f19790 100644 --- a/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt +++ b/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt @@ -48,7 +48,7 @@ Options: @Test fun testHelpForSubcommands() { - class Summary: Subcommand("summary") { + class Summary: Subcommand("summary", "Get summary information") { val exec by option(ArgType.Choice(listOf("samples", "geomean")), description = "Execution time way of calculation").default("geomean") val execSamples by option(ArgType.String, "exec-samples", @@ -96,6 +96,48 @@ Options: --codesize-normalize -> File with golden results which should be used for normalization { String } --user, -u -> User access information for authorization { String } --help, -h -> Usage info +""".trimIndent() + assertEquals(expectedOutput, helpOutput) + } + + @Test + fun testHelpMessageWithSubcommands() { + abstract class CommonOptions(name: String, actionDescription: String): Subcommand(name, actionDescription) { + val numbers by argument(ArgType.Int, "numbers", description = "Numbers").vararg() + } + class Summary: CommonOptions("summary", "Calculate summary") { + val invert by option(ArgType.Boolean, "invert", "i", "Invert results") + var result: Int = 0 + + override fun execute() { + result = numbers.sum() + result = invert?.let { -1 * result } ?: result + } + } + + class Subtraction : CommonOptions("sub", "Calculate subtraction") { + var result: Int = 0 + + override fun execute() { + result = numbers.map { -it }.sum() + } + } + + val summaryAction = Summary() + val subtractionAction = Subtraction() + val argParser = ArgParser("testParser") + argParser.subcommands(summaryAction, subtractionAction) + argParser.parse(emptyArray()) + val helpOutput = argParser.makeUsage().trimIndent() + println(helpOutput) + val expectedOutput = """ +Usage: testParser options_list +Subcommands: + summary - Calculate summary + sub - Calculate subtraction + +Options: + --help, -h -> Usage info """.trimIndent() assertEquals(expectedOutput, helpOutput) } diff --git a/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt b/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt index acaf848c77a..c0d73c415ee 100644 --- a/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt +++ b/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt @@ -16,7 +16,7 @@ class SubcommandsTests { fun testSubcommand() { val argParser = ArgParser("testParser") val output by argParser.option(ArgType.String, "output", "o", "Output file") - class Summary: Subcommand("summary") { + class Summary: Subcommand("summary", "Calculate summary") { val invert by option(ArgType.Boolean, "invert", "i", "Invert results") val addendums by argument(ArgType.Int, "addendums", description = "Addendums").vararg() var result: Int = 0 @@ -35,10 +35,10 @@ class SubcommandsTests { @Test fun testCommonOptions() { - abstract class CommonOptions(name: String): Subcommand(name) { + abstract class CommonOptions(name: String, actionDescription: String): Subcommand(name, actionDescription) { val numbers by argument(ArgType.Int, "numbers", description = "Numbers").vararg() } - class Summary: CommonOptions("summary") { + class Summary: CommonOptions("summary", "Calculate summary") { val invert by option(ArgType.Boolean, "invert", "i", "Invert results") var result: Int = 0 @@ -48,7 +48,7 @@ class SubcommandsTests { } } - class Subtraction : CommonOptions("sub") { + class Subtraction : CommonOptions("sub", "Calculate subtraction") { var result: Int = 0 override fun execute() { @@ -73,7 +73,7 @@ class SubcommandsTests { fun testRecursiveSubcommands() { val argParser = ArgParser("testParser") - class Summary: Subcommand("summary") { + class Summary: Subcommand("summary", "Calculate summary") { val addendums by argument(ArgType.Int, "addendums", description = "Addendums").vararg() var result: Int = 0 @@ -82,7 +82,7 @@ class SubcommandsTests { } } - class Calculation: Subcommand("calc") { + class Calculation: Subcommand("calc", "Execute calculation") { init { subcommands(Summary()) }