improve argument parsing

fail fast by parsing arguments before command execution instead of on demand
This commit is contained in:
2025-12-28 00:16:50 +01:00
parent 79629ae68d
commit f1185886d4
2 changed files with 12 additions and 33 deletions

View File

@@ -95,9 +95,7 @@ class Command private constructor(
) )
} }
fun cli( fun cli(block: Command.Builder.() -> Unit): Command {
block: Command.Builder.() -> Unit,
): Command {
val builder = Command.Builder(-1, null) val builder = Command.Builder(-1, null)
builder.block() builder.block()
return builder.build() return builder.build()

View File

@@ -12,11 +12,7 @@ class Execution private constructor(
val arguments: List<Arg>, val arguments: List<Arg>,
) { ) {
companion object { companion object {
fun from( fun from(command: Command, cmd: List<String>, arg: List<String>): Execution {
command: Command,
cmd: List<String>,
arg: List<String>,
): Execution {
val commands = Cmd.from(cmd) val commands = Cmd.from(cmd)
val arguments = Arg.from(command, arg) val arguments = Arg.from(command, arg)
return Execution(commands, arguments) return Execution(commands, arguments)
@@ -33,7 +29,7 @@ class Execution private constructor(
class Arg( class Arg(
val name: String, val name: String,
val value: String?, val value: Any,
) { ) {
companion object { companion object {
fun from(command: Command, arg: List<String>): List<Arg> = buildList { fun from(command: Command, arg: List<String>): List<Arg> = buildList {
@@ -68,10 +64,10 @@ class Execution private constructor(
} }
for (name in names) { for (name in names) {
if (command.arguments.none { name in it.names }) val argument = command.arguments.firstOrNull { name in it.names }
throw UnknownArgumentException(name) ?: throw UnknownArgumentException(name)
//TODO parse early val value = argument.parser.parse(value) as Any
add(Arg(name, value)) add(Arg(name, value))
} }
i++ i++
@@ -88,26 +84,11 @@ class Execution private constructor(
} }
} }
operator fun Command.Key.getValue( operator fun Command.Key.getValue(thisRef: Any?, property: KProperty<*>): String = commands[index].name
thisRef: Any?,
property: KProperty<*>,
): String = commands[index].name
operator fun <T> Argument.Single<T>.getValue( @Suppress("UNCHECKED_CAST")
thisRef: Any?, private fun <T> Argument<T>.getValue(): T? = arguments.firstOrNull { it.name in names }?.value as? T
property: KProperty<*>, operator fun <T> Argument.Single<T>.getValue(thisRef: Any?, property: KProperty<*>): T = getValue()!!
): T = arguments.single { it.name in names } operator fun <T> Argument.SingleOrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = getValue() ?: other
.let { parser.parse(it.value) } operator fun <T> Argument.SingleOrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = getValue()
operator fun <T> Argument.SingleOrElse<T>.getValue(
thisRef: Any?,
property: KProperty<*>,
): T = arguments.singleOrNull { it.name in names }
?.let { parser.parse(it.value) } ?: other
operator fun <T> Argument.SingleOrNull<T>.getValue(
thisRef: Any?,
property: KProperty<*>,
): T? = arguments.singleOrNull { it.name in names }
?.let { parser.parse(it.value) }
} }