deal with "-" as option value

This commit is contained in:
Alex Flint 2017-02-21 09:08:08 -08:00
parent 2c249ee1fc
commit c4c162448c
2 changed files with 56 additions and 3 deletions

View File

@ -174,6 +174,8 @@ func NewParser(config Config, dests ...interface{}) (*Parser, error) {
} }
switch { switch {
case strings.HasPrefix(key, "---"):
errs = append(errs, fmt.Sprintf("%s.%s: too many hyphens", t.Name(), field.Name))
case strings.HasPrefix(key, "--"): case strings.HasPrefix(key, "--"):
spec.long = key[2:] spec.long = key[2:]
case strings.HasPrefix(key, "-"): case strings.HasPrefix(key, "-"):
@ -285,7 +287,7 @@ func process(specs []*spec, args []string) error {
continue continue
} }
if !strings.HasPrefix(arg, "-") || allpositional { if !isFlag(arg) || allpositional {
positionals = append(positionals, arg) positionals = append(positionals, arg)
continue continue
} }
@ -309,7 +311,7 @@ func process(specs []*spec, args []string) error {
if spec.multiple { if spec.multiple {
var values []string var values []string
if value == "" { if value == "" {
for i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") { for i+1 < len(args) && !isFlag(args[i+1]) {
values = append(values, args[i+1]) values = append(values, args[i+1])
i++ i++
} }
@ -331,7 +333,7 @@ func process(specs []*spec, args []string) error {
// if we have something like "--foo" then the value is the next argument // if we have something like "--foo" then the value is the next argument
if value == "" { if value == "" {
if i+1 == len(args) || strings.HasPrefix(args[i+1], "-") { if i+1 == len(args) || isFlag(args[i+1]) {
return fmt.Errorf("missing value for %s", arg) return fmt.Errorf("missing value for %s", arg)
} }
value = args[i+1] value = args[i+1]
@ -370,6 +372,11 @@ func process(specs []*spec, args []string) error {
return nil return nil
} }
// isFlag returns true if a token is a flag such as "-v" or "--user" but not "-" or "--"
func isFlag(s string) bool {
return strings.HasPrefix(s, "-") && strings.TrimLeft(s, "-") != ""
}
// validate an argument spec after arguments have been parse // validate an argument spec after arguments have been parse
func validate(spec []*spec) error { func validate(spec []*spec) error {
for _, arg := range spec { for _, arg := range spec {

View File

@ -693,3 +693,49 @@ func TestEmptyArgs(t *testing.T) {
// put the original arguments back // put the original arguments back
os.Args = origArgs os.Args = origArgs
} }
func TestTooManyHyphens(t *testing.T) {
var args struct {
TooManyHyphens string `arg:"---x"`
}
err := parse("--foo -", &args)
assert.Error(t, err)
}
func TestHyphenAsOption(t *testing.T) {
var args struct {
Foo string
}
err := parse("--foo -", &args)
require.NoError(t, err)
assert.Equal(t, "-", args.Foo)
}
func TestHyphenAsPositional(t *testing.T) {
var args struct {
Foo string `arg:"positional"`
}
err := parse("-", &args)
require.NoError(t, err)
assert.Equal(t, "-", args.Foo)
}
func TestHyphenInMultiOption(t *testing.T) {
var args struct {
Foo []string
Bar int
}
err := parse("--foo --- x - y --bar 3", &args)
require.NoError(t, err)
assert.Equal(t, []string{"---", "x", "-", "y"}, args.Foo)
assert.Equal(t, 3, args.Bar)
}
func TestHyphenInMultiPositional(t *testing.T) {
var args struct {
Foo []string `arg:"positional"`
}
err := parse("--- x - y", &args)
require.NoError(t, err)
assert.Equal(t, []string{"---", "x", "-", "y"}, args.Foo)
}