Merge pull request #27 from eparis/SliceStrings

Add new StringSlice and IntSlice flag types
diff --git a/int_slice.go b/int_slice.go
new file mode 100644
index 0000000..fb3e67b
--- /dev/null
+++ b/int_slice.go
@@ -0,0 +1,113 @@
+package pflag
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// -- intSlice Value
+type intSliceValue []int
+
+func newIntSliceValue(val []int, p *[]int) *intSliceValue {
+	*p = val
+	return (*intSliceValue)(p)
+}
+
+func (s *intSliceValue) Set(val string) error {
+	ss := strings.Split(val, ",")
+	out := make([]int, len(ss))
+	for i, d := range ss {
+		var err error
+		out[i], err = strconv.Atoi(d)
+		if err != nil {
+			return err
+		}
+
+	}
+	*s = intSliceValue(out)
+	return nil
+}
+
+func (s *intSliceValue) Type() string {
+	return "intSlice"
+}
+
+func (s *intSliceValue) String() string {
+	out := make([]string, len(*s))
+	for i, d := range *s {
+		out[i] = fmt.Sprintf("%d", d)
+	}
+	return strings.Join(out, ",")
+}
+
+func intSliceConv(val string) (interface{}, error) {
+	ss := strings.Split(val, ",")
+	out := make([]int, len(ss))
+	for i, d := range ss {
+		var err error
+		out[i], err = strconv.Atoi(d)
+		if err != nil {
+			return nil, err
+		}
+
+	}
+	return out, nil
+}
+
+// GetIntSlice return the []int value of a flag with the given name
+func (f *FlagSet) GetIntSlice(name string) ([]int, error) {
+	val, err := f.getFlagType(name, "intSlice", intSliceConv)
+	if err != nil {
+		return []int{}, err
+	}
+	return val.([]int), nil
+}
+
+// IntSliceVar defines a intSlice flag with specified name, default value, and usage string.
+// The argument p points to a []int variable in which to store the value of the flag.
+func (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) {
+	f.VarP(newIntSliceValue(value, p), name, "", usage)
+}
+
+// Like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
+	f.VarP(newIntSliceValue(value, p), name, shorthand, usage)
+}
+
+// IntSliceVar defines a int[] flag with specified name, default value, and usage string.
+// The argument p points to a int[] variable in which to store the value of the flag.
+func IntSliceVar(p *[]int, name string, value []int, usage string) {
+	CommandLine.VarP(newIntSliceValue(value, p), name, "", usage)
+}
+
+// Like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
+	CommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage)
+}
+
+// IntSlice defines a []int flag with specified name, default value, and usage string.
+// The return value is the address of a []int variable that stores the value of the flag.
+func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int {
+	p := make([]int, 0)
+	f.IntSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// Like IntSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int {
+	p := make([]int, 0)
+	f.IntSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// IntSlice defines a []int flag with specified name, default value, and usage string.
+// The return value is the address of a []int variable that stores the value of the flag.
+func IntSlice(name string, value []int, usage string) *[]int {
+	return CommandLine.IntSliceP(name, "", value, usage)
+}
+
+// Like IntSlice, but accepts a shorthand letter that can be used after a single dash.
+func IntSliceP(name, shorthand string, value []int, usage string) *[]int {
+	return CommandLine.IntSliceP(name, shorthand, value, usage)
+}
diff --git a/int_slice_test.go b/int_slice_test.go
new file mode 100644
index 0000000..d162e86
--- /dev/null
+++ b/int_slice_test.go
@@ -0,0 +1,49 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func setUpISFlagSet(isp *[]int) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.IntSliceVar(isp, "is", []int{}, "Command seperated list!")
+	return f
+}
+
+func TestIS(t *testing.T) {
+	var is []int
+	f := setUpISFlagSet(&is)
+
+	vals := []string{"1", "2", "4", "3"}
+	arg := fmt.Sprintf("--is=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range is {
+		d, err := strconv.Atoi(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v)
+		}
+	}
+	getIS, err := f.GetIntSlice("is")
+	for i, v := range getIS {
+		d, err := strconv.Atoi(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected is[%d] to be %s but got: %d from GetIntSlice", i, vals[i], v)
+		}
+	}
+}
diff --git a/string_slice.go b/string_slice.go
new file mode 100644
index 0000000..bbe6e00
--- /dev/null
+++ b/string_slice.go
@@ -0,0 +1,86 @@
+package pflag
+
+import (
+	"strings"
+)
+
+// -- stringSlice Value
+type stringSliceValue []string
+
+func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
+	*p = val
+	return (*stringSliceValue)(p)
+}
+
+func (s *stringSliceValue) Set(val string) error {
+	v := strings.Split(val, ",")
+	*s = stringSliceValue(v)
+	return nil
+}
+func (s *stringSliceValue) Type() string {
+	return "stringSlice"
+}
+
+func (s *stringSliceValue) String() string { return strings.Join(*s, ",") }
+
+func stringSliceConv(sval string) (interface{}, error) {
+	v := strings.Split(sval, ",")
+	return v, nil
+}
+
+// GetStringSlice return the []string value of a flag with the given name
+func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
+	val, err := f.getFlagType(name, "stringSlice", stringSliceConv)
+	if err != nil {
+		return []string{}, err
+	}
+	return val.([]string), nil
+}
+
+// StringSliceVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a []string variable in which to store the value of the flag.
+func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
+	f.VarP(newStringSliceValue(value, p), name, "", usage)
+}
+
+// Like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
+	f.VarP(newStringSliceValue(value, p), name, shorthand, usage)
+}
+
+// StringSliceVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a []string variable in which to store the value of the flag.
+func StringSliceVar(p *[]string, name string, value []string, usage string) {
+	CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
+}
+
+// Like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
+	CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage)
+}
+
+// StringSlice defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a []string variable that stores the value of the flag.
+func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
+	p := make([]string, 0)
+	f.StringSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// Like StringSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string {
+	p := make([]string, 0)
+	f.StringSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// StringSlice defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a []string variable that stores the value of the flag.
+func StringSlice(name string, value []string, usage string) *[]string {
+	return CommandLine.StringSliceP(name, "", value, usage)
+}
+
+// Like StringSlice, but accepts a shorthand letter that can be used after a single dash.
+func StringSliceP(name, shorthand string, value []string, usage string) *[]string {
+	return CommandLine.StringSliceP(name, shorthand, value, usage)
+}
diff --git a/string_slice_test.go b/string_slice_test.go
new file mode 100644
index 0000000..c37a91a
--- /dev/null
+++ b/string_slice_test.go
@@ -0,0 +1,44 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func setUpSSFlagSet(ssp *[]string) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringSliceVar(ssp, "ss", []string{}, "Command seperated list!")
+	return f
+}
+
+func TestSS(t *testing.T) {
+	var ss []string
+	f := setUpSSFlagSet(&ss)
+
+	vals := []string{"one", "two", "4", "3"}
+	arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ss {
+		if vals[i] != v {
+			t.Fatal("expected ss[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+
+	getSS, err := f.GetStringSlice("ss")
+	if err != nil {
+		t.Fatal("got an error from GetStringSlice(): %v", err)
+	}
+	for i, v := range getSS {
+		if vals[i] != v {
+			t.Fatal("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
+		}
+	}
+}