improve help
display type for fallback commands display type and range for arguments/options
This commit is contained in:
@@ -23,8 +23,8 @@ sealed class Command private constructor(
|
||||
if (!name.matches(Regex.COMMAND)) throw InvalidCommandName(name)
|
||||
}
|
||||
|
||||
fun run(args: Array<String>) {
|
||||
when (val result = ContextParser(this, args).parse()) {
|
||||
fun run(vararg args: String) {
|
||||
when (val result = ContextParser(this, arrayOf(*args)).parse()) {
|
||||
is ContextParser.Result.Success -> result.context.execute()
|
||||
is ContextParser.Result.Help -> {
|
||||
val command = result.path.last()
|
||||
@@ -144,7 +144,7 @@ sealed class Command private constructor(
|
||||
val last = commands.last()
|
||||
if (last is Fallback<*>) throw InvalidCommandOrder()
|
||||
}
|
||||
if (commands.any { it.name == command.name }) throw DuplicateCommand(command.name)
|
||||
if (commands.any { it.name == command.name }) throw DuplicateCommand(command)
|
||||
}
|
||||
|
||||
private fun validateArgument(argument: Argument<*>) {
|
||||
@@ -155,12 +155,12 @@ sealed class Command private constructor(
|
||||
argument.required && last.optional -> throw InvalidArgumentOrder()
|
||||
}
|
||||
}
|
||||
if (arguments.any { it.name == argument.name }) throw DuplicateArgument(argument.name)
|
||||
if (arguments.any { it.name == argument.name }) throw DuplicateArgument(argument)
|
||||
}
|
||||
|
||||
private fun validateOption(option: Option<*>) {
|
||||
for (name in option.names) {
|
||||
if (options.any { name in it.names }) throw DuplicateOption(name)
|
||||
if (options.any { name in it.names }) throw DuplicateOption(option)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ 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 kotlin.reflect.KClass
|
||||
|
||||
object DefaultHelpRenderer : HelpRenderer {
|
||||
override fun render(path: List<Command>) = buildString {
|
||||
@@ -40,11 +41,7 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
argument.min == 1 && argument.max == 1 -> append("<${argument.name}>")
|
||||
argument.min == 0 && argument.max == 1 -> append("[<${argument.name}>]")
|
||||
else -> {
|
||||
val range = when {
|
||||
argument.unbounded -> "{${argument.min},}"
|
||||
argument.min == argument.max -> "{${argument.min}}"
|
||||
else -> "{${argument.min},${argument.max}}"
|
||||
}
|
||||
val range = renderRange(argument.min, argument.max)
|
||||
append("<${argument.name}>$range")
|
||||
}
|
||||
}
|
||||
@@ -64,11 +61,7 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
option.min == 1 && option.max == 1 -> append("($text)")
|
||||
option.min == 0 && option.max == 1 -> append("[$text]")
|
||||
else -> {
|
||||
val range = when {
|
||||
option.unbounded -> "{${option.min},}"
|
||||
option.min == option.max -> "{${option.min}}"
|
||||
else -> "{${option.min},${option.max}}"
|
||||
}
|
||||
val range = renderRange(option.min, option.max)
|
||||
append("($text)$range")
|
||||
}
|
||||
}
|
||||
@@ -80,7 +73,11 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
appendLine("Commands:")
|
||||
for (command in commands) {
|
||||
val name = when {
|
||||
command is Command.Fallback<*> -> "<${command.name}>"
|
||||
command is Command.Fallback<*> -> {
|
||||
val name = command.name
|
||||
val type = command.parser.type.name
|
||||
"<$name> ($type)"
|
||||
}
|
||||
else -> command.name
|
||||
}
|
||||
appendLine(" * $name")
|
||||
@@ -90,7 +87,10 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
private fun StringBuilder.arguments(arguments: List<Argument<*>>) {
|
||||
appendLine("Arguments:")
|
||||
for (argument in arguments) {
|
||||
appendLine(" * ${argument.name}")
|
||||
val name = argument.name
|
||||
val type = argument.parser.type.name
|
||||
val range = renderRangeFull(argument.min, argument.max)
|
||||
appendLine(" * $name ($type, $range)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,9 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
appendLine("Options:")
|
||||
for (option in options) {
|
||||
val name = option.names.joinToString(" | ") { it.withPrefix() }
|
||||
appendLine(" * $name")
|
||||
val type = option.parser.type.name
|
||||
val range = renderRangeFull(option.min, option.max)
|
||||
appendLine(" * $name ($type, $range)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,4 +108,23 @@ object DefaultHelpRenderer : HelpRenderer {
|
||||
length == 1 -> "-$this"
|
||||
else -> "--$this"
|
||||
}
|
||||
|
||||
private val KClass<*>.name: String
|
||||
get() = simpleName ?: "Unknown"
|
||||
|
||||
private fun renderRange(min: Int, max: Int?) = when {
|
||||
max == null -> "{$min,}"
|
||||
min == max -> "{$min}"
|
||||
else -> "{$min,$max}"
|
||||
}
|
||||
|
||||
private fun renderRangeFull(min: Int, max: Int?) = when {
|
||||
min == 1 && max == 1 -> "required"
|
||||
min == 0 && max == 1 -> "optional"
|
||||
else -> when {
|
||||
max == null -> "at least $min"
|
||||
min == max -> "exactly $min"
|
||||
else -> "between $min and $max"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user