clikt icon indicating copy to clipboard operation
clikt copied to clipboard

Best practice for "sharing" exit codes from chained subcommands

Open sschuberth opened this issue 2 years ago • 2 comments

I'm just wondering whether there is any best practice / built-in means to "share" exit codes from chained subcommands. Because if one subcommand fails, you may still want to continue running the other subcommands, i.e the failed command should not throw ProgramResult. In the end, the root command may want to collect all exit codes and pass the "worst" one to throw ProgramResult. So how would subcommands pass their exit codes back to the root command? It does not seem like the Context class is suitable for this.

sschuberth avatar Mar 28 '22 08:03 sschuberth

Context is the normal way to pass information between commands. However, since parent commands are run before their children, there isn't a way for the parent to act on any context information set by its children.

I can see the value in adding a command base class with a type parameter and a way to control child executions.

Maybe something along the lines of this:

abstract class CliktValueCommand<T, U> {
    abstract fun run(): T
    open fun runChildren(children: CliktValueCommand<U>) {
        for (child in children) child.run()
    }
}

abstract class CliktCommand : CliktValueCommand<Unit, Unit>

fun <U> CliktValueCommand<*, U>.subcommands(vararg children: CliktValueCommand<U, *>) {...}

That would open up a lot of possibilities for using subcommands in new ways, although it would be pretty challenging to implement, and would require a rewrite of the parsing algorithm.

ajalt avatar Mar 28 '22 16:03 ajalt

The line for (child in children) child.run() actually reminds me of this discussion again: Looks like this would also be easier to solve if run() just returned an Int which by default is used as the exit code.

sschuberth avatar Mar 30 '22 05:03 sschuberth