case-app icon indicating copy to clipboard operation
case-app copied to clipboard

boolean handling is confusing

Open balhoff opened this issue 5 years ago • 5 comments

If an option type is boolean, and a default value of true is provided, there doesn't seem to be a way to set it to false on the command line:

[info] Starting scala interpreter...
Welcome to Scala 2.13.3 (Java HotSpot(TM) 64-Bit Server VM, Java 11.0.4).
Type in expressions for evaluation. Or try :help.

scala> import caseapp._
import caseapp._

scala> case class Options(enableFoo: Boolean = false)
class Options

scala> CaseApp.parse[Options](Seq())
val res0: Either[caseapp.core.Error,(Options, Seq[String])] = Right((Options(false),List()))

scala> CaseApp.parse[Options](Seq("--enable-foo", "true"))
val res2: Either[caseapp.core.Error,(Options, Seq[String])] = Right((Options(true),List(true)))

scala> CaseApp.parse[Options](Seq("--enable-foo", "false"))
val res3: Either[caseapp.core.Error,(Options, Seq[String])] = Right((Options(true),List(false)))

scala> case class Options2(enableFoo: Boolean = true)
class Options2

scala> CaseApp.parse[Options2](Seq("--enable-foo", "false"))
val res5: Either[caseapp.core.Error,(Options2, Seq[String])] = Right((Options2(true),List(false)))

scala> CaseApp.parse[Options2](Seq())
val res6: Either[caseapp.core.Error,(Options2, Seq[String])] = Right((Options2(true),List()))

For the case of res3 above, I would expect to be able to explicitly pass false, although I can get a false value by not providing the argument at all (e.g. res0). Unexpectedly --enable-foo false sets the value to true, because "false" is treated as an extra argument.

For the case of the default true value (Options2), there doesn't seem to be any command line that can set it to false.

balhoff avatar Oct 02 '20 15:10 balhoff

I did want to add that I've used several Scala command line parsers, and case-app is easily my favorite—thanks!

balhoff avatar Oct 02 '20 15:10 balhoff

@balhoff It is possible to pass an explicit value to boolean options, like --enable-foo=true or --enable-foo=false.

alexarchambault avatar Oct 05 '20 14:10 alexarchambault

@alexarchambault thank you for pointing that out, I completely missed that it was possible to use = between options and values. Based on the examples in the readme I thought a space was required. To me it's a little confusing that this works differently between, e.g., Boolean and String values. Is it safe then to use = for all arguments?

balhoff avatar Oct 05 '20 15:10 balhoff

Yes, = can be used for all options. = is optional for options requiring a value, such as string options. For options accepting an optional value (it's only booleans IIRC), the = is mandatory if you want to pass a value.

alexarchambault avatar Oct 05 '20 15:10 alexarchambault

Thanks! I'll leave it up to you if you want to go ahead and close this. It would be great to add that to the docs if it isn't somewhere already.

balhoff avatar Oct 05 '20 17:10 balhoff