Skip to content

Commit

Permalink
Add Context.allowGroupedShortOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
ajalt committed Jun 18, 2023
1 parent 4b0fe73 commit 2968109
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Clikt will now report multiple errors if they occur, rather than just the first. ([#367](https://github.com/ajalt/clikt/issues/367))
- Added `CliktCommand.allHelpParams()`, which can be overridden to change which parameters are displayed in help output
- Added `Context.argumentFileReader` which allows custom loading of argument files
- Added `Context.allowGroupedShortOptions` which can disable parsing `-abc` as `-a -b -c`

### Changed
- `prompt` and `confirm` are now implemented with mordant's prompt functionality, and the method parameters have changed to match mordant's
Expand Down
10 changes: 10 additions & 0 deletions clikt/src/commonMain/kotlin/com/github/ajalt/clikt/core/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ typealias TypoSuggestor = (enteredValue: String, possibleValues: List<String>) -
* @property correctionSuggestor A callback called when the command line contains an invalid option or
* subcommand name. It takes the entered name and a list of all registered names option/subcommand
* names and filters the list down to values to suggest to the user.
* @property allowGroupedShortOptions If true, short options can be grouped after a single `-` prefix.
*/

class Context private constructor(
val parent: Context?,
val command: CliktCommand,
val allowInterspersedArgs: Boolean,
val allowGroupedShortOptions: Boolean,
val autoEnvvarPrefix: String?,
val printExtraMessages: Boolean,
val helpOptionNames: Set<String>,
Expand Down Expand Up @@ -113,6 +115,13 @@ class Context private constructor(
*/
var allowInterspersedArgs: Boolean = parent?.allowInterspersedArgs ?: true

/**
* If true, short options can be grouped together after a single `-`.
*
* For example, `-abc` is equivalent to `-a -b -c`. Set to false to disable this behavior.
*/
var allowGroupedShortOptions: Boolean = true

/**
* Set this to false to prevent extra messages from being printed automatically.
*
Expand Down Expand Up @@ -243,6 +252,7 @@ class Context private constructor(
parent,
command,
interspersed,
allowGroupedShortOptions,
autoEnvvarPrefix,
printExtraMessages,
helpOptionNames.toSet(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ internal object Parser {
val normTok = context.tokenTransformer(context, tok)
val prefix = splitOptionPrefix(tok).first
when {
canExpandAtFiles && tok.startsWith("@") && normTok !in optionsByName -> {
canExpandAtFiles
&& tok.startsWith("@")
&& normTok !in optionsByName -> {
if (tok.startsWith("@@")) {
positionalArgs += i to tok.drop(1)
i += 1
Expand All @@ -122,7 +124,8 @@ internal object Parser {
}
}

canParseOptions && tok == "--" -> {
canParseOptions
&& tok == "--" -> {
i += 1
canParseOptions = false
canExpandAtFiles = false
Expand All @@ -132,6 +135,7 @@ internal object Parser {
prefix.length > 1 && prefix in prefixes
|| normTok in longNames
|| isLongOptionWithEquals(prefix, tok)
|| !context.allowGroupedShortOptions
) -> {
consumeParse(
i,
Expand All @@ -147,7 +151,10 @@ internal object Parser {
)
}

canParseOptions && tok.length >= 2 && prefix.isNotEmpty() && prefix in prefixes -> {
canParseOptions
&& tok.length >= 2
&& prefix.isNotEmpty()
&& prefix in prefixes -> {
consumeParse(
i,
parseShortOpt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,27 @@ class OptionTest {
}
C().parse(argv)
}

@Test
@JsName("disable_allowGroupedShortOptions")
fun `disable allowGroupedShortOptions`() {
class C(called: Boolean) : TestCommand(called) {
init {
context { allowGroupedShortOptions = false }
}
val x by option("-x").flag()
val y by option("-y")
}

with(C(true).parse("-x -y 1")) {
x shouldBe true
y shouldBe "1"
}

shouldThrow<NoSuchOption> {
C(false).parse("-xy")
}.formattedMessage shouldBe "no such option: -xy. Did you mean -x?"
}
}


Expand Down
6 changes: 6 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ line:
true true Foo
```

!!! tip

You can diasable short option grouping by setting
[`Context.allowGroupedShortOptions`][allowGroupedShortOptions] to `false`.

## Counted Flag Options

You might want a flag option that counts the number of times it occurs on the command line. You can
Expand Down Expand Up @@ -1189,6 +1194,7 @@ val opt: Pair<Int, Int> by option("-o", "--opt")

[Abort]: api/clikt/com.github.ajalt.clikt.core/-abort/index.html
[allowInterspersedArgs]: api/clikt/com.github.ajalt.clikt.core/-context/allow-interspersed-args.html
[allowGroupedShortOptions]: api/clikt/com.github.ajalt.clikt.core/-context/allow-grouped-short-options.html
[argument.multiple]: api/clikt/com.github.ajalt.clikt.parameters.arguments/multiple.html
[associate]: api/clikt/com.github.ajalt.clikt.parameters.options/associate.html
[choice-options]: #choice-options
Expand Down
5 changes: 0 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
VERSION_NAME=4.0.0

kotlin.native.ignoreDisabledTargets=true

# https://github.com/gradle/gradle/issues/11308
systemProp.org.gradle.internal.publish.checksums.insecure=true

# Silence the compile warning that MPP is experimental
kotlin.mpp.stability.nowarn=true

Expand Down

0 comments on commit 2968109

Please sign in to comment.