Last active
January 24, 2024 13:16
-
-
Save L-Briand/15ddf5787ba8e78f842b3de90c3bf10c to your computer and use it in GitHub Desktop.
Parse arguments with gnu syntax in Kotlin.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Parse arguments with gnu syntax. | |
* | |
* When parsing, the name given to [onArgument] can be: | |
* - `null` if found value has no hyphen. | |
* - A short option if the value starts with a hyphen. (`-s`) | |
* - A long option if the value starts with a double hyphen. (`--long`) | |
* | |
* The `getValue` can be used to get the next non-hyphen value | |
* (-p**8080**, -p **8080**, --port **8080**). | |
* It can be used to get multiple values (-i input1 input2) | |
* It returns null if it founds a value starting with a hyphen or reaches the end of the argument list. | |
* | |
* @param args arguments from command line. | |
* @param onArgument a lambda to catch read arguments. | |
* | |
* @return the number of elements in [args] read until "--" or `args.length` if it reaches the end. | |
*/ | |
inline fun gnuParse( | |
args: Array<String>, | |
onArgument: (name: String?, getNextValue: () -> String?) -> Unit | |
): Int { | |
var index = 0 | |
while (true) { | |
if (index > args.lastIndex) return index | |
val arg = args[index++] | |
when { | |
arg.startsWith("--") -> { | |
if (arg.length == 2) return index | |
val name = arg.substring(2, arg.length) | |
onArgument(name) { | |
if (index > args.lastIndex) return@onArgument null | |
val argument = args[index] | |
if (argument.startsWith('-')) return@onArgument null | |
index++ | |
argument | |
} | |
} | |
arg.startsWith('-') -> { | |
var j = 1 | |
while (j < arg.length) { | |
onArgument(arg[j++].toString()) { | |
if (j == arg.length) { | |
if (index > args.lastIndex) return@onArgument null | |
val argument = args[index] | |
if (argument.startsWith('-')) return@onArgument null | |
index++ | |
argument | |
} | |
else { | |
val value = arg.substring(j, arg.length) | |
j = arg.length | |
value | |
} | |
} | |
} | |
} | |
else -> { | |
var first = true | |
onArgument(null) { | |
if (!first) { | |
if (index > args.lastIndex) return@onArgument null | |
val argument = args[index] | |
if (argument.startsWith('-')) return@onArgument null | |
index++ | |
argument | |
} | |
else { | |
first = false | |
arg | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun main(args: String) { | |
var name: String? = null | |
var enable: Boolean | |
gnuParse(args) { name, getValue -> | |
when(name) { | |
"n", "name" -> getValue()?.let { name = it } | |
"e", "enable" -> bar = true | |
} | |
} | |
println("> ${name ?: "default"} is $bar") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$./program -nfoo -e | |
> foo is true | |
$./program -n foo --enable | |
> foo is true | |
$./program --name foo | |
> foo is false | |
$./program | |
> default is false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment