Kotlin/kotlinx-cli

Question: How to pass "false" to Boolean argument that's default is true?

tateisu opened this issue · 8 comments

How to pass "false" to Boolean argument that's default is true?

Hello, it seems that we should prohibit changing default for boolean flags. It shows only if flag is provided in command line or not. Mostly all command line options that turn off something are similar to -fno-exceptions.
Do you want to have an opportunity to provide a value to flag? Something like -useCommon true? It's very rare approach in command line tools?

I am asking a question. I'm not proposing anything.

I think now only make flag like that
val no_debug by parser.option(ArgType.Boolean, shortName = "d", description = "Turn off debug mode")
and later

if (!no_debug) {
  //Debug mode actions
}
class InvertOption( private val original: SingleNullableOption<Boolean>){
	operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>) =
		Delegate( original.provideDelegate(thisRef,prop))

	inner class Delegate(private val originalDelegate:ArgumentValueDelegate<Boolean?>){
		operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
			return !( originalDelegate.getValue(thisRef,property) ?: false)
		}
	}
}
val useIt by InvertOption( parser.option(ArgType.Boolean,fullName = "dontUseIt",description = "…"))

Or we can define string option and treat it as boolean flag.

Yes, you can do your extension, if you have several such options it's absolutely right way.

It can be misleading to explain to others that "enable / disable an option named dontUseIt". It's basically not a good approach.

We can make something like this, but the problem is that the help description shows the type specification as String.

class TruthyOption( private val original:SingleNullableOption<T>,val defVal:Boolean ){
	operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>) =
		Delegate( original.default(defVal.toString()).provideDelegate(thisRef,prop))

	inner class Delegate(private val originalDelegate:ArgumentValueDelegate<String>){
		operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
			return originalDelegate.getValue(thisRef,property).isTruth() // String->Boolean as you like
		}
	}
}
val useIt by TruthyOption( parser.option(ArgType.String,fullName = "useIt",description = "…"),defVal = true)

another version that use ArgType.Choice(listOf(false,true), { it.isTruth() })

// you need make String.isTruth() as you like
val ArgTypeExplicitBoolean = ArgType.Choice(listOf(false, true), { it.isTruth() }) 
val useIt by parser.option( ArgTypeExplicitBoolean, fullName = "useIt", description = "…" ).default(true)

it shows more better help.

 --useIt [true] -> … { Value should be one of [false, true] }