ajalt / clikt

Multiplatform command line interface parsing for Kotlin
https://ajalt.github.io/clikt/
Apache License 2.0
2.54k stars 121 forks source link

Support observer for child commands run call #434

Closed cmorigaki closed 1 year ago

cmorigaki commented 1 year ago

Hi, I'm adding analytics to the CLI and one of the use cases is sending an event of the invoked command with its arguments/options. To avoid repetition and ensure every command sends the event, my current implementation looks like this:

abstract BaseCommand(...) : ) : CliktCommand(...) {
    final override fun run() {
        sendEvent()
        this.onRun()
    }
    abstract fun onRun()
}

Two Clikt modifications would improve my code and I believe it would also improve Clikt code:

  1. Add observer for child command run. That way instead of creating a Base class, the parent command could observe and send the event after the parsing phase. Also, I would get rid of the final and onRun() workaround because there is no way to force the super method call and ensure the event is sent.

  2. Implement OptionWithValuesImpl.toString() and ProcessedArgumentImpl.toString(). To collect options and arguments information, I replicated part of the ClickCommand.toString(). Implementing these overrides, would also simplify ClickCommand.toString().

I checked the code and the first one seems not trivial. For the second, not sure if I'm missing something else here but I would like to contribute with a PR.

ajalt commented 1 year ago

Thanks for the feedback!

The string implementations were all in CliktCommand since, prior to 4.0, there were multiple implementations of Option and Argument. Now that there's only one of each, implementing toString in them makes sense.

I'm not sure about adding lifecycle callbacks. Since it's only a couple of lines of code to do yourself, I'd need to see more use cases before I add a feature like that.

cmorigaki commented 1 year ago

Awesome! Thanks!