xenomachina / kotlin-argparser

Easy to use and concise yet powerful and robust command line argument parsing for Kotlin
GNU Lesser General Public License v2.1
483 stars 33 forks source link

Add a combination of adding/mapping arguments #31

Open ColinHebert opened 7 years ago

ColinHebert commented 7 years ago

Not sure whether it's something that should be part of the core of argparser but I came across a usecase which consists of multiple arguments (flags) being collected to obtain a set of switches (and allowing this set of switches to be validated).

I monkey patched it as this:

fun <E, T : MutableCollection<E>> ArgParser.addMapping(
        map: Map<String, E>,
        help: String,
        initialValue: T): ArgParser.Delegate<T> {
    val names = map.keys.toTypedArray()
    return option<T>(*names,
            errorName = map.keys.joinToString("|"),
            help = help,
            isRepeating = true) {
        val result = value.orElse { initialValue }
        result.add(map.getValue(optionName))
        result
    }.default(initialValue)
}

fun <E> ArgParser.addMapping(map: Map<String, E>, help: String): ArgParser.Delegate<MutableCollection<E>> =
        addMapping(map, help, mutableSetOf())

fun <E, T : MutableCollection<E>> ArgParser.addMapping(vararg pairs: Pair<String, E>, help: String, initialValue: T): ArgParser.Delegate<T> =
        addMapping(mapOf(*pairs), help, initialValue)

fun <E> ArgParser.addMapping(vararg pairs: Pair<String, E>, help: String): ArgParser.Delegate<MutableCollection<E>> =
        addMapping(mapOf(*pairs), help, mutableSetOf())

Here's an example of the usage:

    private val dumps: MutableCollection<DumpType> by commandParser.addMapping(
            "--heap" to DumpType.HEAP_DUMP,
            "--thread" to DumpType.THREAD_DUMP,
            "--database" to DumpType.THREAD_DUMP, help = "Type of dump to process (more than one type is allowed)")
            .addValidator { if (value.isEmpty()) throw InvalidArgumentException("At least one dump type must be selected") }

What do you think?

xenomachina commented 6 years ago

That is definitely an interesting example! I'm just not sure how much this adds over simply having a separate flag for each dump type, and then validating that at least one is set later on.

value.isEmpty() is definitely nicer than !(heap || thread || database) (especially when it's possible that more of these may be added later), but is it enough to warrant adding this to the API?

(I was actually somewhat on the fence about the existing mapping method.)