Open medyagh opened 3 years ago
Hi @medyagh, yes this can be done. For example kubectl
does it while using Cobra (you can try with kubectl -h
). I haven't done it myself but I believe they do it using cobra.Command.SetUsageFunc()
and cobra.Command.SetHelpFunc()
.
kubectl
even provides a package you can use: "k8s.io/kubectl/pkg/util/templates"
and the code is here: https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/kubectl/pkg/util/templates
Here is an example PR that grouped commands for helm based on that package: https://github.com/helm/helm/pull/7917/files
Be aware that we reverted this PR in the end because the kubectl
package had impacts on the help output that went beyond command grouping. But these impacts may be ok for you, or you may find a way to work around it. See this comment for the impacts that we found: https://github.com/helm/helm/pull/7917#issuecomment-629675187
thanks for the response, I know about the grouping "the commands", (we have added that feature to minikube using the kubectl's lib), but that does Not help with adding groups for Flags. (it only helps with adding groups for Sub Commands) but I was hoping there was a native feature to group the flags of a command too.
for example i would like to see this to give me all of the flags but grouped into different groups
minikube start --help
Groups 1 flags
.
.
Groups 2 flags
.
.
Maybe you can give your support to #1003 which seems to implement this.
This issue is being marked as stale due to a long period of inactivity
+1 - this would be a great tool to improve the UX for more complex CLI commands. Curious to hear if anybody has found a way to solve this.
@marckhouzam My understanding of #1003 is that it implements grouping of subcommands, not flags.
I think this would also be a really useful command; I'm not sure about implementation but happy to review any PRs for it.
The ability to group flags would be really beneficial. +1 bump!
I just noticed that @knqyf263 has implemented this. So all it takes is a release now, or am I wrong? IMO this feature alone would justify a release.
I just noticed that @knqyf263 has implemented this. So all it takes is a release now, or am I wrong? IMO this feature alone would justify a release.
@marians That implementation is in another project 😉 https://github.com/aquasecurity/trivy/pull/2488 Those GitHub references are not very clear.
Yes, it is not this project. Sorry for confusing you. @marians
Oh dear, I didn't notice that. Thanks! And greetings to our partner Aqua.
Have you considered bringing this change here?
It seems like the discussion is suspended. Do the maintainers agree with this enhancement? If yes, I'd be happy to contribute upstream.
It seems like the discussion is suspended. Do the maintainers agree with this enhancement? If yes, I'd be happy to contribute upstream.
I got the impression that the implementations out there are project-specific (overriding the help text and adding specific flag groups). If we can get a PR with a generic solution with a clean API, then it would be appropriate for Cobra.
I really like the feature. Now I'm using NamedFlagSets
to group the flags in the Karmada project, see here for example.
The flags looks like
$ karmada-controller-manager --help
...
Generic flags:
--bind-address string
The IP address on which to listen for the --secure-port port. (default "0.0.0.0")
....
Logs flags:
--add-dir-header
If true, adds the file directory to the header of the log messages
....
I got the impression that the implementations out there are project-specific
Yes, it is a workaround as cobra doesn't support the feature.
NamedFlagSets
looks good to me. @RainbowMango Are you going to bring it upstream?
https://github.com/kubernetes/component-base/blob/b5a495af30a7bb04642ce82f4816b47e75f78dbe/cli/flag/sectioned.go#L33-L41
The maintainer might have better solutions.
I've opened a PR so that we can start a discussion. https://github.com/spf13/cobra/pull/1778
@medyagh can you share a full example of minikube command with flag groups?
An example from real command can help to answer:
Here's a demo, actually it's really easy:
func Test_spf13_cmdflags_groupby(t *testing.T) {
rootCmd := cobra.Command{
Use: "root",
Short: "root cmd description",
Long: "root cmd description",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("command args: %v\n", strings.Join(args, " "))
},
}
groups := map[*pflag.FlagSet]string{}
// group1
fs1 := pflag.NewFlagSet("features", pflag.ExitOnError)
fs1.Bool("feature1", true, "enable feature1")
fs1.Bool("feature2", true, "enable feature2")
fs1.Bool("feature3", true, "enable feature3")
rootCmd.Flags().AddFlagSet(fs1)
groups[fs1] = "features"
// group2
fs2 := pflag.NewFlagSet("patches", pflag.ExitOnError)
fs2.Bool("patch1", true, "apply patch1")
fs2.Bool("patch2", true, "apply patch2")
rootCmd.Flags().AddFlagSet(fs2)
groups[fs2] = "patches"
// cobra will:
// - call helpfunc to print help message if defined, otherwise
// - call usagefunc to print help message if defined, otherwise
// - call the generated default usagefunc
//
// here we use SetUsageFunc is enough.
rootCmd.SetUsageFunc(func(c *cobra.Command) error {
for fs, name := range groups {
usage := fs.FlagUsages()
idx := strings.IndexFunc(usage, func(r rune) bool {
return r != ' '
})
desc := strings.Repeat(" ", idx) + name + ":"
help := desc + "\n" + usage
fmt.Println(help)
}
return nil
})
// run
os.Args = []string{"root", "--feature3=false", "--patch2=false", "--help", "helloworld"}
err := rootCmd.Execute()
require.Nil(t, err)
}
in minikube our start command has many flags and we would like to group them for better readablility
so something like
is that possible?