297 lines
5.5 KiB
Go
297 lines
5.5 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package flags
|
|
|
|
import "fmt"
|
|
|
|
type GroupModifier func(g *Group)
|
|
|
|
// Don't display the group name of the flags
|
|
func HideGroupName() GroupModifier {
|
|
return func(g *Group) {
|
|
g.showGroupName = false
|
|
}
|
|
}
|
|
|
|
// Don't display this group of flags
|
|
func HideGroup() GroupModifier {
|
|
return func(g *Group) {
|
|
g.hidden = true
|
|
}
|
|
}
|
|
|
|
type Group struct {
|
|
flags []*Flag // flags attached to group
|
|
hidden bool // group should not be displayed
|
|
name string // name of the group
|
|
set *Set // Set group is attached to
|
|
showGroupName bool // group name should be included in display
|
|
}
|
|
|
|
func newGroup(s *Set, n string, modifiers ...GroupModifier) *Group {
|
|
if s == nil {
|
|
panic("group must be attached to set")
|
|
}
|
|
g := &Group{
|
|
set: s,
|
|
name: n,
|
|
flags: []*Flag{},
|
|
showGroupName: true,
|
|
}
|
|
|
|
for _, fn := range modifiers {
|
|
fn(g)
|
|
}
|
|
|
|
s.groups = append(s.groups, g)
|
|
|
|
return g
|
|
}
|
|
|
|
// Add a flag to the group. This is used to relocate
|
|
// a flag from one group to another.
|
|
func (g *Group) Add(f *Flag) (err error) {
|
|
if f.group == g {
|
|
return nil
|
|
}
|
|
|
|
if f.group != nil {
|
|
idx := -1
|
|
for i, flg := range f.group.flags {
|
|
if flg.longName == f.longName {
|
|
idx = i
|
|
break
|
|
}
|
|
}
|
|
if idx >= 0 {
|
|
f.group.flags = append(f.group.flags[0:idx], f.group.flags[idx+1:]...)
|
|
}
|
|
}
|
|
|
|
f.group = g
|
|
g.flags = append(g.flags, f)
|
|
return err
|
|
}
|
|
|
|
// Name of the group
|
|
func (g *Group) Name() string {
|
|
return g.name
|
|
}
|
|
|
|
// Flags contained by this group
|
|
func (g *Group) Flags() []*Flag {
|
|
f := make([]*Flag, len(g.flags))
|
|
copy(f, g.flags)
|
|
return f
|
|
}
|
|
|
|
// Add a new BooleanType flag
|
|
func (g *Group) Bool(
|
|
name string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
return newFlag(name, BooleanType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new BooleanType flag using variable
|
|
func (g *Group) BoolVar(
|
|
name string,
|
|
ptr *bool,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Bool(name, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new StringType flag
|
|
func (g *Group) String(
|
|
name string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
return newFlag(name, StringType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new StringType flag using variable
|
|
func (g *Group) StringVar(
|
|
name string,
|
|
ptr *string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.String(name, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new ArrayType flag
|
|
func (g *Group) Array(
|
|
name string,
|
|
subtype Type,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
modifiers = append(modifiers, SetSubtype(subtype))
|
|
return newFlag(name, ArrayType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new ArrayType flag using variable
|
|
func (g *Group) ArrayVar(
|
|
name string,
|
|
subtype Type,
|
|
ptr interface{},
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Array(name, subtype, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new FloatType flag
|
|
func (g *Group) Float(
|
|
name string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
return newFlag(name, FloatType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new FloatType flag using variable
|
|
func (g *Group) FloatVar(
|
|
name string,
|
|
ptr *float64,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Float(name, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new Integer flag
|
|
func (g *Group) Integer(
|
|
name string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
return newFlag(name, IntegerType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new Integer flag using variable
|
|
func (g *Group) IntegerVar(
|
|
name string,
|
|
ptr *int64,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Integer(name, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new IncrementType flag
|
|
func (g *Group) Increment(
|
|
name string,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
modifiers = append(modifiers, SetSubtype(IntegerType))
|
|
return newFlag(name, IncrementType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new IncrementType flag using variable
|
|
func (g *Group) IncrementVar(
|
|
name string,
|
|
ptr *int64,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Increment(name, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Add a new MapType flag
|
|
func (g *Group) Map(
|
|
name string,
|
|
subtype Type,
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
modifiers = append(modifiers, SetSubtype(subtype))
|
|
return newFlag(name, MapType, g, modifiers...)
|
|
}
|
|
|
|
// Add a new MaptType flag using variable
|
|
func (g *Group) MapVar(
|
|
name string,
|
|
subtype Type,
|
|
ptr interface{},
|
|
modifiers ...FlagModifier,
|
|
) *Flag {
|
|
f := g.Map(name, subtype, modifiers...)
|
|
f.ptr = true
|
|
f.value = ptr
|
|
|
|
return f
|
|
}
|
|
|
|
// Generate printable output of flag group
|
|
func (g *Group) Display(
|
|
indent int, // Number of spaces to indent
|
|
) string {
|
|
if g.hidden {
|
|
return ""
|
|
}
|
|
|
|
var pad int
|
|
opts := []string{}
|
|
desc := []string{}
|
|
|
|
for i, f := range g.flags {
|
|
if f.hidden {
|
|
continue
|
|
}
|
|
if f.shortName != 0 {
|
|
opts = append(opts, fmt.Sprintf("-%c,", f.shortName))
|
|
} else {
|
|
opts = append(opts, " ")
|
|
}
|
|
switch f.kind {
|
|
case BooleanType:
|
|
opts[i] = fmt.Sprintf("%s --[no-]%s", opts[i], f.longName)
|
|
case IncrementType:
|
|
opts[i] = fmt.Sprintf("%s --%s", opts[i], f.longName)
|
|
default:
|
|
opts[i] = fmt.Sprintf("%s --%s VALUE", opts[i], f.longName)
|
|
}
|
|
desc = append(desc, f.description)
|
|
if len(opts[i]) > pad {
|
|
pad = len(opts[i])
|
|
}
|
|
}
|
|
|
|
// If there were no flags to display (empty flag collection or all hidden)
|
|
// then just return an empty string
|
|
if len(opts) == 0 {
|
|
return ""
|
|
}
|
|
|
|
pad += indent
|
|
var d string
|
|
|
|
if g.showGroupName {
|
|
d = fmt.Sprintf("%s:\n", g.name)
|
|
}
|
|
|
|
for i := 0; i < len(opts); i++ {
|
|
d = fmt.Sprintf("%s%4s%-*s%s\n", d, "", pad, opts[i], desc[i])
|
|
}
|
|
|
|
return d
|
|
}
|