in rd-kt/rd-gen/src/main/kotlin/com/jetbrains/rd/util/kli/Kli.kt [130:238]
fun parse(cmdline: Array<String>): String? {
require (state == Init) { "Parsed already" }
var argumentIdx = 0
val commands = cmdline.iterator()
var chars = PushBackCharIterator("") //fake
val err = { msg:String ->
error = msg
Fin
}
val parseOption = { option: Option<*>?, presentableName: String ->
if (option == null) err("Unknown option: $presentableName")
else when(option) {
is Option.Flag -> {
option._value = true
ShortOption
}
is Option.Valued<*> -> {
val rawValue =
if (chars.rem.isEmpty())
if (commands.hasNext()) commands.next()
else null
else
chars.rem
if (rawValue == null) err("No value provided for option $presentableName")
else if (!option.tryParse(rawValue)) err("Can't parse value '$rawValue' for option $presentableName")
else StartCmd
}
}
}
cycle@while (true) {
state = when (state) {
Init -> StartCmd
StartCmd ->
if (!commands.hasNext()) Fin
else {
chars = PushBackCharIterator(commands.next())
if (!chars.moveNext()) err("Empty argument")
else if (chars.cur == '-') Minus
else {
chars.pushBack()
Argument
}
}
Minus ->
if (!chars.moveNext()) err("Standalone '-' is not allowed")
else if (chars.cur == '-') DoubleMinus
else {
chars.pushBack()
ShortOption
}
DoubleMinus ->
if (!chars.moveNext()) err("Standalone '--' is not allowed")
else if (chars.cur == '-') err("Triple minus '---' is not allowed")
else {
chars.pushBack()
LongOption
}
ShortOption ->
if (!chars.moveNext()) StartCmd //if it's not first long option in a row
else {
val option = options.firstOrNull {it.short == chars.cur}
parseOption(option, "'-${chars.cur}'")
}
LongOption -> {
val rawName = buildString {
while (chars.moveNext()) {
if (chars.cur == '=') break
else append(chars.cur)
}
}
if (rawName.isEmpty()) err("Invalid option pattern: '${chars.str}'")
else {
val option = options.firstOrNull {it.long == rawName}
parseOption(option, "'--$rawName'")
}
}
Argument -> {
val rawValue = chars.rem
if (argumentIdx >= arguments.size) err("Too many arguments: '$rawValue'")
else {
val argument = arguments[argumentIdx++]
if (!argument.parseValue(rawValue)) err("Can't parse value '$rawValue' for argument '${argument.name}'")
else StartCmd
}
}
Fin -> break@cycle
}
}
if (error == null && argumentIdx < arguments.size) error = "Value of argument '${arguments[argumentIdx].name}' undefined"
return error
}