diff --git a/CHANGELOG.md b/CHANGELOG.md index e2ffad7b..46eb1f25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - Added support for aliasing options to other options. ([#535](https://github.com/ajalt/clikt/pull/535)) ### Changed -- In a subcommand with `argument().multiple()`, the behavior is now the same regardless of the value of `allowMultipleSubcommands`: if a token matches a subcommand name, it's now treated as a subcommand rather than a positional argument. +- In a subcommand with and an `argument()` with `multiple()` or `optional()`, the behavior is now the same regardless of the value of `allowMultipleSubcommands`: if a token matches a subcommand name, it's now treated as a subcommand rather than a positional argument. - Due to changes to the internal parsing algorithm, the exact details of error messages when multiple usage errors occur have changed in some cases. - **Breaking Change:** Moved the following parameters from `CliktCommand`'s constructor; override the corresponding properties instead: diff --git a/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/core/CliktCommandTest.kt b/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/core/CliktCommandTest.kt index bb844458..def2920b 100644 --- a/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/core/CliktCommandTest.kt +++ b/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/core/CliktCommandTest.kt @@ -2,6 +2,7 @@ package com.github.ajalt.clikt.core import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.multiple +import com.github.ajalt.clikt.parameters.arguments.optional import com.github.ajalt.clikt.parameters.groups.OptionGroup import com.github.ajalt.clikt.parameters.groups.cooccurring import com.github.ajalt.clikt.parameters.groups.mutuallyExclusiveOptions @@ -10,9 +11,7 @@ import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.required import com.github.ajalt.clikt.parameters.types.int -import com.github.ajalt.clikt.testing.TestCommand -import com.github.ajalt.clikt.testing.parse -import com.github.ajalt.clikt.testing.test +import com.github.ajalt.clikt.testing.* import com.github.ajalt.clikt.testing.withEnv import io.kotest.assertions.throwables.shouldThrow import io.kotest.data.blocking.forAll diff --git a/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/parameters/SubcommandTest.kt b/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/parameters/SubcommandTest.kt index 8c107269..c54f45af 100644 --- a/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/parameters/SubcommandTest.kt +++ b/clikt-mordant/src/commonTest/kotlin/com/github/ajalt/clikt/parameters/SubcommandTest.kt @@ -3,6 +3,7 @@ package com.github.ajalt.clikt.parameters import com.github.ajalt.clikt.core.* import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.multiple +import com.github.ajalt.clikt.parameters.arguments.optional import com.github.ajalt.clikt.parameters.arguments.pair import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.option @@ -338,6 +339,18 @@ class SubcommandTest { } } + @Test + @JsName("multiple_subcommands_optional_sub_arg") + fun `multiple subcommands optional sub arg`() { + class Sub: TestCommand(count = 2) { + val a by argument().optional() + } + class C: TestCommand(allowMultipleSubcommands = true) + val sub = Sub() + C().subcommands(sub).parse("sub sub b") + sub.a shouldBe "b" + } + @Test @JsName("multiple_subcommands_with_nesting") fun `multiple subcommands with nesting`() { diff --git a/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/parsers/ParserInternals.kt b/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/parsers/ParserInternals.kt index 1e33e4ff..0e9a4b51 100644 --- a/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/parsers/ParserInternals.kt +++ b/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/parsers/ParserInternals.kt @@ -77,7 +77,9 @@ private class CommandParser>( private val errors = mutableListOf() private var i = startingIndex private var minAliasI = i - private val minArgCount = command._arguments.sumOf { it.nvalues.coerceAtLeast(0) } + private val minArgCount = command._arguments.sumOf { + if (it.required) it.nvalues.coerceAtLeast(0) else 0 + } private val canParseSubcommands get() = argumentTokens.size >= minArgCount private var canParseOptions = true private var canExpandAtFiles = context.expandArgumentFiles diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME