github.com/bilus/oya@v0.0.3-0.20190301162104-da4acbd394c6/pkg/flags/flags.go (about) 1 package flags 2 3 import ( 4 "fmt" 5 "regexp" 6 ) 7 8 var switchFlagRx = regexp.MustCompile("^--([a-z][-a-zA-z_0-9]*)$") 9 var valueFlagRx = regexp.MustCompile("^--([a-z][-a-zA-z_0-9]*)=\"?([^\"]*)\"?$") 10 var maybeFlagRx = regexp.MustCompile("^--.*") 11 12 const TrueValue = "true" 13 14 type ErrRepeatedFlag struct { 15 Arg string 16 } 17 18 func (err ErrRepeatedFlag) Error() string { 19 return fmt.Sprintf("Flag %q specified more than once", err.Arg) 20 } 21 22 type ErrInvalidFlag struct { 23 Arg string 24 } 25 26 func (err ErrInvalidFlag) Error() string { 27 return fmt.Sprintf("Flag syntax invalid: %q", err.Arg) 28 } 29 30 func Parse(args []string) ([]string, map[string]string, error) { 31 positionalArgs := make([]string, 0, len(args)) 32 flags := make(map[string]string) 33 for _, arg := range args { 34 flag, value, ok, err := parseFlag(arg) 35 if err != nil { 36 return nil, nil, err 37 } 38 if ok { 39 if _, exists := flags[flag]; exists { 40 return nil, nil, ErrRepeatedFlag{ 41 Arg: arg, 42 } 43 } 44 flags[flag] = value 45 } else { 46 positionalArgs = append(positionalArgs, arg) 47 } 48 } 49 return positionalArgs, flags, nil 50 } 51 52 func parseFlag(arg string) (string, string, bool, error) { 53 if maybeFlagRx.MatchString(arg) { 54 if matches := switchFlagRx.FindStringSubmatch(arg); len(matches) == 2 { 55 return matches[1], TrueValue, true, nil 56 57 } else if matches := valueFlagRx.FindStringSubmatch(arg); len(matches) == 3 { 58 return matches[1], matches[2], true, nil 59 } 60 return "", "", false, ErrInvalidFlag{Arg: arg} 61 } 62 return arg, arg, false, nil 63 }