improve parsing and flag Options
This commit is contained in:
@@ -1,21 +1,20 @@
|
|||||||
package com.infendro.cli.command
|
package com.infendro.cli.command
|
||||||
|
|
||||||
import com.infendro.cli.parser.*
|
import com.infendro.cli.parser.*
|
||||||
import com.infendro.cli.parser.Parser
|
|
||||||
|
|
||||||
sealed class Argument<T>(
|
sealed class Argument<T : Any>(
|
||||||
val parser: Parser<T>,
|
val parser: Parser<T>,
|
||||||
) {
|
) {
|
||||||
abstract val required: Boolean
|
abstract val required: Boolean
|
||||||
|
|
||||||
class Required<T>(
|
class Required<T : Any>(
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Argument<T>(parser) {
|
) : Argument<T>(parser) {
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrElse<T>(
|
class OrElse<T : Any>(
|
||||||
val other: T,
|
val other: T,
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Argument<T>(parser) {
|
) : Argument<T>(parser) {
|
||||||
@@ -23,14 +22,14 @@ sealed class Argument<T>(
|
|||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrNull<T>(
|
class OrNull<T : Any>(
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Argument<T>(parser) {
|
) : Argument<T>(parser) {
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class Variable<T>(
|
class Variable<T : Any>(
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Argument<T>(parser) {
|
) : Argument<T>(parser) {
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.infendro.cli.command
|
package com.infendro.cli.command
|
||||||
|
|
||||||
|
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.build.*
|
||||||
import com.infendro.cli.exception.run.CliException
|
import com.infendro.cli.exception.run.CliException
|
||||||
import com.infendro.cli.util.Regex.COMMAND
|
import com.infendro.cli.util.Regex.COMMAND
|
||||||
@@ -22,7 +24,7 @@ class Command private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Builder internal constructor(
|
class Builder internal constructor(
|
||||||
private val index: Int,
|
private val level: Int,
|
||||||
private val name: String?,
|
private val name: String?,
|
||||||
) {
|
) {
|
||||||
private val commands = mutableListOf<Command>()
|
private val commands = mutableListOf<Command>()
|
||||||
@@ -30,22 +32,19 @@ class Command private constructor(
|
|||||||
private val options = mutableListOf<Option<*>>()
|
private val options = mutableListOf<Option<*>>()
|
||||||
private lateinit var _execute: Context.() -> Unit
|
private lateinit var _execute: Context.() -> Unit
|
||||||
|
|
||||||
private val nextIndex: Int
|
private val key: Key
|
||||||
get() = index + 1
|
get() = Key(level)
|
||||||
|
|
||||||
fun command(name: String? = null, block: Builder.(Key) -> Unit) {
|
fun command(name: String? = null, block: Builder.(Key) -> Unit) {
|
||||||
// validate
|
// validate
|
||||||
val last = commands.lastOrNull()
|
val last = commands.lastOrNull()
|
||||||
when {
|
when {
|
||||||
last?.fallback == true -> throw CommandOrderException()
|
last != null && last.fallback -> throw CommandOrderException()
|
||||||
name?.matches(COMMAND) == false -> throw IllegalCommandNameException(name)
|
name != null && !name.matches(COMMAND) -> throw IllegalCommandNameException(name)
|
||||||
commands.any { it.name == name } -> throw DuplicateCommandException(name)
|
commands.any { it.name == name } -> throw DuplicateCommandException(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
commands += Builder(nextIndex, name).also {
|
commands += Builder(level + 1, name).also { it.block(it.key) }.build()
|
||||||
val key = Key(nextIndex)
|
|
||||||
it.block(key)
|
|
||||||
}.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun argument(argument: Argument<*>) {
|
fun argument(argument: Argument<*>) {
|
||||||
@@ -53,7 +52,7 @@ class Command private constructor(
|
|||||||
val last = arguments.lastOrNull()
|
val last = arguments.lastOrNull()
|
||||||
when {
|
when {
|
||||||
last is Argument.Variable -> throw ArgumentOrderException()
|
last is Argument.Variable -> throw ArgumentOrderException()
|
||||||
argument.required && last?.required == false -> throw ArgumentOrderException()
|
argument.required && last != null && !last.required -> throw ArgumentOrderException()
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments += argument
|
arguments += argument
|
||||||
@@ -92,7 +91,7 @@ class Command private constructor(
|
|||||||
// validate
|
// validate
|
||||||
val last = commands.lastOrNull()
|
val last = commands.lastOrNull()
|
||||||
when {
|
when {
|
||||||
last?.fallback == true && arguments.isNotEmpty() -> throw InvalidFallbackException()
|
last != null && last.fallback && arguments.isNotEmpty() -> throw InvalidFallbackException()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!::_execute.isInitialized)
|
if (!::_execute.isInitialized)
|
||||||
@@ -107,8 +106,5 @@ class Command private constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cli(block: Command.Builder.() -> Unit): Command {
|
fun cli(block: Command.Builder.() -> Unit) =
|
||||||
val builder = Command.Builder(-1, null)
|
Command.Builder(-1, null).also(block).build()
|
||||||
builder.block()
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package com.infendro.cli.command
|
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
class Context internal constructor(
|
|
||||||
val command: Command,
|
|
||||||
val commands: List<Cmd>,
|
|
||||||
val options: List<Opt>,
|
|
||||||
val arguments: List<Arg>,
|
|
||||||
) {
|
|
||||||
class Cmd(
|
|
||||||
val name: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
class Arg(
|
|
||||||
val value: Any,
|
|
||||||
)
|
|
||||||
|
|
||||||
class Opt(
|
|
||||||
val name: String,
|
|
||||||
val value: Any,
|
|
||||||
)
|
|
||||||
|
|
||||||
internal fun execute() = (command.execute)()
|
|
||||||
|
|
||||||
operator fun Command.Key.getValue(thisRef: Any?, property: KProperty<*>): String = commands[index].name
|
|
||||||
|
|
||||||
private val <T> Argument<T>.index: Int
|
|
||||||
get() = command.arguments.indexOf(this)
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private val <T> Argument<T>.value: T?
|
|
||||||
get() = arguments.getOrNull(index)?.value as? T
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private val <T> Argument.Variable<T>.values: List<T>
|
|
||||||
get() = arguments.drop(index).map { it.value as T }
|
|
||||||
|
|
||||||
operator fun <T> Argument.Required<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value!!
|
|
||||||
operator fun <T> Argument.OrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other
|
|
||||||
operator fun <T> Argument.OrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = value
|
|
||||||
operator fun <T> Argument.Variable<T>.getValue(thisRef: Any?, property: KProperty<*>): List<T> = values
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private val <T> Option<T>.value: T?
|
|
||||||
get() = options.firstOrNull { it.name in names }?.value as? T
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private val <T> Option.Variable<T>.values: List<T>
|
|
||||||
get() = options.filter { it.name in names }.map { it.value as T }
|
|
||||||
|
|
||||||
operator fun <T> Option.Required<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value!!
|
|
||||||
operator fun <T> Option.OrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other
|
|
||||||
operator fun <T> Option.OrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = value
|
|
||||||
operator fun <T> Option.Variable<T>.getValue(thisRef: Any?, property: KProperty<*>): List<T> = values
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
package com.infendro.cli.command
|
package com.infendro.cli.command
|
||||||
|
|
||||||
import com.infendro.cli.exception.build.NoOptionNameException
|
import com.infendro.cli.exception.build.MissingOptionNameException
|
||||||
import com.infendro.cli.parser.*
|
import com.infendro.cli.parser.*
|
||||||
import com.infendro.cli.parser.Parser
|
|
||||||
|
|
||||||
sealed class Option<T>(
|
sealed class Option<T : Any>(
|
||||||
val names: List<String>,
|
|
||||||
val parser: Parser<T>,
|
val parser: Parser<T>,
|
||||||
|
val fallback: T?,
|
||||||
|
val names: List<String>,
|
||||||
) {
|
) {
|
||||||
|
val flag: Boolean
|
||||||
|
get() = fallback != null
|
||||||
|
|
||||||
val name: String
|
val name: String
|
||||||
get() = names[0]
|
get() = names[0]
|
||||||
|
|
||||||
@@ -15,89 +18,114 @@ sealed class Option<T>(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
if (names.isEmpty())
|
if (names.isEmpty())
|
||||||
throw NoOptionNameException()
|
throw MissingOptionNameException()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Required<T>(
|
class Required<T : Any>(
|
||||||
names: List<String>,
|
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Option<T>(names, parser) {
|
fallback: T?,
|
||||||
|
names: List<String>,
|
||||||
|
) : Option<T>(parser, fallback, names) {
|
||||||
|
constructor(
|
||||||
|
parser: Parser<T>,
|
||||||
|
names: List<String>,
|
||||||
|
) : this(parser, null, names)
|
||||||
|
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrElse<T>(
|
class OrElse<T : Any>(
|
||||||
|
parser: Parser<T>,
|
||||||
|
fallback: T?,
|
||||||
names: List<String>,
|
names: List<String>,
|
||||||
val other: T,
|
val other: T,
|
||||||
|
) : Option<T>(parser, fallback, names) {
|
||||||
|
constructor(
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Option<T>(names, parser) {
|
names: List<String>,
|
||||||
|
other: T,
|
||||||
|
) : this(parser, null, names, other)
|
||||||
|
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrNull<T>(
|
class OrNull<T : Any>(
|
||||||
names: List<String>,
|
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Option<T>(names, parser) {
|
fallback: T?,
|
||||||
|
names: List<String>,
|
||||||
|
) : Option<T>(parser, fallback, names) {
|
||||||
|
constructor(
|
||||||
|
parser: Parser<T>,
|
||||||
|
names: List<String>,
|
||||||
|
) : this(parser, null, names)
|
||||||
|
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class Variable<T>(
|
class Variable<T : Any>(
|
||||||
names: List<String>,
|
|
||||||
parser: Parser<T>,
|
parser: Parser<T>,
|
||||||
) : Option<T>(names, parser) {
|
fallback: T?,
|
||||||
|
names: List<String>,
|
||||||
|
) : Option<T>(parser, fallback, names) {
|
||||||
|
constructor(
|
||||||
|
parser: Parser<T>,
|
||||||
|
names: List<String>,
|
||||||
|
) : this(parser, null, names)
|
||||||
|
|
||||||
override val required: Boolean
|
override val required: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun string(vararg names: String) =
|
fun string(vararg names: String) =
|
||||||
Required(names.asList(), StringParser)
|
Required(StringParser, names.asList())
|
||||||
|
|
||||||
fun stringOrElse(vararg names: String, other: String) =
|
fun stringOrElse(vararg names: String, other: String) =
|
||||||
OrElse(names.asList(), other, StringParser)
|
OrElse(StringParser, names.asList(), other)
|
||||||
|
|
||||||
fun stringOrNull(vararg names: String) =
|
fun stringOrNull(vararg names: String) =
|
||||||
OrNull(names.asList(), StringParser)
|
OrNull(StringParser, names.asList())
|
||||||
|
|
||||||
fun strings(vararg names: String) =
|
fun strings(vararg names: String) =
|
||||||
Variable(names.asList(), StringParser)
|
Variable(StringParser, names.asList())
|
||||||
|
|
||||||
fun int(vararg names: String) =
|
fun int(vararg names: String) =
|
||||||
Required(names.asList(), IntParser)
|
Required(IntParser, names.asList())
|
||||||
|
|
||||||
fun intOrElse(vararg names: String, other: Int) =
|
fun intOrElse(vararg names: String, other: Int) =
|
||||||
OrElse(names.asList(), other, IntParser)
|
OrElse(IntParser, names.asList(), other)
|
||||||
|
|
||||||
fun intOrNull(vararg names: String) =
|
fun intOrNull(vararg names: String) =
|
||||||
OrNull(names.asList(), IntParser)
|
OrNull(IntParser, names.asList())
|
||||||
|
|
||||||
fun ints(vararg names: String) =
|
fun ints(vararg names: String) =
|
||||||
Variable(names.asList(), IntParser)
|
Variable(IntParser, names.asList())
|
||||||
|
|
||||||
fun boolean(vararg names: String) =
|
fun boolean(vararg names: String) =
|
||||||
Required(names.asList(), BooleanParser)
|
Required(BooleanParser, true, names.asList())
|
||||||
|
|
||||||
fun booleanOrElse(vararg names: String, other: Boolean) =
|
fun booleanOrElse(vararg names: String, other: Boolean) =
|
||||||
OrElse(names.asList(), other, BooleanParser)
|
OrElse(BooleanParser, true, names.asList(), other)
|
||||||
|
|
||||||
fun booleanOrNull(vararg names: String) =
|
fun booleanOrNull(vararg names: String) =
|
||||||
OrNull(names.asList(), BooleanParser)
|
OrNull(BooleanParser, true, names.asList())
|
||||||
|
|
||||||
fun booleans(vararg names: String) =
|
fun booleans(vararg names: String) =
|
||||||
Variable(names.asList(), BooleanParser)
|
Variable(BooleanParser, true, names.asList())
|
||||||
|
|
||||||
inline fun <reified T : Enum<T>> enum(vararg names: String) =
|
inline fun <reified T : Enum<T>> enum(vararg names: String) =
|
||||||
Required(names.asList(), enumParser<T>())
|
Required(enumParser<T>(), names.asList())
|
||||||
|
|
||||||
inline fun <reified T : Enum<T>> enumOrElse(vararg names: String, other: T) =
|
inline fun <reified T : Enum<T>> enumOrElse(vararg names: String, other: T) =
|
||||||
OrElse(names.asList(), other, enumParser<T>())
|
OrElse(enumParser<T>(), names.asList(), other)
|
||||||
|
|
||||||
inline fun <reified T : Enum<T>> enumOrNull(vararg names: String) =
|
inline fun <reified T : Enum<T>> enumOrNull(vararg names: String) =
|
||||||
OrNull(names.asList(), enumParser<T>())
|
OrNull(enumParser<T>(), names.asList())
|
||||||
|
|
||||||
inline fun <reified T : Enum<T>> enums(vararg names: String) =
|
inline fun <reified T : Enum<T>> enums(vararg names: String) =
|
||||||
Variable(names.asList(), enumParser<T>())
|
Variable(enumParser<T>(), names.asList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.infendro.cli.command.context
|
||||||
|
|
||||||
|
import com.infendro.cli.command.Argument
|
||||||
|
import com.infendro.cli.command.Command
|
||||||
|
import com.infendro.cli.command.Option
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class Context internal constructor(
|
||||||
|
val command: Command,
|
||||||
|
val commands: List<Cmd>,
|
||||||
|
val options: List<Opt>,
|
||||||
|
val arguments: List<Arg>,
|
||||||
|
) {
|
||||||
|
class Cmd(
|
||||||
|
val name: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Arg(
|
||||||
|
val value: Any,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Opt(
|
||||||
|
val name: String,
|
||||||
|
val value: Any,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun execute() = (command.execute)()
|
||||||
|
|
||||||
|
operator fun Command.Key.getValue(thisRef: Any?, property: KProperty<*>): String = commands[index].name
|
||||||
|
|
||||||
|
private val <T : Any> Argument<T>.index: Int
|
||||||
|
get() = command.arguments.indexOf(this)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val <T : Any> Argument<T>.value: T?
|
||||||
|
get() = arguments.getOrNull(index)?.value as? T
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val <T : Any> Argument.Variable<T>.values: List<T>
|
||||||
|
get() = arguments.drop(index).map { it.value as T }
|
||||||
|
|
||||||
|
operator fun <T : Any> Argument.Required<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value!!
|
||||||
|
operator fun <T : Any> Argument.OrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other
|
||||||
|
operator fun <T : Any> Argument.OrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = value
|
||||||
|
operator fun <T : Any> Argument.Variable<T>.getValue(thisRef: Any?, property: KProperty<*>): List<T> = values
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val <T : Any> Option<T>.value: T?
|
||||||
|
get() = options.firstOrNull { it.name in names }?.value as? T
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val <T : Any> Option.Variable<T>.values: List<T>
|
||||||
|
get() = options.filter { it.name in names }.map { it.value as T }
|
||||||
|
|
||||||
|
operator fun <T : Any> Option.Required<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value!!
|
||||||
|
operator fun <T : Any> Option.OrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other
|
||||||
|
operator fun <T : Any> Option.OrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = value
|
||||||
|
operator fun <T : Any> Option.Variable<T>.getValue(thisRef: Any?, property: KProperty<*>): List<T> = values
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.infendro.cli.command
|
package com.infendro.cli.command.context
|
||||||
|
|
||||||
import com.infendro.cli.command.Context.*
|
import com.infendro.cli.command.Argument
|
||||||
|
import com.infendro.cli.command.Command
|
||||||
|
import com.infendro.cli.command.Option
|
||||||
|
import com.infendro.cli.command.context.Context.*
|
||||||
import com.infendro.cli.exception.run.*
|
import com.infendro.cli.exception.run.*
|
||||||
|
|
||||||
internal object Parser {
|
internal object Parser {
|
||||||
@@ -41,6 +44,7 @@ internal object Parser {
|
|||||||
val current = args[i].drop(dashes)
|
val current = args[i].drop(dashes)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
|
// argument
|
||||||
endOfOptions || dashes == 0 -> {
|
endOfOptions || dashes == 0 -> {
|
||||||
val argument = command.arguments.getOrNull(argumentIndex)
|
val argument = command.arguments.getOrNull(argumentIndex)
|
||||||
?: throw TooManyArgumentsException()
|
?: throw TooManyArgumentsException()
|
||||||
@@ -52,6 +56,7 @@ internal object Parser {
|
|||||||
arg += Arg(value)
|
arg += Arg(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// option
|
||||||
dashes in 1..2 -> {
|
dashes in 1..2 -> {
|
||||||
if (dashes == 2 && current.isEmpty()) {
|
if (dashes == 2 && current.isEmpty()) {
|
||||||
endOfOptions = true
|
endOfOptions = true
|
||||||
@@ -59,7 +64,7 @@ internal object Parser {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val (name, value) = when {
|
val (name, text) = when {
|
||||||
current.contains('=') -> {
|
current.contains('=') -> {
|
||||||
val (name, value) = current.split('=', limit = 2)
|
val (name, value) = current.split('=', limit = 2)
|
||||||
name to value
|
name to value
|
||||||
@@ -85,11 +90,16 @@ internal object Parser {
|
|||||||
val option = command.options.firstOrNull { name in it.names }
|
val option = command.options.firstOrNull { name in it.names }
|
||||||
?: throw UnknownOptionException(name)
|
?: throw UnknownOptionException(name)
|
||||||
|
|
||||||
val value = option.parser.parse(value) as Any
|
val value = when {
|
||||||
|
text != null -> option.parser.parse(text)
|
||||||
|
option.flag -> option.fallback!!
|
||||||
|
else -> throw MissingOptionValueException(name)
|
||||||
|
}
|
||||||
opt += Opt(name, value)
|
opt += Opt(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// malformed option
|
||||||
else -> {
|
else -> {
|
||||||
when {
|
when {
|
||||||
args[i].contains('=') -> {
|
args[i].contains('=') -> {
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package com.infendro.cli.exception.build
|
||||||
|
|
||||||
|
class MissingOptionNameException : Exception()
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package com.infendro.cli.exception.build
|
|
||||||
|
|
||||||
class NoOptionNameException : Exception()
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.infendro.cli.exception.run
|
||||||
|
|
||||||
|
class MissingOptionValueException(
|
||||||
|
val option: String,
|
||||||
|
) : CliException() {
|
||||||
|
override val message: String
|
||||||
|
get() = """no value provided for option "$option""""
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@ package com.infendro.cli.parser
|
|||||||
import com.infendro.cli.exception.run.ParseException
|
import com.infendro.cli.exception.run.ParseException
|
||||||
|
|
||||||
object BooleanParser : Parser<Boolean> {
|
object BooleanParser : Parser<Boolean> {
|
||||||
override fun parse(text: String?): Boolean = when (text) {
|
override fun parse(text: String): Boolean = when (text) {
|
||||||
"true", "t", null -> true
|
"true", "t" -> true
|
||||||
"false", "f" -> false
|
"false", "f" -> false
|
||||||
else -> throw ParseException(text, "Boolean")
|
else -> throw ParseException(text, "Boolean")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class EnumParser<T : Enum<T>>(
|
|||||||
private val name: String,
|
private val name: String,
|
||||||
private val values: List<T>,
|
private val values: List<T>,
|
||||||
) : Parser<T> {
|
) : Parser<T> {
|
||||||
override fun parse(text: String?): T = try {
|
override fun parse(text: String): T = try {
|
||||||
values.first { it.name == text }
|
values.first { it.name == text }
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
throw ParseException(text, name)
|
throw ParseException(text, name)
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package com.infendro.cli.parser
|
|||||||
import com.infendro.cli.exception.run.ParseException
|
import com.infendro.cli.exception.run.ParseException
|
||||||
|
|
||||||
object IntParser : Parser<Int> {
|
object IntParser : Parser<Int> {
|
||||||
override fun parse(text: String?): Int = try {
|
override fun parse(text: String): Int = try {
|
||||||
text!!.toInt()
|
text.toInt()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
throw ParseException(text, "Int")
|
throw ParseException(text, "Int")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package com.infendro.cli.parser
|
package com.infendro.cli.parser
|
||||||
|
|
||||||
interface Parser<T> {
|
interface Parser<T> {
|
||||||
fun parse(text: String?): T
|
fun parse(text: String): T
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.infendro.cli.parser
|
package com.infendro.cli.parser
|
||||||
|
|
||||||
import com.infendro.cli.exception.run.ParseException
|
|
||||||
|
|
||||||
object StringParser : Parser<String> {
|
object StringParser : Parser<String> {
|
||||||
override fun parse(text: String?): String = text ?: throw ParseException(text, "String")
|
override fun parse(text: String): String = text
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.infendro.cli.util
|
package com.infendro.cli.util
|
||||||
|
|
||||||
internal object Regex {
|
internal object Regex {
|
||||||
private const val L = "[a-zA-Z]"
|
val COMMAND = Regex("""[a-zA-Z][a-zA-Z0-9]*(?:-[a-zA-Z0-9]+)*""")
|
||||||
private const val AN = """[a-zA-Z0-9]"""
|
val OPTION = Regex("""[a-zA-Z][a-zA-Z0-9]*(?:[\-.][a-zA-Z0-9]+)*""")
|
||||||
val COMMAND = Regex("""${L}${AN}*(?:-${AN}+)*""")
|
|
||||||
val OPTION = Regex("""${L}${AN}*(?:[\-.]${AN}+)*""")
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user