Merge pull request #38 from thesyncim/master

add ability to parse []string types
This commit is contained in:
Jeremy Saenz 2013-09-26 15:06:15 -07:00
commit 3c97f95b6a
4 changed files with 171 additions and 8 deletions

View File

@ -84,3 +84,61 @@ func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
expect(t, parsedOption, "my-option")
expect(t, firstArg, "my-arg")
}
func TestApp_ParseSliceFlags(t *testing.T) {
var parsedOption, firstArg string
var parsedIntSlice []int
var parsedStringSlice []string
app := cli.NewApp()
command := cli.Command{
Name: "cmd",
Flags: []cli.Flag{
cli.IntSliceFlag{"p", &cli.IntSlice{}, "set one or more ip addr"},
cli.StringSliceFlag{"ip", &cli.StringSlice{}, "set one or more ports to open"},
},
Action: func(c *cli.Context) {
parsedIntSlice = c.IntSlice("p")
parsedStringSlice = c.StringSlice("ip")
parsedOption = c.String("option")
firstArg = c.Args()[0]
},
}
app.Commands = []cli.Command{command}
app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})
IntsEquals := func(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
StrsEquals := func(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
var expectedIntSlice = []int{22, 80}
var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}
if !IntsEquals(parsedIntSlice, expectedIntSlice) {
t.Errorf("%s does not match %s", parsedIntSlice, expectedIntSlice)
}
if !StrsEquals(parsedStringSlice, expectedStringSlice) {
t.Errorf("%s does not match %s", parsedStringSlice, expectedStringSlice)
}
}

View File

@ -1,19 +1,19 @@
package cli
import (
"os"
"fmt"
"io/ioutil"
"os"
"strings"
)
type Command struct {
Name string
ShortName string
Usage string
Description string
Action func (context *Context)
Flags []Flag
Name string
ShortName string
Usage string
Description string
Action func(context *Context)
Flags []Flag
}
func (c Command) Run(ctx *Context) {
@ -52,7 +52,6 @@ func (c Command) Run(ctx *Context) {
context := NewContext(ctx.App, set, ctx.globalSet)
checkCommandHelp(context, c.Name)
c.Action(context)
}

View File

@ -34,6 +34,16 @@ func (c *Context) String(name string) string {
return c.lookupString(name, c.flagSet)
}
// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
return c.lookupStringSlice(name, c.flagSet)
}
// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
return c.lookupIntSlice(name, c.flagSet)
}
// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
return c.lookupInt(name, c.globalSet)
@ -49,6 +59,16 @@ func (c *Context) GlobalString(name string) string {
return c.lookupString(name, c.globalSet)
}
// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
return c.lookupStringSlice(name, c.globalSet)
}
// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
return c.lookupIntSlice(name, c.globalSet)
}
func (c *Context) Args() []string {
return c.flagSet.Args()
}
@ -75,6 +95,26 @@ func (c *Context) lookupString(name string, set *flag.FlagSet) string {
return ""
}
func (c *Context) lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*StringSlice)).Value()
}
return nil
}
func (c *Context) lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*IntSlice)).Value()
}
return nil
}
func (c *Context) lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {

66
flag.go
View File

@ -2,6 +2,7 @@ package cli
import "fmt"
import "flag"
import "strconv"
type Flag interface {
fmt.Stringer
@ -10,12 +11,77 @@ type Flag interface {
func flagSet(name string, flags []Flag) *flag.FlagSet {
set := flag.NewFlagSet(name, flag.ContinueOnError)
for _, f := range flags {
f.Apply(set)
}
return set
}
type StringSlice []string
func (f *StringSlice) Set(value string) error {
*f = append(*f, value)
return nil
}
func (f *StringSlice) String() string {
return fmt.Sprintf("%s", *f)
}
func (f *StringSlice) Value() []string {
return *f
}
type StringSliceFlag struct {
Name string
Value *StringSlice
Usage string
}
func (f StringSliceFlag) String() string {
return fmt.Sprintf("%s%v '%v'\t%v", prefixFor(f.Name), f.Name, "-"+f.Name+" option -"+f.Name+" option", f.Usage)
}
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
set.Var(f.Value, f.Name, f.Usage)
}
type IntSlice []int
func (f *IntSlice) Set(value string) error {
tmp, err := strconv.Atoi(value)
if err != nil {
return err
} else {
*f = append(*f, tmp)
}
return nil
}
func (f *IntSlice) String() string {
return fmt.Sprintf("%d", *f)
}
func (f *IntSlice) Value() []int {
return *f
}
type IntSliceFlag struct {
Name string
Value *IntSlice
Usage string
}
func (f IntSliceFlag) String() string {
return fmt.Sprintf("%s%v '%v'\t%v", prefixFor(f.Name), f.Name, "-"+f.Name+" option -"+f.Name+" option", f.Usage)
}
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
set.Var(f.Value, f.Name, f.Usage)
}
type BoolFlag struct {
Name string
Usage string