From 54972c36b6159a80313c5910bd95e5edb61dcd80 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 10 Jan 2026 09:32:55 +0100 Subject: [PATCH 1/8] refactor package structure --- .../com/infendro/cli/{command => }/argument/Argument.kt | 2 +- .../infendro/cli/{command => }/argument/ArgumentFactory.kt | 2 +- src/commonMain/kotlin/com/infendro/cli/command/Command.kt | 4 ++-- .../kotlin/com/infendro/cli/command/context/Context.kt | 4 ++-- .../com/infendro/cli/command/help/DefaultHelpRenderer.kt | 4 ++-- .../kotlin/com/infendro/cli/error/build/DuplicateArgument.kt | 2 +- .../kotlin/com/infendro/cli/error/build/DuplicateOption.kt | 2 +- .../kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt | 2 +- .../kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt | 2 +- .../kotlin/com/infendro/cli/error/run/MissingOptionValue.kt | 2 +- .../kotlin/com/infendro/cli/{command => }/option/Option.kt | 2 +- .../com/infendro/cli/{command => }/option/OptionFactory.kt | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) rename src/commonMain/kotlin/com/infendro/cli/{command => }/argument/Argument.kt (97%) rename src/commonMain/kotlin/com/infendro/cli/{command => }/argument/ArgumentFactory.kt (96%) rename src/commonMain/kotlin/com/infendro/cli/{command => }/option/Option.kt (98%) rename src/commonMain/kotlin/com/infendro/cli/{command => }/option/OptionFactory.kt (97%) diff --git a/src/commonMain/kotlin/com/infendro/cli/command/argument/Argument.kt b/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt similarity index 97% rename from src/commonMain/kotlin/com/infendro/cli/command/argument/Argument.kt rename to src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt index 542e721..6d38dbb 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/argument/Argument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.command.argument +package com.infendro.cli.argument import com.infendro.cli.error.build.InvalidArgumentName import com.infendro.cli.error.build.InvalidRange diff --git a/src/commonMain/kotlin/com/infendro/cli/command/argument/ArgumentFactory.kt b/src/commonMain/kotlin/com/infendro/cli/argument/ArgumentFactory.kt similarity index 96% rename from src/commonMain/kotlin/com/infendro/cli/command/argument/ArgumentFactory.kt rename to src/commonMain/kotlin/com/infendro/cli/argument/ArgumentFactory.kt index 38fcf6e..4ecb7fd 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/argument/ArgumentFactory.kt +++ b/src/commonMain/kotlin/com/infendro/cli/argument/ArgumentFactory.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.command.argument +package com.infendro.cli.argument import com.infendro.cli.parser.* diff --git a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt index da59ca0..55ad40f 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt @@ -1,12 +1,12 @@ package com.infendro.cli.command import com.infendro.cli.Dsl -import com.infendro.cli.command.argument.Argument +import com.infendro.cli.argument.Argument import com.infendro.cli.command.context.Context import com.infendro.cli.command.context.ContextParser import com.infendro.cli.command.help.DefaultHelpRenderer import com.infendro.cli.command.help.HelpRenderer -import com.infendro.cli.command.option.Option +import com.infendro.cli.option.Option import com.infendro.cli.error.build.* import com.infendro.cli.parser.Parser import com.infendro.cli.util.Regex 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 9f1c866..e133305 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/context/Context.kt @@ -2,8 +2,8 @@ package com.infendro.cli.command.context import com.infendro.cli.Dsl import com.infendro.cli.command.Command -import com.infendro.cli.command.argument.Argument -import com.infendro.cli.command.option.Option +import com.infendro.cli.argument.Argument +import com.infendro.cli.option.Option import kotlin.reflect.KProperty @Dsl diff --git a/src/commonMain/kotlin/com/infendro/cli/command/help/DefaultHelpRenderer.kt b/src/commonMain/kotlin/com/infendro/cli/command/help/DefaultHelpRenderer.kt index 79febeb..e011648 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/help/DefaultHelpRenderer.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/help/DefaultHelpRenderer.kt @@ -1,8 +1,8 @@ package com.infendro.cli.command.help import com.infendro.cli.command.Command -import com.infendro.cli.command.argument.Argument -import com.infendro.cli.command.option.Option +import com.infendro.cli.argument.Argument +import com.infendro.cli.option.Option import kotlin.reflect.KClass object DefaultHelpRenderer : HelpRenderer { diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt b/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt index 5f3bbab..17ceb79 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt @@ -1,6 +1,6 @@ package com.infendro.cli.error.build -import com.infendro.cli.command.argument.Argument +import com.infendro.cli.argument.Argument class DuplicateArgument( val argument: Argument<*>, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt b/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt index 52f3c3b..5124de8 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt @@ -1,6 +1,6 @@ package com.infendro.cli.error.build -import com.infendro.cli.command.option.Option +import com.infendro.cli.option.Option class DuplicateOption( val option: Option<*>, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt b/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt index 6ac72f7..5073a93 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt @@ -1,6 +1,6 @@ package com.infendro.cli.error.run -import com.infendro.cli.command.argument.Argument +import com.infendro.cli.argument.Argument class InvalidArgumentCount( val argument: Argument<*>, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt b/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt index 848cdb8..c80c0f8 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt @@ -1,6 +1,6 @@ package com.infendro.cli.error.run -import com.infendro.cli.command.option.Option +import com.infendro.cli.option.Option class InvalidOptionCount( val option: Option<*>, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt b/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt index 49b1013..11b6f41 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt @@ -1,6 +1,6 @@ package com.infendro.cli.error.run -import com.infendro.cli.command.option.Option +import com.infendro.cli.option.Option class MissingOptionValue( val option: Option<*>, diff --git a/src/commonMain/kotlin/com/infendro/cli/command/option/Option.kt b/src/commonMain/kotlin/com/infendro/cli/option/Option.kt similarity index 98% rename from src/commonMain/kotlin/com/infendro/cli/command/option/Option.kt rename to src/commonMain/kotlin/com/infendro/cli/option/Option.kt index 8b2aca0..69c806d 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/option/Option.kt +++ b/src/commonMain/kotlin/com/infendro/cli/option/Option.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.command.option +package com.infendro.cli.option import com.infendro.cli.error.build.InvalidOptionName import com.infendro.cli.error.build.InvalidRange diff --git a/src/commonMain/kotlin/com/infendro/cli/command/option/OptionFactory.kt b/src/commonMain/kotlin/com/infendro/cli/option/OptionFactory.kt similarity index 97% rename from src/commonMain/kotlin/com/infendro/cli/command/option/OptionFactory.kt rename to src/commonMain/kotlin/com/infendro/cli/option/OptionFactory.kt index fea7dd1..1c3cbaa 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/option/OptionFactory.kt +++ b/src/commonMain/kotlin/com/infendro/cli/option/OptionFactory.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.command.option +package com.infendro.cli.option import com.infendro.cli.parser.* From 87e6e6580990c644442973411c60d08d6531f0e0 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 10 Jan 2026 15:12:36 +0100 Subject: [PATCH 2/8] improve string distance documentation --- src/commonMain/kotlin/com/infendro/cli/util/Distance.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/commonMain/kotlin/com/infendro/cli/util/Distance.kt b/src/commonMain/kotlin/com/infendro/cli/util/Distance.kt index b11ca6b..46977f2 100644 --- a/src/commonMain/kotlin/com/infendro/cli/util/Distance.kt +++ b/src/commonMain/kotlin/com/infendro/cli/util/Distance.kt @@ -3,7 +3,13 @@ package com.infendro.cli.util internal const val threshold = 2 /** - * Damerau-Levenshtein string distance + * Calculates the Damerau-Levenshtein distance between two strings. + * + * The distance is the minimum number of operations (insertion, deletion, substitution, and transposition) required to transform one string into another. + * + * @param a The source string. + * @param b The target string. + * @return The minimum number of operations to transform [a] into [b]. */ internal fun distance(a: String, b: String): Int { if (a == b) return 0 From dbd9d5305019d97e788d7dea5d1fdcee67b27bd9 Mon Sep 17 00:00:00 2001 From: Infendro Date: Tue, 13 Jan 2026 15:39:50 +0100 Subject: [PATCH 3/8] improve ci --- .gitea/workflows/ci.yaml | 47 ++++++++++++++++++++++++++++++++++++++ .gitea/workflows/main.yaml | 36 ----------------------------- 2 files changed, 47 insertions(+), 36 deletions(-) create mode 100644 .gitea/workflows/ci.yaml delete mode 100644 .gitea/workflows/main.yaml diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..a63d994 --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,47 @@ +on: + push: + branches: [ main ] + +jobs: + test: + runs-on: linux + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + java-version: '24' + distribution: 'temurin' + + - name: Cache Gradle + uses: actions/cache@v4 + with: + key: gradle-${{ hashFiles('**/libs.versions.toml') }} + restore-keys: gradle- + path: | + ~/.gradle/caches/ + ~/.gradle/wrapper/ + + - name: Cache Konan + uses: actions/cache@v4 + with: + key: konan-${{ hashFiles('**/libs.versions.toml') }} + restore-keys: konan- + path: | + ~/.konan/ + + - name: Cache Node + uses: actions/cache@v4 + with: + key: node-${{ hashFiles('**/libs.versions.toml') }} + restore-keys: node- + path: | + ~/.gradle/nodejs + ~/.gradle/yarn + + - name: Publish + run: ./gradlew publish + env: + INFENDRO__TOKEN: ${{ secrets.TOKEN }} diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml deleted file mode 100644 index 4885477..0000000 --- a/.gitea/workflows/main.yaml +++ /dev/null @@ -1,36 +0,0 @@ -on: - push: - branches: - - main - -env: - INFENDRO__TOKEN: ${{ secrets.TOKEN }} - -jobs: - publish: - runs-on: linux - steps: - - uses: actions/checkout@v4 - - - uses: actions/cache/restore@v4 - with: - key: gradle - path: | - ~/.gradle/caches/ - ~/.gradle/wrapper/ - ~/.konan/ - - - uses: actions/setup-java@v4 - with: - java-version: '24' - distribution: 'temurin' - - - run: ./gradlew publish - - - uses: actions/cache/save@v4 - with: - key: gradle - path: | - ~/.gradle/caches/ - ~/.gradle/wrapper/ - ~/.konan/ From a5b578a47d4e8b8622fa0f2064cf0e1be1cf41e9 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 17 Jan 2026 15:57:05 +0100 Subject: [PATCH 4/8] split error and exception --- .../kotlin/com/infendro/cli/argument/Argument.kt | 4 ++-- .../kotlin/com/infendro/cli/command/Command.kt | 4 ++-- .../infendro/cli/command/context/ContextParser.kt | 12 ++++++------ .../kotlin/com/infendro/cli/error/Error.kt | 5 +++++ .../cli/error/{run => }/InvalidArgumentCount.kt | 4 ++-- .../cli/error/{run => }/InvalidOptionCount.kt | 4 ++-- .../com/infendro/cli/error/{run => }/InvalidValue.kt | 4 ++-- .../infendro/cli/error/{run => }/MalformedOption.kt | 4 ++-- .../cli/error/{run => }/MissingOptionValue.kt | 4 ++-- .../cli/error/{run => }/UnexpectedArgument.kt | 4 ++-- .../infendro/cli/error/{run => }/UnknownCommand.kt | 4 ++-- .../infendro/cli/error/{run => }/UnknownOption.kt | 4 ++-- .../com/infendro/cli/error/run/RuntimeFailure.kt | 5 ----- .../cli/{error/build => exception}/BuildException.kt | 2 +- .../{error/build => exception}/DuplicateArgument.kt | 2 +- .../{error/build => exception}/DuplicateCommand.kt | 2 +- .../{error/build => exception}/DuplicateExecute.kt | 2 +- .../{error/build => exception}/DuplicateOption.kt | 2 +- .../{error/build => exception}/DuplicateRenderer.kt | 2 +- .../build => exception}/InvalidArgumentName.kt | 2 +- .../build => exception}/InvalidArgumentOrder.kt | 2 +- .../{error/build => exception}/InvalidCommandName.kt | 2 +- .../build => exception}/InvalidCommandOrder.kt | 2 +- .../{error/build => exception}/InvalidFallback.kt | 2 +- .../{error/build => exception}/InvalidOptionName.kt | 2 +- .../cli/{error/build => exception}/InvalidRange.kt | 2 +- .../{error/build => exception}/MissingOptionName.kt | 2 +- .../kotlin/com/infendro/cli/option/Option.kt | 6 +++--- .../kotlin/com/infendro/cli/parser/Parser.kt | 6 +++--- 29 files changed, 51 insertions(+), 51 deletions(-) create mode 100644 src/commonMain/kotlin/com/infendro/cli/error/Error.kt rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/InvalidArgumentCount.kt (90%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/InvalidOptionCount.kt (90%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/InvalidValue.kt (79%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/MalformedOption.kt (69%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/MissingOptionValue.kt (77%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/UnexpectedArgument.kt (71%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/UnknownCommand.kt (92%) rename src/commonMain/kotlin/com/infendro/cli/error/{run => }/UnknownOption.kt (92%) delete mode 100644 src/commonMain/kotlin/com/infendro/cli/error/run/RuntimeFailure.kt rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/BuildException.kt (54%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/DuplicateArgument.kt (85%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/DuplicateCommand.kt (84%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/DuplicateExecute.kt (77%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/DuplicateOption.kt (84%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/DuplicateRenderer.kt (76%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidArgumentName.kt (81%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidArgumentOrder.kt (77%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidCommandName.kt (81%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidCommandOrder.kt (77%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidFallback.kt (76%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidOptionName.kt (80%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/InvalidRange.kt (75%) rename src/commonMain/kotlin/com/infendro/cli/{error/build => exception}/MissingOptionName.kt (76%) diff --git a/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt b/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt index 6d38dbb..15f137c 100644 --- a/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/argument/Argument.kt @@ -1,7 +1,7 @@ package com.infendro.cli.argument -import com.infendro.cli.error.build.InvalidArgumentName -import com.infendro.cli.error.build.InvalidRange +import com.infendro.cli.exception.InvalidArgumentName +import com.infendro.cli.exception.InvalidRange import com.infendro.cli.parser.Parser import com.infendro.cli.util.Regex.ARGUMENT diff --git a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt index 55ad40f..88b8c85 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/Command.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/Command.kt @@ -6,8 +6,8 @@ import com.infendro.cli.command.context.Context import com.infendro.cli.command.context.ContextParser import com.infendro.cli.command.help.DefaultHelpRenderer import com.infendro.cli.command.help.HelpRenderer +import com.infendro.cli.exception.* import com.infendro.cli.option.Option -import com.infendro.cli.error.build.* import com.infendro.cli.parser.Parser import com.infendro.cli.util.Regex @@ -33,7 +33,7 @@ sealed class Command private constructor( if (help != null) print(help) } is ContextParser.Result.Failure -> { - println("error: ${result.failure.message}") + println("error: ${result.error.message}") val command = result.path.last() val help = command.renderer.render(result.path) if (help != null) print("\n$help") diff --git a/src/commonMain/kotlin/com/infendro/cli/command/context/ContextParser.kt b/src/commonMain/kotlin/com/infendro/cli/command/context/ContextParser.kt index 9cdde49..605c1bf 100644 --- a/src/commonMain/kotlin/com/infendro/cli/command/context/ContextParser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/command/context/ContextParser.kt @@ -1,7 +1,7 @@ package com.infendro.cli.command.context import com.infendro.cli.command.Command -import com.infendro.cli.error.run.* +import com.infendro.cli.error.* import com.infendro.cli.parser.Parser internal class ContextParser( @@ -19,13 +19,13 @@ internal class ContextParser( data class Failure( val path: List, - val failure: RuntimeFailure, + val error: Error, ) : Result() } private fun success(context: Context) = Result.Success(context) private fun help(path: List) = Result.Help(path) - private fun failure(path: List, exception: RuntimeFailure) = Result.Failure(path, exception) + private fun failure(path: List, error: Error) = Result.Failure(path, error) private var index = 0 private val current: String @@ -63,7 +63,7 @@ internal class ContextParser( if (cmd is Command.Fallback<*>) { val value = when (val result = cmd.parser.parse(current)) { is Parser.Result.Success<*> -> result.value - is Parser.Result.Failure<*> -> return failure(path, result.failure) + is Parser.Result.Failure<*> -> return failure(path, result.error) } commands[cmd.key] = value } @@ -91,7 +91,7 @@ internal class ContextParser( val value = when (val result = argument.parser.parse(current)) { is Parser.Result.Success<*> -> result.value - is Parser.Result.Failure<*> -> return failure(path, result.failure) + is Parser.Result.Failure<*> -> return failure(path, result.error) } arguments[argument]!! += value argumentCount++ @@ -141,7 +141,7 @@ internal class ContextParser( text != null -> when (val result = option.parser.parse(text)) { is Parser.Result.Success<*> -> result.value - is Parser.Result.Failure<*> -> return failure(path, result.failure) + is Parser.Result.Failure<*> -> return failure(path, result.error) } option.flag -> option.fallback!! else -> return failure(path, MissingOptionValue(option)) diff --git a/src/commonMain/kotlin/com/infendro/cli/error/Error.kt b/src/commonMain/kotlin/com/infendro/cli/error/Error.kt new file mode 100644 index 0000000..a3b6b26 --- /dev/null +++ b/src/commonMain/kotlin/com/infendro/cli/error/Error.kt @@ -0,0 +1,5 @@ +package com.infendro.cli.error + +abstract class Error { + abstract val message: String +} diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt b/src/commonMain/kotlin/com/infendro/cli/error/InvalidArgumentCount.kt similarity index 90% rename from src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt rename to src/commonMain/kotlin/com/infendro/cli/error/InvalidArgumentCount.kt index 5073a93..3149682 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidArgumentCount.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/InvalidArgumentCount.kt @@ -1,11 +1,11 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import com.infendro.cli.argument.Argument class InvalidArgumentCount( val argument: Argument<*>, val count: Int, -) : RuntimeFailure() { +) : Error() { override val message: String get() { val expected = when { diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt b/src/commonMain/kotlin/com/infendro/cli/error/InvalidOptionCount.kt similarity index 90% rename from src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt rename to src/commonMain/kotlin/com/infendro/cli/error/InvalidOptionCount.kt index c80c0f8..8a4acfc 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidOptionCount.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/InvalidOptionCount.kt @@ -1,11 +1,11 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import com.infendro.cli.option.Option class InvalidOptionCount( val option: Option<*>, val count: Int, -) : RuntimeFailure() { +) : Error() { override val message: String get() { val expected = when { diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidValue.kt b/src/commonMain/kotlin/com/infendro/cli/error/InvalidValue.kt similarity index 79% rename from src/commonMain/kotlin/com/infendro/cli/error/run/InvalidValue.kt rename to src/commonMain/kotlin/com/infendro/cli/error/InvalidValue.kt index ecf5d99..ab5e430 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/InvalidValue.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/InvalidValue.kt @@ -1,11 +1,11 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import kotlin.reflect.KClass class InvalidValue( val value: String, val type: KClass<*>, -) : RuntimeFailure() { +) : Error() { override val message: String get() = """"$value" cannot be converted to ${type.simpleName ?: "Unknown"}.""" } diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/MalformedOption.kt b/src/commonMain/kotlin/com/infendro/cli/error/MalformedOption.kt similarity index 69% rename from src/commonMain/kotlin/com/infendro/cli/error/run/MalformedOption.kt rename to src/commonMain/kotlin/com/infendro/cli/error/MalformedOption.kt index 097db35..98da6a5 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/MalformedOption.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/MalformedOption.kt @@ -1,8 +1,8 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error class MalformedOption( val option: String, -) : RuntimeFailure() { +) : Error() { override val message: String get() = """Malformed option "$option".""" } diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt b/src/commonMain/kotlin/com/infendro/cli/error/MissingOptionValue.kt similarity index 77% rename from src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt rename to src/commonMain/kotlin/com/infendro/cli/error/MissingOptionValue.kt index 11b6f41..ae2b086 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/MissingOptionValue.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/MissingOptionValue.kt @@ -1,10 +1,10 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import com.infendro.cli.option.Option class MissingOptionValue( val option: Option<*>, -) : RuntimeFailure() { +) : Error() { override val message: String get() = """No value provided for option "${option.name}".""" } diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/UnexpectedArgument.kt b/src/commonMain/kotlin/com/infendro/cli/error/UnexpectedArgument.kt similarity index 71% rename from src/commonMain/kotlin/com/infendro/cli/error/run/UnexpectedArgument.kt rename to src/commonMain/kotlin/com/infendro/cli/error/UnexpectedArgument.kt index 960d2d2..cf26ec8 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/UnexpectedArgument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/UnexpectedArgument.kt @@ -1,8 +1,8 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error class UnexpectedArgument( val argument: String, -) : RuntimeFailure() { +) : Error() { override val message: String get() = """Unexpected argument "$argument".""" } diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/UnknownCommand.kt b/src/commonMain/kotlin/com/infendro/cli/error/UnknownCommand.kt similarity index 92% rename from src/commonMain/kotlin/com/infendro/cli/error/run/UnknownCommand.kt rename to src/commonMain/kotlin/com/infendro/cli/error/UnknownCommand.kt index 643c51c..4429de2 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/UnknownCommand.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/UnknownCommand.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import com.infendro.cli.command.Command import com.infendro.cli.util.distance @@ -8,7 +8,7 @@ import kotlin.math.min class UnknownCommand( val command: Command, val name: String, -) : RuntimeFailure() { +) : Error() { override val message: String get() = buildString { val suggestion = command.commands diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/UnknownOption.kt b/src/commonMain/kotlin/com/infendro/cli/error/UnknownOption.kt similarity index 92% rename from src/commonMain/kotlin/com/infendro/cli/error/run/UnknownOption.kt rename to src/commonMain/kotlin/com/infendro/cli/error/UnknownOption.kt index cb01a69..d697e36 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/UnknownOption.kt +++ b/src/commonMain/kotlin/com/infendro/cli/error/UnknownOption.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.run +package com.infendro.cli.error import com.infendro.cli.command.Command import com.infendro.cli.util.distance @@ -8,7 +8,7 @@ import kotlin.math.min class UnknownOption( val command: Command, val name: String, -) : RuntimeFailure() { +) : Error() { override val message: String get() = buildString { val suggestion = command.options diff --git a/src/commonMain/kotlin/com/infendro/cli/error/run/RuntimeFailure.kt b/src/commonMain/kotlin/com/infendro/cli/error/run/RuntimeFailure.kt deleted file mode 100644 index a027c36..0000000 --- a/src/commonMain/kotlin/com/infendro/cli/error/run/RuntimeFailure.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.infendro.cli.error.run - -abstract class RuntimeFailure { - abstract val message: String -} diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/BuildException.kt b/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt similarity index 54% rename from src/commonMain/kotlin/com/infendro/cli/error/build/BuildException.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt index 0c1af10..bf5d540 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/BuildException.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt @@ -1,3 +1,3 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception abstract class BuildException : Exception() diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateArgument.kt similarity index 85% rename from src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/DuplicateArgument.kt index 17ceb79..d8b285d 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateArgument.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateArgument.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception import com.infendro.cli.argument.Argument diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateCommand.kt b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateCommand.kt similarity index 84% rename from src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateCommand.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/DuplicateCommand.kt index 4919bb0..a33651e 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateCommand.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateCommand.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception import com.infendro.cli.command.Command diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateExecute.kt b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateExecute.kt similarity index 77% rename from src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateExecute.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/DuplicateExecute.kt index f52c38d..335bff9 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateExecute.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateExecute.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class DuplicateExecute : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateOption.kt similarity index 84% rename from src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/DuplicateOption.kt index 5124de8..c56bd1b 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateOption.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateOption.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception import com.infendro.cli.option.Option diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateRenderer.kt b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateRenderer.kt similarity index 76% rename from src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateRenderer.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/DuplicateRenderer.kt index 347b803..492bb3d 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/DuplicateRenderer.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/DuplicateRenderer.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class DuplicateRenderer : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentName.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentName.kt similarity index 81% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentName.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentName.kt index 8a9a3d5..43b3ea8 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentName.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentName.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidArgumentName( val name: String, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentOrder.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentOrder.kt similarity index 77% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentOrder.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentOrder.kt index f5b4b52..119ded7 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidArgumentOrder.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidArgumentOrder.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidArgumentOrder : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandName.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandName.kt similarity index 81% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandName.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandName.kt index e1fd029..109f827 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandName.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandName.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidCommandName( val name: String, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandOrder.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandOrder.kt similarity index 77% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandOrder.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandOrder.kt index eb65123..81b2b19 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidCommandOrder.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidCommandOrder.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidCommandOrder : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidFallback.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidFallback.kt similarity index 76% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidFallback.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidFallback.kt index ac0c01a..b897c1c 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidFallback.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidFallback.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidFallback : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidOptionName.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidOptionName.kt similarity index 80% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidOptionName.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidOptionName.kt index 1eeaa0d..34bc6a8 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidOptionName.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidOptionName.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidOptionName( val name: String, diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidRange.kt b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidRange.kt similarity index 75% rename from src/commonMain/kotlin/com/infendro/cli/error/build/InvalidRange.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/InvalidRange.kt index f95e8df..31c1d50 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/InvalidRange.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/InvalidRange.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class InvalidRange : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/error/build/MissingOptionName.kt b/src/commonMain/kotlin/com/infendro/cli/exception/MissingOptionName.kt similarity index 76% rename from src/commonMain/kotlin/com/infendro/cli/error/build/MissingOptionName.kt rename to src/commonMain/kotlin/com/infendro/cli/exception/MissingOptionName.kt index a7997fd..4386853 100644 --- a/src/commonMain/kotlin/com/infendro/cli/error/build/MissingOptionName.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/MissingOptionName.kt @@ -1,4 +1,4 @@ -package com.infendro.cli.error.build +package com.infendro.cli.exception class MissingOptionName : BuildException() { override val message: String diff --git a/src/commonMain/kotlin/com/infendro/cli/option/Option.kt b/src/commonMain/kotlin/com/infendro/cli/option/Option.kt index 69c806d..5c5718b 100644 --- a/src/commonMain/kotlin/com/infendro/cli/option/Option.kt +++ b/src/commonMain/kotlin/com/infendro/cli/option/Option.kt @@ -1,8 +1,8 @@ package com.infendro.cli.option -import com.infendro.cli.error.build.InvalidOptionName -import com.infendro.cli.error.build.InvalidRange -import com.infendro.cli.error.build.MissingOptionName +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 diff --git a/src/commonMain/kotlin/com/infendro/cli/parser/Parser.kt b/src/commonMain/kotlin/com/infendro/cli/parser/Parser.kt index 257f2f0..0eb92dd 100644 --- a/src/commonMain/kotlin/com/infendro/cli/parser/Parser.kt +++ b/src/commonMain/kotlin/com/infendro/cli/parser/Parser.kt @@ -1,7 +1,7 @@ package com.infendro.cli.parser -import com.infendro.cli.error.run.InvalidValue -import com.infendro.cli.error.run.RuntimeFailure +import com.infendro.cli.error.Error +import com.infendro.cli.error.InvalidValue import kotlin.reflect.KClass abstract class Parser( @@ -13,7 +13,7 @@ abstract class Parser( ) : Result() data class Failure( - val failure: RuntimeFailure, + val error: Error, ) : Result() } From 9ad2d2c5e02344b8bf1470d43f93e91398e1d89e Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 17 Jan 2026 15:59:07 +0100 Subject: [PATCH 5/8] rename ci --- .gitea/workflows/{ci.yaml => publish.yaml} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename .gitea/workflows/{ci.yaml => publish.yaml} (90%) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/publish.yaml similarity index 90% rename from .gitea/workflows/ci.yaml rename to .gitea/workflows/publish.yaml index a63d994..dad1306 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/publish.yaml @@ -3,7 +3,7 @@ on: branches: [ main ] jobs: - test: + publish: runs-on: linux steps: - name: Checkout @@ -19,7 +19,7 @@ jobs: uses: actions/cache@v4 with: key: gradle-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: gradle- + restore-keys: gradle path: | ~/.gradle/caches/ ~/.gradle/wrapper/ @@ -28,7 +28,7 @@ jobs: uses: actions/cache@v4 with: key: konan-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: konan- + restore-keys: konan path: | ~/.konan/ @@ -36,7 +36,7 @@ jobs: uses: actions/cache@v4 with: key: node-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: node- + restore-keys: node path: | ~/.gradle/nodejs ~/.gradle/yarn From f55869193e22285af87321cbccee2eed84c20c75 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 17 Jan 2026 16:00:36 +0100 Subject: [PATCH 6/8] add additional targets --- build.gradle.kts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9df02c6..2492828 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,8 @@ +@file:OptIn(ExperimentalWasmDsl::class) + import com.infendro.plugin.infendro import com.infendro.plugin.token +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl group = "com.infendro" version = "1.4.0" @@ -12,10 +15,14 @@ plugins { kotlin { jvm() - js { - nodejs() - } linuxX64() + linuxArm64() + mingwX64() + macosX64() + macosArm64() + js { nodejs() } + wasmJs { nodejs() } + wasmWasi { nodejs() } repositories { mavenCentral() From d5a66f6853eb8b3e527fecdba1c410f2093aba3d Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 17 Jan 2026 16:02:14 +0100 Subject: [PATCH 7/8] bump version to 1.4.1 --- README.md | 11 +---------- build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 67ec8e5..7744887 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,6 @@ `cli-kt` is a Kotlin Multiplatform framework for implementing terminal applications. -## Targets - -| Target | Status | -|------------------|---------------| -| JVM | Supported | -| JavaScript | Supported | -| Native (Linux) | Supported | -| Native (Windows) | Not Supported | - ## Installation Add the following to your `build.gradle.kts`. @@ -21,7 +12,7 @@ repositories { } dependencies { - implementation("com.infendro:cli:1.4.0") + implementation("com.infendro:cli:1.4.1") } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 2492828..7d00784 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ import com.infendro.plugin.token import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl group = "com.infendro" -version = "1.4.0" +version = "1.4.1" plugins { alias(libs.plugins.infendro) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1139889..1896437 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] infendro = "1.0.0" -kotlin = "2.2.21" +kotlin = "2.3.0" [plugins] infendro = { id = "com.infendro.plugin", version.ref = "infendro" } From 21769c20c41aabfaeaad0691ce88056fba6d1af6 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sun, 18 Jan 2026 21:45:55 +0100 Subject: [PATCH 8/8] enforce exception message --- .../kotlin/com/infendro/cli/exception/BuildException.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt b/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt index bf5d540..57982c1 100644 --- a/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt +++ b/src/commonMain/kotlin/com/infendro/cli/exception/BuildException.kt @@ -1,3 +1,5 @@ package com.infendro.cli.exception -abstract class BuildException : Exception() +abstract class BuildException : Exception() { + abstract override val message: String +}