clikt icon indicating copy to clipboard operation
clikt copied to clipboard

Feature request: ability to specify required() after check()

Open pgarrett-twc opened this issue 4 months ago • 1 comments

Hi, thanks for a great library.

In our app we have a library of options, where we specify types, help text, and validation rules for objects in our domain, like this contrived example:

class Options(private val command: ParameterHolder) {
  val widgetId get() =
      command.option("--widget-id", help="Widget ID as integer")
          .int()
          .check("Widget ID must be positive") { it > 0 }
}

And then in each command, we include the options that are relevant to it, like:

class UpdateWidgetCommand : CliktCommand() {
  private val options = Options(this)
  val widgetId by options.widgetId
  ...
}

The problem I have is that in some commands widgetId is required but in others it is optional. So I'd like to be able to do something like this:

  val widgetId by options.widgetId             // this is an Int?
  // or
  val widgetId by options.widgetId.required()  // this would be an Int. Doesn't compile.

The required() method is only available on NullableOption, not OptionDelegate<Int?>, so this doesn't work currently.

Thanks for considering this request. And of course, I'd be happy to know if there's already a way to do it that I missed.

pgarrett-twc avatar Oct 14 '25 18:10 pgarrett-twc

An option's final value is computed by check(transformAll(transformEach(convert(value)))), and required is a wrapper around transformAll, so you can't change the order the transformations are applied.

In your case, I would recommend adding that check in convert instead: option().int().convert{ require(it > 0) { "must be positive" }; it }.

ajalt avatar Oct 14 '25 19:10 ajalt