mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Add group flags
This commit is contained in:
parent
dbf85f6104
commit
ec6fe6b61c
2 changed files with 148 additions and 1 deletions
60
command.go
60
command.go
|
@ -139,6 +139,8 @@ type Command struct {
|
||||||
iflags *flag.FlagSet
|
iflags *flag.FlagSet
|
||||||
// parentsPflags is all persistent flags of cmd's parents.
|
// parentsPflags is all persistent flags of cmd's parents.
|
||||||
parentsPflags *flag.FlagSet
|
parentsPflags *flag.FlagSet
|
||||||
|
// lnamedFlagSets contains local named flags.
|
||||||
|
lnamedFlagSets *NamedFlagSets
|
||||||
// globNormFunc is the global normalization function
|
// globNormFunc is the global normalization function
|
||||||
// that we can use on every pflag set and children commands
|
// that we can use on every pflag set and children commands
|
||||||
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
|
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
|
||||||
|
@ -514,7 +516,8 @@ Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "he
|
||||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
|
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
{{.LocalNonNamedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableNamedFlags}}
|
||||||
|
{{.NamedFlagSets.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
||||||
|
|
||||||
Global Flags:
|
Global Flags:
|
||||||
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
|
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
|
||||||
|
@ -578,6 +581,7 @@ func stripFlags(args []string, c *Command) []string {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
|
|
||||||
commands := []string{}
|
commands := []string{}
|
||||||
flags := c.Flags()
|
flags := c.Flags()
|
||||||
|
@ -1046,6 +1050,7 @@ func (c *Command) validateRequiredFlags() error {
|
||||||
// If c already has help flag, it will do nothing.
|
// If c already has help flag, it will do nothing.
|
||||||
func (c *Command) InitDefaultHelpFlag() {
|
func (c *Command) InitDefaultHelpFlag() {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
if c.Flags().Lookup("help") == nil {
|
if c.Flags().Lookup("help") == nil {
|
||||||
usage := "help for "
|
usage := "help for "
|
||||||
if c.Name() == "" {
|
if c.Name() == "" {
|
||||||
|
@ -1067,6 +1072,7 @@ func (c *Command) InitDefaultVersionFlag() {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
if c.Flags().Lookup("version") == nil {
|
if c.Flags().Lookup("version") == nil {
|
||||||
usage := "version for "
|
usage := "version for "
|
||||||
if c.Name() == "" {
|
if c.Name() == "" {
|
||||||
|
@ -1475,6 +1481,31 @@ func (c *Command) Flags() *flag.FlagSet {
|
||||||
return c.flags
|
return c.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamedFlagSets returns all the named FlagSet that applies to this command.
|
||||||
|
func (c *Command) NamedFlagSets() *NamedFlagSets {
|
||||||
|
if c.lnamedFlagSets == nil {
|
||||||
|
c.lnamedFlagSets = NewNamedFlagSets(c.Name(), flag.ContinueOnError)
|
||||||
|
}
|
||||||
|
return c.lnamedFlagSets
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamedFlags returns the specific named FlagSet that applies to this command.
|
||||||
|
func (c *Command) NamedFlags(name string) *flag.FlagSet {
|
||||||
|
nfs := c.NamedFlagSets()
|
||||||
|
flags, ok := nfs.FlagSet(name)
|
||||||
|
if !ok {
|
||||||
|
if c.flagErrorBuf == nil {
|
||||||
|
c.flagErrorBuf = new(bytes.Buffer)
|
||||||
|
}
|
||||||
|
flags.SetOutput(c.flagErrorBuf)
|
||||||
|
if c.globNormFunc != nil {
|
||||||
|
flags.SetNormalizeFunc(c.globNormFunc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.
|
// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.
|
||||||
func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
|
func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
|
||||||
persistentFlags := c.PersistentFlags()
|
persistentFlags := c.PersistentFlags()
|
||||||
|
@ -1488,9 +1519,23 @@ func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LocalNonNamedFlags are flags specific to this command which are NOT named.
|
||||||
|
func (c *Command) LocalNonNamedFlags() *flag.FlagSet {
|
||||||
|
namedFlags := c.NamedFlagSets().Flatten()
|
||||||
|
|
||||||
|
out := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||||
|
c.LocalFlags().VisitAll(func(f *flag.Flag) {
|
||||||
|
if namedFlags.Lookup(f.Name) == nil {
|
||||||
|
out.AddFlag(f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// LocalFlags returns the local FlagSet specifically set in the current command.
|
// LocalFlags returns the local FlagSet specifically set in the current command.
|
||||||
func (c *Command) LocalFlags() *flag.FlagSet {
|
func (c *Command) LocalFlags() *flag.FlagSet {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
|
|
||||||
if c.lflags == nil {
|
if c.lflags == nil {
|
||||||
c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||||
|
@ -1517,6 +1562,7 @@ func (c *Command) LocalFlags() *flag.FlagSet {
|
||||||
// InheritedFlags returns all flags which were inherited from parent commands.
|
// InheritedFlags returns all flags which were inherited from parent commands.
|
||||||
func (c *Command) InheritedFlags() *flag.FlagSet {
|
func (c *Command) InheritedFlags() *flag.FlagSet {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
|
|
||||||
if c.iflags == nil {
|
if c.iflags == nil {
|
||||||
c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||||
|
@ -1568,6 +1614,7 @@ func (c *Command) ResetFlags() {
|
||||||
c.lflags = nil
|
c.lflags = nil
|
||||||
c.iflags = nil
|
c.iflags = nil
|
||||||
c.parentsPflags = nil
|
c.parentsPflags = nil
|
||||||
|
c.lnamedFlagSets = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
|
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
|
||||||
|
@ -1596,6 +1643,11 @@ func (c *Command) HasAvailableFlags() bool {
|
||||||
return c.Flags().HasAvailableFlags()
|
return c.Flags().HasAvailableFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasAvailableNamedFlags checks if the command contains any named flags which are not hidden or deprecated.
|
||||||
|
func (c *Command) HasAvailableNamedFlags() bool {
|
||||||
|
return c.NamedFlagSets().Flatten().HasAvailableFlags()
|
||||||
|
}
|
||||||
|
|
||||||
// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
|
// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
|
||||||
func (c *Command) HasAvailablePersistentFlags() bool {
|
func (c *Command) HasAvailablePersistentFlags() bool {
|
||||||
return c.PersistentFlags().HasAvailableFlags()
|
return c.PersistentFlags().HasAvailableFlags()
|
||||||
|
@ -1648,6 +1700,7 @@ func (c *Command) ParseFlags(args []string) error {
|
||||||
}
|
}
|
||||||
beforeErrorBufLen := c.flagErrorBuf.Len()
|
beforeErrorBufLen := c.flagErrorBuf.Len()
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
c.mergeNamedFlags()
|
||||||
|
|
||||||
// do it here after merging all flags and just before parse
|
// do it here after merging all flags and just before parse
|
||||||
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
|
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
|
||||||
|
@ -1674,6 +1727,11 @@ func (c *Command) mergePersistentFlags() {
|
||||||
c.Flags().AddFlagSet(c.parentsPflags)
|
c.Flags().AddFlagSet(c.parentsPflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeNamedFlags merges c.NamedFlagSets() to c.Flags()
|
||||||
|
func (c *Command) mergeNamedFlags() {
|
||||||
|
c.Flags().AddFlagSet(c.NamedFlagSets().Flatten())
|
||||||
|
}
|
||||||
|
|
||||||
// updateParentsPflags updates c.parentsPflags by adding
|
// updateParentsPflags updates c.parentsPflags by adding
|
||||||
// new persistent flags of all parents.
|
// new persistent flags of all parents.
|
||||||
// If c.parentsPflags == nil, it makes new.
|
// If c.parentsPflags == nil, it makes new.
|
||||||
|
|
89
named_flag_sets.go
Normal file
89
named_flag_sets.go
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package cobra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NamedFlagSets stores named flag sets in the order of calling FlagSet.
|
||||||
|
type NamedFlagSets struct {
|
||||||
|
name string
|
||||||
|
errorHandling pflag.ErrorHandling
|
||||||
|
|
||||||
|
// order is an ordered list of flag set names.
|
||||||
|
order []string
|
||||||
|
// flagSets stores the flag sets by name.
|
||||||
|
flagSets map[string]*pflag.FlagSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNamedFlagSets(name string, errorHandling pflag.ErrorHandling) *NamedFlagSets {
|
||||||
|
return &NamedFlagSets{
|
||||||
|
name: name,
|
||||||
|
errorHandling: errorHandling,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagSet returns the flag set with the given name and adds it to the
|
||||||
|
// ordered name list if it is not in there yet.
|
||||||
|
func (nfs *NamedFlagSets) FlagSet(name string) (*pflag.FlagSet, bool) {
|
||||||
|
if nfs.flagSets == nil {
|
||||||
|
nfs.flagSets = map[string]*pflag.FlagSet{}
|
||||||
|
}
|
||||||
|
var ok bool
|
||||||
|
if _, ok = nfs.flagSets[name]; !ok {
|
||||||
|
flagSet := pflag.NewFlagSet(name, nfs.errorHandling)
|
||||||
|
nfs.flagSets[name] = flagSet
|
||||||
|
nfs.order = append(nfs.order, name)
|
||||||
|
}
|
||||||
|
return nfs.flagSets[name], ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten returns a single flag set containing all the flag sets
|
||||||
|
// in the NamedFlagSet
|
||||||
|
func (nfs *NamedFlagSets) Flatten() *pflag.FlagSet {
|
||||||
|
out := pflag.NewFlagSet(nfs.name, nfs.errorHandling)
|
||||||
|
for _, fs := range nfs.flagSets {
|
||||||
|
out.AddFlagSet(fs)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagUsages returns a string containing the usage information for all flags in
|
||||||
|
// the FlagSet
|
||||||
|
func (nfs *NamedFlagSets) FlagUsages() string {
|
||||||
|
return nfs.FlagUsagesWrapped(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nfs *NamedFlagSets) FlagUsagesWrapped(cols int) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, name := range nfs.order {
|
||||||
|
fs := nfs.flagSets[name]
|
||||||
|
if !fs.HasFlags() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wideFS := pflag.NewFlagSet("", pflag.ExitOnError)
|
||||||
|
wideFS.AddFlagSet(fs)
|
||||||
|
|
||||||
|
var zzz string
|
||||||
|
if cols > 24 {
|
||||||
|
zzz = strings.Repeat("z", cols-24)
|
||||||
|
wideFS.Int(zzz, 0, strings.Repeat("z", cols-24))
|
||||||
|
}
|
||||||
|
|
||||||
|
s := fmt.Sprintf("\n%s Flags:\n%s", strings.ToUpper(name[:1])+name[1:], wideFS.FlagUsagesWrapped(cols))
|
||||||
|
|
||||||
|
if cols > 24 {
|
||||||
|
i := strings.Index(s, zzz)
|
||||||
|
lines := strings.Split(s[:i], "\n")
|
||||||
|
fmt.Fprint(&buf, strings.Join(lines[:len(lines)-1], "\n"))
|
||||||
|
fmt.Fprintln(&buf)
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(&buf, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
Loading…
Reference in a new issue