ajalt / clikt

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

Feature request: Command/option/flag information exposed via hook #481

Closed jaytee closed 7 months ago

jaytee commented 7 months ago

Hi @ajalt, thanks for your work on Clikt, I've used it a fair bit now and have always loved the clear documentation and the ease of implementation.


I have a use case for a CLI tool with a lot of subcommands (a toolbox type app for odd jobs) that would benefit greatly from being able to be invoked with no command line arguments and for the user to be presented with a TUI to select a subcommand from the tree of all available commands, and then incrementally be walked through setting each applicable option/flag, before finally handing the built up command line to Clikt to invoke the command as normal.

The idea being that it would be a nice-to-have type feature allowing the user to drop in, discover utilities within the app and execute one without needing to read the --help outputs and incrementally build a command line manually.

I could obviously achieve this by running some code before invoking Clikt and then passing a transformed args through to RootCommand.main(), but the ugly bit would be obtaining the available commands automatically (and importantly the tree structure of subcommands), along with option and flag information.

I've got a couple of ideas:

  1. Support some type of hook/interceptor functionality in Clikt that would expose all of the command/option/flag information to an interested external component before the applicable command is computed and executed, to allow the external component (e.g. something responsible for prompting/selection of command, perhaps with Mordant or Mosaic) to mutate the CLI args and then pass along a new args array to Clikt to execute, and for everything else to run as normal.

  2. Another idea/potential path would be for Clikt to support interactive selection and setting of commands and options natively. An extension to how prompting works currently perhaps. This could allow any Clikt app to get this UX boost for free (via opt-in I expect).

Some benefits to either approach as I see them:

Are either of these ideas something you could see making sense as part of Clikt? I'd be happy to put together a proof of concept.

Thanks!

ajalt commented 7 months ago

No need to add any hooks, you can already get the registered parameters with these functions:

For example:

class Command : CliktCommand(invokeWithoutSubcommand = true) {
    //...
    override fun run() {
        if(currentContext.invokedSubcommand == null) {
            echo("This command's options: " + registeredOptions().map { it.names })
        }
    }
}

I don't have plans on adding a TUI in the short term, but if you build one for yourself and are able to share it, I'd love to see what you come up with.

jaytee commented 7 months ago

Totally missed those functions, will give it a shot using them!