-
Notifications
You must be signed in to change notification settings - Fork 128
Open
Description
When using class inheritance to share common options between commands, options passed to parent commands are not accessible to subcommands, even though both commands inherit from the same base class with shared option definitions. The same issue is present with other ways of sharing options.
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.groups.OptionGroup
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
class CommonOptions : OptionGroup("Common options") {
val verbose by option("-v", "--verbose")
.flag(default = false, defaultForHelp = "false")
.help("Show verbose output")
}
open class MyCli : CliktCommand() {
override val invokeWithoutSubcommand: Boolean = true
val commonOptions by CommonOptions()
override fun run() {
echo("Root verbose: ${commonOptions.verbose}")
// Not checking `currentContext.invokedSubcommand == null` on purpose to always print `commonOptions`
}
}
class Count : MyCli() {
override fun run() {
echo("Count verbose: ${commonOptions.verbose}")
}
}
fun main(args: Array<String>) {
MyCli().subcommands(Count()).main(args)
}Current output:
$ mycli -v count
Root verbose: true
Count verbose: false # ❌ Should be true
$ mycli count -v
Root verbose: false
Count verbose: true # ✅ Works as expectedExpected output:
$ mycli -v count
Root verbose: true
Count verbose: true # ✅ Should inherit parent's value
$ mycli count -v
Root verbose: false # ✅ OK - subcommand option doesn't affect parent, though I wouldn't mind if it did.
Count verbose: true # ✅ Works as expectedComparison with other languages:
- Go (Cobra):
// Same variable reference shared across all commands
var verbose bool
var rootCmd = &cobra.Command{
Use: "root",
Short: "My root command for a basic Cobra CLI.",
}
var countCmd = &cobra.Command{
Use: "count",
Short: "Count command for a basic Cobra CLI.",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Is verbose: ", verbose)
},
}
func main() {
rootCmd.AddCommand(countCmd)
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose output")
}- C# (DotMake)
[CliCommand(ShortFormAutoGenerate = false)]
public class RootCommand
{
[CliOption(Description = "Whether to show verbose output", Recursive = true, Aliases = ["-v"])]
public bool Verbose { get; set; }
}
[CliCommand(Parent = typeof(RootCommand))]
public class CountCommand
{
// RootCommand is injected automatically, so we can access all its options.
public required RootCommand RootCommand { get; set; }
public void Run()
{
// This feels weird to use, but at least it works.
Console.WriteLine($"Verbose: {RootCommand.Verbose}");
}
}Metadata
Metadata
Assignees
Labels
No labels