
commonMain.com.github.ajalt.clikt.parameters.options.Convert.kt Maven / Gradle / Ivy
@file:JvmMultifileClass
@file:JvmName("OptionWithValuesKt")
package com.github.ajalt.clikt.parameters.options
import com.github.ajalt.clikt.completion.CompletionCandidates
import com.github.ajalt.clikt.core.BadParameterValue
import com.github.ajalt.clikt.core.UsageError
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* Convert the option's value type.
*
* The [conversion] is called once for each value in each invocation of the option. If any errors are thrown,
* they are caught and a [BadParameterValue] is thrown with the error message. You can call `fail` to throw a
* [BadParameterValue] manually.
*
* You can call `convert` more than once to wrap the result of the previous `convert`, but it cannot
* be called after [transformAll] (e.g. [multiple]) or [transformValues] (e.g. [pair]).
*
* ## Example
*
* ```
* val bd: BigDecimal? by option().convert { it.toBigDecimal() }
* val fileText: ByteArray? by option().file().convert { it.readBytes() }
* ```
*
* @param metavar The metavar for the type. Overridden by a metavar passed to [option].
* @param envvarSplit If the value is read from an envvar, the pattern to split the value on. The default
* splits on whitespace. This value is can be overridden by passing a value to the [option] function.
* @param completionCandidates candidates to use when completing this option in shell autocomplete,
* if no candidates are specified in [option]
*/
inline fun NullableOption.convert(
metavar: String = "VALUE",
envvarSplit: Regex = this.envvarSplit.default,
completionCandidates: CompletionCandidates = completionCandidatesWithDefault.default,
crossinline conversion: ValueConverter
): NullableOption {
val proc: ValueTransformer = {
try {
conversion(transformValue(it))
} catch (err: UsageError) {
err.paramName = name
throw err
} catch (err: Exception) {
fail(err.message ?: "")
}
}
return copy(proc, defaultEachProcessor(), defaultAllProcessor(), defaultValidator(),
metavarWithDefault = metavarWithDefault.copy(default = metavar),
envvarSplit = this.envvarSplit.copy(default = envvarSplit),
completionCandidatesWithDefault = completionCandidatesWithDefault.copy(default = completionCandidates)
)
}
/**
* Change to option to take any number of values, separated by a [regex].
*
* This must be called after converting the value type, and before other transforms.
*
* ### Example:
*
* ```
* val opt: List? by option().int().split(Regex(","))
* ```
*
* Which can be called like this:
*
* `./program --opt 1,2,3`
*/
fun NullableOption.split(regex: Regex)
: OptionWithValues?, List, ValueT> {
return copy(
transformValue = transformValue,
transformEach = { it },
transformAll = defaultAllProcessor(),
validator = defaultValidator(),
nvalues = 1,
valueSplit = regex
)
}
/**
* Change to option to take any number of values, separated by a string [delimiter].
*
* This must be called after converting the value type, and before other transforms.
*
* ### Example:
*
* ```
* val opt: List? by option().int().split(",")
* ```
*
* Which can be called like this:
*
* `./program --opt 1,2,3`
*/
fun NullableOption.split(delimiter: String)
: OptionWithValues?, List, ValueT> {
return split(Regex.fromLiteral(delimiter))
}
/**
* Split this option's value into two with a [delimiter].
*
* If the delimiter is not present in the value, the [second][Pair.second] part of the pair will be
* an empty string. You can use [validate] to reject these values.
*
* You cannot call [convert] before this function, but you can call it after.
*
* ### Example:
*
* ```
* val opt: option("-o").splitPair()
* ```
*
* Which can be called like this:
*
* `./program -o key=value`
*/
fun RawOption.splitPair(delimiter: String = "="): NullableOption, Pair> {
return convert { it.substringBefore(delimiter) to it.substringAfter(delimiter, missingDelimiterValue = "") }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy