diff --git a/pkg/mflag/example/example.go b/pkg/mflag/example/example.go index fa26c97e1b638..b0d25fbfc6d0c 100644 --- a/pkg/mflag/example/example.go +++ b/pkg/mflag/example/example.go @@ -27,4 +27,5 @@ func main() { fmt.Printf("b: %b\n", b) fmt.Printf("-bool: %b\n", b2) fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String()) + fmt.Printf("ARGS: %v\n", flag.Args()) } diff --git a/pkg/mflag/flag.go b/pkg/mflag/flag.go index f721e04557f01..7a0e8bfb79bdd 100644 --- a/pkg/mflag/flag.go +++ b/pkg/mflag/flag.go @@ -77,6 +77,9 @@ import ( // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. var ErrHelp = errors.New("flag: help requested") +// ErrRetry is the error returned if you need to try letter by letter +var ErrRetry = errors.New("flag: retry") + // -- bool Value type boolValue bool @@ -733,21 +736,21 @@ func (f *FlagSet) usage() { } // parseOne parses one flag. It reports whether a flag was seen. -func (f *FlagSet) parseOne() (bool, error) { +func (f *FlagSet) parseOne() (bool, string, error) { if len(f.args) == 0 { - return false, nil + return false, "", nil } s := f.args[0] if len(s) == 0 || s[0] != '-' || len(s) == 1 { - return false, nil + return false, "", nil } if s[1] == '-' && len(s) == 2 { // "--" terminates the flags f.args = f.args[1:] - return false, nil + return false, "", nil } name := s[1:] if len(name) == 0 || name[0] == '=' { - return false, f.failf("bad flag syntax: %s", s) + return false, "", f.failf("bad flag syntax: %s", s) } // it's a flag. does it have an argument? @@ -767,14 +770,14 @@ func (f *FlagSet) parseOne() (bool, error) { if !alreadythere { if name == "-help" || name == "help" || name == "h" { // special case for nice help message. f.usage() - return false, ErrHelp + return false, "", ErrHelp } - return false, f.failf("flag provided but not defined: -%s", name) + return false, name, ErrRetry } if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg if has_value { if err := fv.Set(value); err != nil { - return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) + return false, "", f.failf("invalid boolean value %q for -%s: %v", value, name, err) } } else { fv.Set("true") @@ -787,17 +790,17 @@ func (f *FlagSet) parseOne() (bool, error) { value, f.args = f.args[0], f.args[1:] } if !has_value { - return false, f.failf("flag needs an argument: -%s", name) + return false, "", f.failf("flag needs an argument: -%s", name) } if err := flag.Value.Set(value); err != nil { - return false, f.failf("invalid value %q for flag -%s: %v", value, name, err) + return false, "", f.failf("invalid value %q for flag -%s: %v", value, name, err) } } if f.actual == nil { f.actual = make(map[string]*Flag) } f.actual[name] = flag - return true, nil + return true, "", nil } // Parse parses flag definitions from the argument list, which should not @@ -808,13 +811,34 @@ func (f *FlagSet) Parse(arguments []string) error { f.parsed = true f.args = arguments for { - seen, err := f.parseOne() + seen, name, err := f.parseOne() if seen { continue } if err == nil { break } + if err == ErrRetry { + if len(name) > 1 { + err = nil + for _, letter := range strings.Split(name, "") { + f.args = append([]string{"-" + letter}, f.args...) + seen2, _, err2 := f.parseOne() + if seen2 { + continue + } + if err2 != nil { + err = f.failf("flag provided but not defined: -%s", name) + break + } + } + if err == nil { + continue + } + } else { + err = f.failf("flag provided but not defined: -%s", name) + } + } switch f.errorHandling { case ContinueOnError: return err