github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/flags/flags.go (about) 1 package flags 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 "strings" 8 9 "github.com/cloudfoundry/cli/flags/flag" 10 ) 11 12 type FlagSet interface { 13 fmt.Stringer 14 GetName() string 15 GetValue() interface{} 16 Set(string) 17 } 18 19 type FlagContext interface { 20 Parse(...string) error 21 Args() []string 22 Int(string) int 23 Bool(string) bool 24 String(string) string 25 StringSlice(string) []string 26 IsSet(string) bool 27 SkipFlagParsing(bool) 28 } 29 30 type flagContext struct { 31 flagsets map[string]FlagSet 32 args []string 33 cmdFlags map[string]FlagSet //valid flags for command 34 cursor int 35 skipFlagParsing bool 36 } 37 38 func NewFlagContext(cmdFlags map[string]FlagSet) FlagContext { 39 return &flagContext{ 40 flagsets: make(map[string]FlagSet), 41 cmdFlags: cmdFlags, 42 cursor: 0, 43 } 44 } 45 46 func (c *flagContext) Parse(args ...string) error { 47 var flagset FlagSet 48 var ok bool 49 var v string 50 var err error 51 52 c.setDefaultFlagValueIfAny() 53 54 for c.cursor <= len(args)-1 { 55 arg := args[c.cursor] 56 57 if !c.skipFlagParsing && (strings.HasPrefix(arg, "-") || strings.HasPrefix(arg, "--")) { 58 flg := strings.TrimLeft(strings.TrimLeft(arg, "-"), "-") 59 60 c.extractEqualSignIfAny(&flg, &args) 61 62 if flagset, ok = c.cmdFlags[flg]; !ok { 63 return errors.New("Invalid flag: " + arg) 64 } 65 66 switch flagset.GetValue().(type) { 67 case bool: 68 c.flagsets[flg] = &cliFlags.BoolFlag{Name: flg, Value: c.getBoolFlagValue(args)} 69 case int: 70 if v, err = c.getFlagValue(args); err != nil { 71 return err 72 } 73 i, err := strconv.ParseInt(v, 10, 32) 74 if err != nil { 75 return errors.New("Value for flag '" + flg + "' must be integer") 76 } 77 c.flagsets[flg] = &cliFlags.IntFlag{Name: flg, Value: int(i)} 78 case string: 79 if v, err = c.getFlagValue(args); err != nil { 80 return err 81 } 82 c.flagsets[flg] = &cliFlags.StringFlag{Name: flg, Value: v} 83 case []string: 84 if v, err = c.getFlagValue(args); err != nil { 85 return err 86 } 87 if _, ok = c.flagsets[flg]; !ok { 88 c.flagsets[flg] = &cliFlags.StringSliceFlag{Name: flg, Value: []string{v}} 89 } else { 90 c.flagsets[flg].Set(v) 91 } 92 } 93 } else { 94 c.args = append(c.args, args[c.cursor]) 95 } 96 c.cursor++ 97 } 98 return nil 99 } 100 101 func (c *flagContext) getFlagValue(args []string) (string, error) { 102 if c.cursor >= len(args)-1 { 103 return "", errors.New("No value provided for flag: " + args[c.cursor]) 104 } 105 106 c.cursor++ 107 return args[c.cursor], nil 108 } 109 110 func (c *flagContext) getBoolFlagValue(args []string) bool { 111 if c.cursor >= len(args)-1 { 112 return true 113 } 114 115 b, err := strconv.ParseBool(args[c.cursor+1]) 116 if err == nil { 117 c.cursor++ 118 return b 119 } 120 return true 121 } 122 123 func (c *flagContext) Args() []string { 124 return c.args 125 } 126 127 func (c *flagContext) IsSet(k string) bool { 128 if _, ok := c.flagsets[k]; ok { 129 return true 130 } 131 return false 132 } 133 134 func (c *flagContext) Int(k string) int { 135 if _, ok := c.flagsets[k]; ok { 136 v := c.flagsets[k].GetValue() 137 switch v.(type) { 138 case int: 139 return v.(int) 140 } 141 } 142 return 0 143 } 144 145 func (c *flagContext) String(k string) string { 146 if _, ok := c.flagsets[k]; ok { 147 v := c.flagsets[k].GetValue() 148 switch v.(type) { 149 case string: 150 return v.(string) 151 } 152 } 153 return "" 154 } 155 156 func (c *flagContext) Bool(k string) bool { 157 if _, ok := c.flagsets[k]; ok { 158 v := c.flagsets[k].GetValue() 159 switch v.(type) { 160 case bool: 161 return v.(bool) 162 } 163 } 164 return false 165 } 166 167 func (c *flagContext) StringSlice(k string) []string { 168 if _, ok := c.flagsets[k]; ok { 169 v := c.flagsets[k].GetValue() 170 switch v.(type) { 171 case []string: 172 return v.([]string) 173 } 174 } 175 return []string{} 176 } 177 178 func (c *flagContext) SkipFlagParsing(skip bool) { 179 c.skipFlagParsing = skip 180 } 181 182 func (c *flagContext) extractEqualSignIfAny(flg *string, args *[]string) { 183 if strings.Contains(*flg, "=") { 184 tmpAry := strings.SplitN(*flg, "=", 2) 185 *flg = tmpAry[0] 186 tmpArg := append((*args)[:c.cursor], tmpAry[1]) 187 *args = append(tmpArg, (*args)[c.cursor:]...) 188 } 189 } 190 191 func (c *flagContext) setDefaultFlagValueIfAny() { 192 var v interface{} 193 194 for flgName, flg := range c.cmdFlags { 195 v = flg.GetValue() 196 switch v.(type) { 197 case bool: 198 if v.(bool) != false { 199 c.flagsets[flgName] = &cliFlags.BoolFlag{Name: flgName, Value: v.(bool)} 200 } 201 case int: 202 if v.(int) != 0 { 203 c.flagsets[flgName] = &cliFlags.IntFlag{Name: flgName, Value: v.(int)} 204 } 205 case string: 206 if len(v.(string)) != 0 { 207 c.flagsets[flgName] = &cliFlags.StringFlag{Name: flgName, Value: v.(string)} 208 } 209 case []string: 210 if len(v.([]string)) != 0 { 211 c.flagsets[flgName] = &cliFlags.StringSliceFlag{Name: flgName, Value: v.([]string)} 212 } 213 } 214 } 215 216 }