Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,18 @@ If you specify description in description tag (`desc` by default) it will be use

```golang
Addr string `desc:"HTTP host"`
````
This description produces something like:
```sh
this description produces something like:
```
-addr value
HTTP host (default 127.0.0.1)
```

## Options for env tag

If you specify environment variable name in `env` tag, it will be used to set the value of the field.
```golang
SSL bool `env:"HTTP_SSL_VALUE"`
```

## Options for Parse function:

Expand Down Expand Up @@ -212,8 +215,14 @@ func EnvDivider(val string)
// Check existed validators in sflags/validator package.
func Validator(val ValidateFunc)

// Set to false if you don't want anonymous structure fields to be flatten.
// Set to false if you don't want anonymous structure fields to be flattened.
func Flatten(val bool)

// InheritHidden sets if fields should inherit the value of the hidden tag from parent structs.
func InheritHidden()

// InheritDeprecated sets if fields should inherit the value of the deprecated tag from parent structs.
func InheritDeprecated()
```


Expand Down
84 changes: 63 additions & 21 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import (
)

const (
defaultDescTag = "desc"
defaultFlagTag = "flag"
defaultEnvTag = "env"
defaultFlagDivider = "-"
defaultEnvDivider = "_"
defaultFlatten = true
defaultDescTag = "desc"
defaultFlagTag = "flag"
defaultEnvTag = "env"
defaultFlagDivider = "-"
defaultEnvDivider = "_"
defaultFlatten = true
defaultInheritHidden = false
defaultHidden = false
defaultInheritDeprecated = false
defaultDeprecated = false
)

// ValidateFunc describes a validation func,
Expand All @@ -22,14 +26,18 @@ const (
type ValidateFunc func(val string, field reflect.StructField, cfg interface{}) error

type opts struct {
descTag string
flagTag string
prefix string
envPrefix string
flagDivider string
envDivider string
flatten bool
validator ValidateFunc
descTag string
flagTag string
prefix string
envPrefix string
flagDivider string
envDivider string
flatten bool
validator ValidateFunc
inheritHidden bool
hidden bool
inheritDeprecated bool
deprecated bool
}

func (o opts) apply(optFuncs ...OptFunc) opts {
Expand All @@ -51,6 +59,22 @@ func FlagTag(val string) OptFunc { return func(opt *opts) { opt.flagTag = val }
// Prefix sets prefix that will be applied for all flags (if they are not marked as ~).
func Prefix(val string) OptFunc { return func(opt *opts) { opt.prefix = val } }

// InheritHidden enables inheriting the hidden flag for all nested flags if set for a parent flag
func InheritHidden() OptFunc { return func(opt *opts) { opt.inheritHidden = true } }

// hidden sets the hidden flag for all nested flags if set for a parent flag
func hidden(val bool) OptFunc {
return func(opt *opts) { opt.hidden = val }
}

// InheritDeprecated enables inheriting the deprecated flag for all nested flags if set for a parent flag
func InheritDeprecated() OptFunc { return func(opt *opts) { opt.inheritDeprecated = true } }

// deprecated sets the deprecated flag for all nested flags if set for a parent flag
func deprecated(val bool) OptFunc {
return func(opt *opts) { opt.deprecated = val }
}

// EnvPrefix sets prefix that will be applied for all environment variables (if they are not marked as ~).
func EnvPrefix(val string) OptFunc { return func(opt *opts) { opt.envPrefix = val } }

Expand Down Expand Up @@ -82,11 +106,15 @@ func hasOption(options []string, option string) bool {

func defOpts() opts {
return opts{
descTag: defaultDescTag,
flagTag: defaultFlagTag,
flagDivider: defaultFlagDivider,
envDivider: defaultEnvDivider,
flatten: defaultFlatten,
descTag: defaultDescTag,
flagTag: defaultFlagTag,
flagDivider: defaultFlagDivider,
envDivider: defaultEnvDivider,
flatten: defaultFlatten,
inheritHidden: defaultInheritHidden,
hidden: defaultHidden,
inheritDeprecated: defaultInheritDeprecated,
deprecated: defaultDeprecated,
}
}

Expand Down Expand Up @@ -120,6 +148,13 @@ func parseFlagTag(field reflect.StructField, opt opts) *Flag {
if opt.prefix != "" && !ignoreFlagPrefix {
flag.Name = opt.prefix + flag.Name
}

if opt.deprecated {
flag.Deprecated = opt.deprecated
}
if opt.hidden {
flag.Hidden = opt.hidden
}
return &flag
}

Expand Down Expand Up @@ -264,9 +299,16 @@ fields:
prefix = opt.prefix
}

nestedOpts := []OptFunc{copyOpts(opt), Prefix(prefix)}
if opt.inheritHidden {
nestedOpts = append(nestedOpts, hidden(flag.Hidden))
}
if opt.inheritDeprecated {
nestedOpts = append(nestedOpts, deprecated(flag.Deprecated))
}

nestedFlags, val := parseVal(fieldValue,
copyOpts(opt),
Prefix(prefix),
nestedOpts...,
)

// field contains a simple value.
Expand Down
106 changes: 106 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,58 @@ func TestParseStruct(t *testing.T) {
},
},
}
hiddenNestedCfg := &struct {
Sub struct {
Name string
Sub2 struct {
Name string
}
} `flag:",hidden"`
Sub3 struct {
Name string
}
}{
Sub: struct {
Name string
Sub2 struct {
Name string
}
}{
Name: "name_value",
Sub2: struct{ Name string }{
Name: "other_value",
},
},
Sub3: struct{ Name string }{
Name: "name_value",
},
}
deprecatedNestedCfg := &struct {
Sub struct {
Name string
Sub2 struct {
Name string
}
} `flag:",deprecated"`
Sub3 struct {
Name string
}
}{
Sub: struct {
Name string
Sub2 struct {
Name string
}
}{
Name: "name_value",
Sub2: struct{ Name string }{
Name: "other_value",
},
},
Sub3: struct{ Name string }{
Name: "name_value",
},
}
descCfg := &struct {
Name string `desc:"name description"`
Name2 string `description:"name2 description"`
Expand Down Expand Up @@ -347,6 +399,60 @@ func TestParseStruct(t *testing.T) {
},
expErr: nil,
},
{
name: "Inherit hidden parent flag",
cfg: hiddenNestedCfg,
optFuncs: []OptFunc{InheritHidden()},
expFlagSet: []*Flag{
{
Name: "sub-name",
EnvNames: []string{"SUB_NAME"},
DefValue: "name_value",
Value: newStringValue(&hiddenNestedCfg.Sub.Name),
Hidden: true,
},
{
Name: "sub-sub2-name",
EnvNames: []string{"SUB_SUB2_NAME"},
DefValue: "other_value",
Value: newStringValue(&hiddenNestedCfg.Sub.Sub2.Name),
Hidden: true,
},
{
Name: "sub3-name",
EnvNames: []string{"SUB3_NAME"},
DefValue: "name_value",
Value: newStringValue(&hiddenNestedCfg.Sub3.Name),
},
},
},
{
name: "Inherit deprecated parent flag",
cfg: deprecatedNestedCfg,
optFuncs: []OptFunc{InheritDeprecated()},
expFlagSet: []*Flag{
{
Name: "sub-name",
EnvNames: []string{"SUB_NAME"},
DefValue: "name_value",
Value: newStringValue(&deprecatedNestedCfg.Sub.Name),
Deprecated: true,
},
{
Name: "sub-sub2-name",
EnvNames: []string{"SUB_SUB2_NAME"},
DefValue: "other_value",
Value: newStringValue(&deprecatedNestedCfg.Sub.Sub2.Name),
Deprecated: true,
},
{
Name: "sub3-name",
EnvNames: []string{"SUB3_NAME"},
DefValue: "name_value",
Value: newStringValue(&deprecatedNestedCfg.Sub3.Name),
},
},
},
{
name: "DescCfg with custom desc tag",
cfg: descCfg,
Expand Down
Loading