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)
|
if (!name.matches(Regex.COMMAND)) throw InvalidCommandName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun run(args: Array<String>) {
|
fun run(vararg args: String) {
|
||||||
when (val result = ContextParser(this, args).parse()) {
|
when (val result = ContextParser(this, arrayOf(*args)).parse()) {
|
||||||
is ContextParser.Result.Success -> result.context.execute()
|
is ContextParser.Result.Success -> result.context.execute()
|
||||||
is ContextParser.Result.Help -> {
|
is ContextParser.Result.Help -> {
|
||||||
val command = result.path.last()
|
val command = result.path.last()
|
||||||
@@ -144,7 +144,7 @@ sealed class Command private constructor(
|
|||||||
val last = commands.last()
|
val last = commands.last()
|
||||||
if (last is Fallback<*>) throw InvalidCommandOrder()
|
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<*>) {
|
private fun validateArgument(argument: Argument<*>) {
|
||||||
@@ -155,12 +155,12 @@ sealed class Command private constructor(
|
|||||||
argument.required && last.optional -> throw InvalidArgumentOrder()
|
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<*>) {
|
private fun validateOption(option: Option<*>) {
|
||||||
for (name in option.names) {
|
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.Command
|
||||||
import com.infendro.cli.command.argument.Argument
|
import com.infendro.cli.command.argument.Argument
|
||||||
import com.infendro.cli.command.option.Option
|
import com.infendro.cli.command.option.Option
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
object DefaultHelpRenderer : HelpRenderer {
|
object DefaultHelpRenderer : HelpRenderer {
|
||||||
override fun render(path: List<Command>) = buildString {
|
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 == 1 && argument.max == 1 -> append("<${argument.name}>")
|
||||||
argument.min == 0 && argument.max == 1 -> append("[<${argument.name}>]")
|
argument.min == 0 && argument.max == 1 -> append("[<${argument.name}>]")
|
||||||
else -> {
|
else -> {
|
||||||
val range = when {
|
val range = renderRange(argument.min, argument.max)
|
||||||
argument.unbounded -> "{${argument.min},}"
|
|
||||||
argument.min == argument.max -> "{${argument.min}}"
|
|
||||||
else -> "{${argument.min},${argument.max}}"
|
|
||||||
}
|
|
||||||
append("<${argument.name}>$range")
|
append("<${argument.name}>$range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,11 +61,7 @@ object DefaultHelpRenderer : HelpRenderer {
|
|||||||
option.min == 1 && option.max == 1 -> append("($text)")
|
option.min == 1 && option.max == 1 -> append("($text)")
|
||||||
option.min == 0 && option.max == 1 -> append("[$text]")
|
option.min == 0 && option.max == 1 -> append("[$text]")
|
||||||
else -> {
|
else -> {
|
||||||
val range = when {
|
val range = renderRange(option.min, option.max)
|
||||||
option.unbounded -> "{${option.min},}"
|
|
||||||
option.min == option.max -> "{${option.min}}"
|
|
||||||
else -> "{${option.min},${option.max}}"
|
|
||||||
}
|
|
||||||
append("($text)$range")
|
append("($text)$range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +73,11 @@ object DefaultHelpRenderer : HelpRenderer {
|
|||||||
appendLine("Commands:")
|
appendLine("Commands:")
|
||||||
for (command in commands) {
|
for (command in commands) {
|
||||||
val name = when {
|
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
|
else -> command.name
|
||||||
}
|
}
|
||||||
appendLine(" * $name")
|
appendLine(" * $name")
|
||||||
@@ -90,7 +87,10 @@ object DefaultHelpRenderer : HelpRenderer {
|
|||||||
private fun StringBuilder.arguments(arguments: List<Argument<*>>) {
|
private fun StringBuilder.arguments(arguments: List<Argument<*>>) {
|
||||||
appendLine("Arguments:")
|
appendLine("Arguments:")
|
||||||
for (argument in 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:")
|
appendLine("Options:")
|
||||||
for (option in options) {
|
for (option in options) {
|
||||||
val name = option.names.joinToString(" | ") { it.withPrefix() }
|
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"
|
length == 1 -> "-$this"
|
||||||
else -> "--$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