From 0a8e51c7aba52a82c2863459890f8c4f1b92d12c Mon Sep 17 00:00:00 2001 From: Infendro Date: Tue, 6 Jan 2026 11:12:45 +0100 Subject: [PATCH] improve argument/option declaration --- src/commonMain/kotlin/com/infendro/cli/Dsl.kt | 4 +++ .../com/infendro/cli/command/Argument.kt | 33 ++++++----------- .../com/infendro/cli/command/Command.kt | 15 ++++---- .../kotlin/com/infendro/cli/command/Option.kt | 36 ++++++++----------- .../infendro/cli/command/context/Context.kt | 2 ++ .../cli/exception/run/ExecuteException.kt | 5 +++ .../com/infendro/cli/parser/DoubleParser.kt | 7 ++-- .../com/infendro/cli/parser/EnumParser.kt | 7 ++-- .../com/infendro/cli/parser/FloatParser.kt | 7 ++-- .../com/infendro/cli/parser/IntParser.kt | 7 ++-- .../com/infendro/cli/parser/LongParser.kt | 7 ++-- 11 files changed, 55 insertions(+), 75 deletions(-) create mode 100644 src/commonMain/kotlin/com/infendro/cli/Dsl.kt create mode 100644 src/commonMain/kotlin/com/infendro/cli/exception/run/ExecuteException.kt diff --git a/src/commonMain/kotlin/com/infendro/cli/Dsl.kt b/src/commonMain/kotlin/com/infendro/cli/Dsl.kt new file mode 100644 index 0000000..5705e9a --- /dev/null +++ b/src/commonMain/kotlin/com/infendro/cli/Dsl.kt @@ -0,0 +1,4 @@ +package com.infendro.cli + +@DslMarker +internal annotation class Dsl() diff --git a/src/commonMain/kotlin/com/infendro/cli/command/Argument.kt b/src/commonMain/kotlin/com/infendro/cli/command/Argument.kt index 7b6c945..6a1ad1b 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/Argument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/Argument.kt @@ -41,28 +41,17 @@ sealed class Argument( } companion object { - fun string() = - Required(StringParser) + fun string() = argument(StringParser) + fun int() = argument(IntParser) + fun long() = argument(LongParser) + fun float() = argument(FloatParser) + fun double() = argument(DoubleParser) + fun boolean() = argument(BooleanParser) - fun int() = - Required(IntParser) - - fun long() = - Required(LongParser) - - fun float() = - Required(FloatParser) - - fun double() = - Required(DoubleParser) - - fun boolean() = - Required(BooleanParser) - - inline fun > enum() = - Required(enumParser()) - - fun regex() = - Required(RegexParser) + inline fun > enum() = argument(enumParser()) + fun regex() = argument(RegexParser) } } + +fun argument(parser: Parser) = + Argument.Required(parser) diff --git a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt index 3936b1e..0d2d78d 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt @@ -1,11 +1,13 @@ package com.infendro.cli.command +import com.infendro.cli.Dsl import com.infendro.cli.command.context.Context import com.infendro.cli.command.context.Parser import com.infendro.cli.exception.build.* import com.infendro.cli.exception.run.CliException import com.infendro.cli.util.Regex.COMMAND import com.infendro.cli.util.Regex.OPTION +import kotlin.reflect.KProperty class Command private constructor( val name: String?, @@ -23,6 +25,7 @@ class Command private constructor( println(e.message) } + @Dsl class Builder internal constructor( private val level: Int, private val name: String?, @@ -68,10 +71,10 @@ class Command private constructor( arguments += argument } - fun > T.register() = also(::argument) - fun arguments(vararg arguments: Argument<*>) = arguments.forEach(::argument) - fun > Array.register() = also(::arguments) + + operator fun > T.provideDelegate(thisRef: Nothing?, property: KProperty<*>) = also(::argument) + operator fun > T.getValue(thisRef: Nothing?, property: KProperty<*>) = this fun option(option: Option<*>) { // validate @@ -85,10 +88,10 @@ class Command private constructor( options += option } - fun > T.register() = also(::option) - fun options(vararg options: Option<*>) = options.forEach(::option) - fun > Array.register() = also(::options) + + operator fun > T.provideDelegate(thisRef: Nothing?, property: KProperty<*>) = also(::option) + operator fun > T.getValue(thisRef: Nothing?, property: KProperty<*>) = this fun execute(block: Context.() -> Unit) { if (::_execute.isInitialized) diff --git a/src/commonMain/kotlin/com/infendro/cli/command/Option.kt b/src/commonMain/kotlin/com/infendro/cli/command/Option.kt index ab39039..5866018 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/Option.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/Option.kt @@ -84,28 +84,20 @@ sealed class Option( } companion object { - fun string(vararg names: String) = - Required(StringParser, names.asList()) + fun string(vararg names: String) = option(StringParser, *names) + fun int(vararg names: String) = option(IntParser, *names) + fun long(vararg names: String) = option(LongParser, *names) + fun float(vararg names: String) = option(FloatParser, *names) + fun double(vararg names: String) = option(DoubleParser, *names) + fun boolean(vararg names: String) = option(BooleanParser, true, *names) - fun int(vararg names: String) = - Required(IntParser, names.asList()) - - fun long(vararg names: String) = - Required(LongParser, names.asList()) - - fun float(vararg names: String) = - Required(FloatParser, names.asList()) - - fun double(vararg names: String) = - Required(DoubleParser, names.asList()) - - fun boolean(vararg names: String) = - Required(BooleanParser, true, names.asList()) - - inline fun > enum(vararg names: String) = - Required(enumParser(), names.asList()) - - fun regex(vararg names: String) = - Required(RegexParser, names.asList()) + inline fun > enum(vararg names: String) = option(enumParser(), *names) + fun regex(vararg names: String) = option(RegexParser, *names) } } + +fun option(parser: Parser, vararg names: String) = + Option.Required(parser, names.asList()) + +fun option(parser: Parser, fallback: T, vararg names: String) = + Option.Required(parser, fallback, names.asList()) diff --git a/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt b/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt index 037d2e4..b1e53ad 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt @@ -1,10 +1,12 @@ package com.infendro.cli.command.context +import com.infendro.cli.Dsl import com.infendro.cli.command.Argument import com.infendro.cli.command.Command import com.infendro.cli.command.Option import kotlin.reflect.KProperty +@Dsl class Context internal constructor( val command: Command, val commands: List, diff --git a/src/commonMain/kotlin/com/infendro/cli/exception/run/ExecuteException.kt b/src/commonMain/kotlin/com/infendro/cli/exception/run/ExecuteException.kt new file mode 100644 index 0000000..b826d7b --- /dev/null +++ b/src/commonMain/kotlin/com/infendro/cli/exception/run/ExecuteException.kt @@ -0,0 +1,5 @@ +package com.infendro.cli.exception.run + +class ExecuteException( + override val message: String, +) : CliException() diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/DoubleParser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/DoubleParser.kt index 0efcf27..df2cea5 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/DoubleParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/DoubleParser.kt @@ -3,9 +3,6 @@ package com.infendro.cli.parser import com.infendro.cli.exception.run.ParseException object DoubleParser : Parser { - override fun parse(text: String): Double = try { - text.toDouble() - } catch (_: Exception) { - throw ParseException(text, "Double") - } + override fun parse(text: String): Double = text.toDoubleOrNull() + ?: throw ParseException(text, "Double") } diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/EnumParser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/EnumParser.kt index b4247a4..30dfa79 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/EnumParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/EnumParser.kt @@ -7,11 +7,8 @@ class EnumParser>( private val name: String, private val values: List, ) : Parser { - override fun parse(text: String): T = try { - values.first { it.name == text } - } catch (_: Exception) { - throw ParseException(text, name) - } + override fun parse(text: String): T = values.firstOrNull { it.name == text } + ?: throw ParseException(text, name) } inline fun > enumParser() = EnumParser(T::class.simpleName!!, enumEntries()) diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/FloatParser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/FloatParser.kt index 28434c3..cdef5ec 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/FloatParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/FloatParser.kt @@ -3,9 +3,6 @@ package com.infendro.cli.parser import com.infendro.cli.exception.run.ParseException object FloatParser : Parser { - override fun parse(text: String): Float = try { - text.toFloat() - } catch (_: Exception) { - throw ParseException(text, "Float") - } + override fun parse(text: String): Float = text.toFloatOrNull() + ?: throw ParseException(text, "Float") } diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/IntParser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/IntParser.kt index 750920a..33be4af 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/IntParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/IntParser.kt @@ -3,9 +3,6 @@ package com.infendro.cli.parser import com.infendro.cli.exception.run.ParseException object IntParser : Parser { - override fun parse(text: String): Int = try { - text.toInt() - } catch (_: Exception) { - throw ParseException(text, "Int") - } + override fun parse(text: String): Int = text.toIntOrNull() + ?: throw ParseException(text, "Int") } diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/LongParser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/LongParser.kt index 8072f83..a234ab7 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/LongParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/LongParser.kt @@ -3,9 +3,6 @@ package com.infendro.cli.parser import com.infendro.cli.exception.run.ParseException object LongParser : Parser { - override fun parse(text: String): Long = try { - text.toLong() - } catch (_: Exception) { - throw ParseException(text, "Long") - } + override fun parse(text: String): Long = text.toLongOrNull() + ?: throw ParseException(text, "Long") }