Parse env-only vars

This commit is contained in:
Ilja Neumann 2023-06-03 09:50:42 +02:00
parent ccf62e0ffc
commit b928a1839a
2 changed files with 34 additions and 9 deletions

View File

@ -54,9 +54,10 @@ type spec struct {
separate bool // if true, each slice and map entry will have its own --flag
help string // the help text for this option
env string // the name of the environment variable for this option, or empty for none
defaultValue reflect.Value // default value for this option
defaultString string // default value for this option, in string form to be displayed in help text
placeholder string // name of the data in help
envOnly bool
defaultValue reflect.Value // default value for this option
defaultString string // default value for this option, in string form to be displayed in help text
placeholder string // name of the data in help
}
// command represents a named subcommand, or the top-level command
@ -343,7 +344,9 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) {
// Look at the tag
var isSubcommand bool // tracks whether this field is a subcommand
for _, key := range strings.Split(tag, ",") {
kvPairs := strings.Split(tag, ",")
for _, key := range kvPairs {
if key == "" {
continue
}
@ -360,7 +363,7 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) {
case strings.HasPrefix(key, "--"):
spec.long = key[2:]
case strings.HasPrefix(key, "-"):
if len(key) != 2 {
if len(key) > 2 {
errs = append(errs, fmt.Sprintf("%s.%s: short arguments must be one character only",
t.Name(), field.Name))
return false
@ -415,6 +418,12 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) {
spec.placeholder = strings.ToUpper(spec.field.Name)
}
if spec.env == "" && emptyLongAndShort(kvPairs) {
errs = append(errs, fmt.Sprintf("%s.%s: short arguments must be one character only",
t.Name(), field.Name))
return false
}
// if this is a subcommand then we've done everything we need to do
if isSubcommand {
return false
@ -788,6 +797,22 @@ func isFlag(s string) bool {
return strings.HasPrefix(s, "-") && strings.TrimLeft(s, "-") != ""
}
func emptyLongAndShort(kv []string) bool {
var noShort, noLong bool
for _, key := range kv {
if key == "-" {
noShort = true
}
if key == "--" {
noLong = true
}
}
return noShort && noLong
}
// val returns a reflect.Value corresponding to the current value for the
// given path
func (p *Parser) val(dest path) reflect.Value {

View File

@ -544,10 +544,10 @@ Options:
}
func TestUsageWithEnvOptions(t *testing.T) {
expectedUsage := "Usage: [CUSTOM=custom_value] [ENVONLY=envonly_value] example [-s SHORT]"
expectedUsage := "Usage: example [-s SHORT]"
expectedHelp := `
Usage: [CUSTOM=custom_value] [ENVONLY=envonly_value] example [-s SHORT]
Usage: example [-s SHORT]
Options:
-s SHORT [env: SHORT]
@ -652,10 +652,10 @@ Options:
}
func TestFailEnvOnly(t *testing.T) {
expectedUsage := "Usage: [AUTH_KEY=auth_key_value] example [--arg ARG]"
expectedUsage := "Usage: example [--arg ARG]"
expectedHelp := `
Usage: [AUTH_KEY=auth_key_value] example [--arg ARG]
Usage: example [--arg ARG]
Options:
--arg ARG, -a ARG [env: MY_ARG]