M flag.go => flag.go +41 -17
@@ 72,6 72,8 @@ func (p *Parser) Parse(args []string, v interface{}) error {
return nil
}
+var durationType = reflect.TypeOf(time.Duration(0))
+
func (p *Parser) parseFlags(args []string, v interface{}) error {
if len(args) == 0 {
return nil
@@ 83,8 85,6 @@ func (p *Parser) parseFlags(args []string, v interface{}) error {
fs.SetOutput(ioutil.Discard)
fs.Usage = nil
- durationType := reflect.TypeOf(time.Duration(0))
-
// extract the flags from the struct
val := reflect.ValueOf(v).Elem()
str := reflect.TypeOf(v).Elem()
@@ 116,26 116,50 @@ func (p *Parser) parseFlags(args []string, v interface{}) error {
}
}
- if err := fs.Parse(args[1:]); err != nil {
- return err
+ var (
+ nonFlags []string
+ flagSet map[string]bool
+ )
+ args = args[1:]
+ for len(args) > 0 {
+ if err := fs.Parse(args); err != nil {
+ return err
+ }
+
+ args = nil
+ curNonFlags := fs.Args()
+ for i, nf := range curNonFlags {
+ if nf == "--" {
+ // ignore this one, but treat all subsequent as non-flags
+ nonFlags = append(nonFlags, curNonFlags[i+1:]...)
+ break
+ }
+ if ((strings.HasPrefix(nf, "-") && len(nf) > 1) ||
+ (strings.HasPrefix(nf, "--") && len(nf) > 2)) &&
+ !strings.HasPrefix(nf, "---") {
+
+ // this is a flag, stop non-flags here
+ args = curNonFlags[i:]
+ break
+ }
+ nonFlags = append(nonFlags, nf)
+ }
+
+ if _, ok := v.(interface{ SetFlags(map[string]bool) }); ok {
+ fs.Visit(func(fl *stdflag.Flag) {
+ if flagSet == nil {
+ flagSet = make(map[string]bool)
+ }
+ flagSet[fl.Name] = true
+ })
+ }
}
if sa, ok := v.(interface{ SetArgs([]string) }); ok {
- args := fs.Args()
- if len(args) == 0 {
- args = nil
- }
- sa.SetArgs(args)
+ sa.SetArgs(nonFlags)
}
if sf, ok := v.(interface{ SetFlags(map[string]bool) }); ok {
- set := make(map[string]bool)
- fs.Visit(func(fl *stdflag.Flag) {
- set[fl.Name] = true
- })
- if len(set) == 0 {
- set = nil
- }
- sf.SetFlags(set)
+ sf.SetFlags(flagSet)
}
return nil
M flag_test.go => flag_test.go +20 -0
@@ 107,6 107,26 @@ func TestParseFlags(t *testing.T) {
want: &F{},
err: "invalid value",
},
+ {
+ args: []string{"arg1", "-i", "1", "arg2", "-b"},
+ want: &F{
+ I: 1,
+ B: true,
+ args: []string{"arg1", "arg2"},
+ flags: map[string]bool{"i": true, "b": true},
+ },
+ },
+ {
+ args: []string{"arg1", "-z", "arg2"},
+ want: &F{},
+ err: "not defined: -z",
+ },
+ {
+ args: []string{"arg1", "--", "-i", "2"},
+ want: &F{
+ args: []string{"arg1", "-i", "2"},
+ },
+ },
}
var p Parser