Skip to content

Instantly share code, notes, and snippets.

@OndraZizka
Last active November 22, 2022 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OndraZizka/04ae3ec04e0e0750ef01934b57633490 to your computer and use it in GitHub Desktop.
Save OndraZizka/04ae3ec04e0e0750ef01934b57633490 to your computer and use it in GitHub Desktop.
Kotlin: Parsing of enum-based application linux-like arguments (--name[=value])
object OptionsParsingUtils {
private inline fun <reified T : OptionEnum> tryParseEnumOption(enumArgumentDefault: T, arg: String): T? {
val optionIntro = "--${enumArgumentDefault.optionName}"
if (!arg.startsWith(optionIntro))
return null
if (arg.endsWith(optionIntro) || arg.endsWith("=${enumArgumentDefault.optionValue}"))
return enumArgumentDefault
val valueStr = arg.substringAfter(optionIntro)
val enumConstants = T::class.java.enumConstants
return enumConstants.firstOrNull { it.optionName == valueStr }
?: throw IllegalArgumentException("Unknown value for ${enumArgumentDefault.optionName}: $arg Try one of ${enumConstants.map { it.optionValue }}")
}
}
fun main(args: List<String>) {
for (arg in args) {
// Tries to match an option starting "--sortInputPaths",
// matching the enum value after, or PARAMS_ORDER as default if no value after "=".
val order = tryParseEnumOption(SortInputPaths.PARAMS_ORDER, arg)
val combine = tryParseEnumOption(CombineInputFiles.CONCAT, arg)
}
// If you have many options, the enums could be put to a list and tried in another loop:
val optionEnums = listOf<OptionEnum>(SortInputPaths.PARAMS_ORDER, CombineInputFiles.CONCAT, ...)
val appOptions = Map<Class<OptionEnum>, OptionEnum>>
for (arg in args)
for (enumDefault in optionEnums) {
val choice = tryParseEnumOption(enumDefault, arg)
if (choice != null)
appOptions[enumDefault.javaClass] = choice
}
}
}
enum class SortInputPaths(override val optionValue: String) : OptionEnum {
PARAMS_ORDER("paramOrder"),
ALPHA("alpha"),
TIME("time");
// A little trick: The name is defined on all members, not on the class.
override val optionName: String by lazy { "sortInputPaths" }
}
interface OptionEnum {
val optionName: String
val optionValue: String?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment