Files
cli.kt/src/commonMain/kotlin/com/infendro/cli/option/Option.kt
2026-01-17 15:57:05 +01:00

84 lines
2.2 KiB
Kotlin

package com.infendro.cli.option
import com.infendro.cli.exception.InvalidOptionName
import com.infendro.cli.exception.InvalidRange
import com.infendro.cli.exception.MissingOptionName
import com.infendro.cli.parser.Parser
import com.infendro.cli.util.Regex.OPTION
sealed class Option<T : Any>(
val parser: Parser<T>,
val fallback: T?,
val names: List<String>,
val description: String?,
val min: Int,
val max: Int?,
) {
val name: String
get() = names.maxBy { it.length }
val flag: Boolean
get() = fallback != null
val required: Boolean
get() = min > 0
val optional: Boolean
get() = !required
val bounded: Boolean
get() = max != null
val unbounded: Boolean
get() = !bounded
val count: Int
get() = max ?: Int.MAX_VALUE
init {
when {
names.isEmpty() -> throw MissingOptionName()
names.any { !it.matches(OPTION) } -> throw InvalidOptionName(name)
min !in 0..count || max == 0 -> throw InvalidRange()
}
}
class Required<T : Any>(
parser: Parser<T>,
fallback: T?,
names: List<String>,
description: String?,
) : Option<T>(parser, fallback, names, description, min = 1, max = 1) {
fun orElse(other: T) =
OrElse(parser, fallback, names, description, other)
fun orNull() =
OrNull(parser, fallback, names, description)
fun variable(min: Int = 0, max: Int? = null) =
Variable(parser, fallback, names, description, min, max)
}
class OrElse<T : Any>(
parser: Parser<T>,
fallback: T?,
names: List<String>,
description: String?,
val other: T,
) : Option<T>(parser, fallback, names, description, min = 0, max = 1)
class OrNull<T : Any>(
parser: Parser<T>,
fallback: T?,
names: List<String>,
description: String?,
) : Option<T>(parser, fallback, names, description, min = 0, max = 1)
class Variable<T : Any>(
parser: Parser<T>,
fallback: T?,
names: List<String>,
description: String?,
min: Int,
max: Int?,
) : Option<T>(parser, fallback, names, description, min, max)
}