Add BoolSlice and UintSlice flag types. (#111)

* Add Gogland/IntelliJ/Jetbrains config directory to .gitignore.

* Added uint slice flag type.
Added godoc for uint slice type.
Added unit tests for new uint slice type.

* Added new boolSliceValue type to handle []bool arguments.
Added unit tests for new boolSliceValue type.
Added godoc documentation.

* Added new ipSliceValue type to handle []net.IP arguments.
Added unit tests for new ipSliceValue type.
Added godoc documentation.

* Fix golint warnings.

* boolSliceValue:
    - Use CSV parser for boolean flag arguments, and handle corner cases
      with extraneous quote characters.
    - Add unit tests for to parse flags with extraneous quote
      characters.
    - Add godoc documentation to undocumented methods.

* boolSliceValue:
    - Refactored boolSlice name to boolStrSlice for clarity.
    - Fix allocation of out variable to len=0 (not len=cap)
    - Remove extraneous err declaration in range loop.
    - Actually append bool to []bool.
    - Simplify unit test function name.
ipSliceValue:
    - Use csv parser for net.IP flag arguments, and handle corner cases
    with extraneous quote characters.
    - Add unit tests to parse flags with extraneous quote characters.
    - Add godoc documentation to undocumented methods.

* boolSliceValue:
ipSliceValue:
    - Use csv utility functions instead of duplicating code for reading
    and writing CSV flag string values.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c3da290
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea/*
+
diff --git a/bool_slice.go b/bool_slice.go
new file mode 100644
index 0000000..5af02f1
--- /dev/null
+++ b/bool_slice.go
@@ -0,0 +1,147 @@
+package pflag
+
+import (
+	"io"
+	"strconv"
+	"strings"
+)
+
+// -- boolSlice Value
+type boolSliceValue struct {
+	value   *[]bool
+	changed bool
+}
+
+func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
+	bsv := new(boolSliceValue)
+	bsv.value = p
+	*bsv.value = val
+	return bsv
+}
+
+// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
+// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
+func (s *boolSliceValue) Set(val string) error {
+
+	// remove all quote characters
+	rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
+
+	// read flag arguments with CSV parser
+	boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
+	if err != nil && err != io.EOF {
+		return err
+	}
+
+	// parse boolean values into slice
+	out := make([]bool, 0, len(boolStrSlice))
+	for _, boolStr := range boolStrSlice {
+		b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
+		if err != nil {
+			return err
+		}
+		out = append(out, b)
+	}
+
+	if !s.changed {
+		*s.value = out
+	} else {
+		*s.value = append(*s.value, out...)
+	}
+
+	s.changed = true
+
+	return nil
+}
+
+// Type returns a string that uniquely represents this flag's type.
+func (s *boolSliceValue) Type() string {
+	return "boolSlice"
+}
+
+// String defines a "native" format for this boolean slice flag value.
+func (s *boolSliceValue) String() string {
+
+	boolStrSlice := make([]string, len(*s.value))
+	for i, b := range *s.value {
+		boolStrSlice[i] = strconv.FormatBool(b)
+	}
+
+	out, _ := writeAsCSV(boolStrSlice)
+
+	return "[" + out + "]"
+}
+
+func boolSliceConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// Empty string would cause a slice with one (empty) entry
+	if len(val) == 0 {
+		return []bool{}, nil
+	}
+	ss := strings.Split(val, ",")
+	out := make([]bool, len(ss))
+	for i, t := range ss {
+		var err error
+		out[i], err = strconv.ParseBool(t)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return out, nil
+}
+
+// GetBoolSlice returns the []bool value of a flag with the given name.
+func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
+	val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
+	if err != nil {
+		return []bool{}, err
+	}
+	return val.([]bool), nil
+}
+
+// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
+// The argument p points to a []bool variable in which to store the value of the flag.
+func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
+	f.VarP(newBoolSliceValue(value, p), name, "", usage)
+}
+
+// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
+	f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
+}
+
+// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
+// The argument p points to a []bool variable in which to store the value of the flag.
+func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
+	CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
+}
+
+// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
+	CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
+}
+
+// BoolSlice defines a []bool flag with specified name, default value, and usage string.
+// The return value is the address of a []bool variable that stores the value of the flag.
+func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
+	p := []bool{}
+	f.BoolSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
+	p := []bool{}
+	f.BoolSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// BoolSlice defines a []bool flag with specified name, default value, and usage string.
+// The return value is the address of a []bool variable that stores the value of the flag.
+func BoolSlice(name string, value []bool, usage string) *[]bool {
+	return CommandLine.BoolSliceP(name, "", value, usage)
+}
+
+// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
+func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
+	return CommandLine.BoolSliceP(name, shorthand, value, usage)
+}
diff --git a/bool_slice_test.go b/bool_slice_test.go
new file mode 100644
index 0000000..b617dd2
--- /dev/null
+++ b/bool_slice_test.go
@@ -0,0 +1,215 @@
+package pflag
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func setUpBSFlagSet(bsp *[]bool) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!")
+	return f
+}
+
+func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!")
+	return f
+}
+
+func TestEmptyBS(t *testing.T) {
+	var bs []bool
+	f := setUpBSFlagSet(&bs)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getBS, err := f.GetBoolSlice("bs")
+	if err != nil {
+		t.Fatal("got an error from GetBoolSlice():", err)
+	}
+	if len(getBS) != 0 {
+		t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS))
+	}
+}
+
+func TestBS(t *testing.T) {
+	var bs []bool
+	f := setUpBSFlagSet(&bs)
+
+	vals := []string{"1", "F", "TRUE", "0"}
+	arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range bs {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if b != v {
+			t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v)
+		}
+	}
+	getBS, err := f.GetBoolSlice("bs")
+	if err != nil {
+		t.Fatalf("got error: %v", err)
+	}
+	for i, v := range getBS {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if b != v {
+			t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v)
+		}
+	}
+}
+
+func TestBSDefault(t *testing.T) {
+	var bs []bool
+	f := setUpBSFlagSetWithDefault(&bs)
+
+	vals := []string{"false", "T"}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range bs {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if b != v {
+			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
+		}
+	}
+
+	getBS, err := f.GetBoolSlice("bs")
+	if err != nil {
+		t.Fatal("got an error from GetBoolSlice():", err)
+	}
+	for i, v := range getBS {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatal("got an error from GetBoolSlice():", err)
+		}
+		if b != v {
+			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
+		}
+	}
+}
+
+func TestBSWithDefault(t *testing.T) {
+	var bs []bool
+	f := setUpBSFlagSetWithDefault(&bs)
+
+	vals := []string{"FALSE", "1"}
+	arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range bs {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if b != v {
+			t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v)
+		}
+	}
+
+	getBS, err := f.GetBoolSlice("bs")
+	if err != nil {
+		t.Fatal("got an error from GetBoolSlice():", err)
+	}
+	for i, v := range getBS {
+		b, err := strconv.ParseBool(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if b != v {
+			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
+		}
+	}
+}
+
+func TestBSCalledTwice(t *testing.T) {
+	var bs []bool
+	f := setUpBSFlagSet(&bs)
+
+	in := []string{"T,F", "T"}
+	expected := []bool{true, false, true}
+	argfmt := "--bs=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range bs {
+		if expected[i] != v {
+			t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v)
+		}
+	}
+}
+
+func TestBSBadQuoting(t *testing.T) {
+
+	tests := []struct {
+		Want    []bool
+		FlagArg []string
+	}{
+		{
+			Want:    []bool{true, false, true},
+			FlagArg: []string{"1", "0", "true"},
+		},
+		{
+			Want:    []bool{true, false},
+			FlagArg: []string{"True", "F"},
+		},
+		{
+			Want:    []bool{true, false},
+			FlagArg: []string{"T", "0"},
+		},
+		{
+			Want:    []bool{true, false},
+			FlagArg: []string{"1", "0"},
+		},
+		{
+			Want:    []bool{true, false, false},
+			FlagArg: []string{"true,false", "false"},
+		},
+		{
+			Want:    []bool{true, false, false, true, false, true, false},
+			FlagArg: []string{`"true,false,false,1,0,     T"`, " false "},
+		},
+		{
+			Want:    []bool{false, false, true, false, true, false, true},
+			FlagArg: []string{`"0, False,  T,false  , true,F"`, "true"},
+		},
+	}
+
+	for i, test := range tests {
+
+		var bs []bool
+		f := setUpBSFlagSet(&bs)
+
+		if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
+			t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v",
+				err, test.FlagArg, test.Want[i])
+		}
+
+		for j, b := range bs {
+			if b != test.Want[j] {
+				t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b)
+			}
+		}
+	}
+}
diff --git a/ip_slice.go b/ip_slice.go
new file mode 100644
index 0000000..7dd196f
--- /dev/null
+++ b/ip_slice.go
@@ -0,0 +1,148 @@
+package pflag
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"strings"
+)
+
+// -- ipSlice Value
+type ipSliceValue struct {
+	value   *[]net.IP
+	changed bool
+}
+
+func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
+	ipsv := new(ipSliceValue)
+	ipsv.value = p
+	*ipsv.value = val
+	return ipsv
+}
+
+// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
+// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
+func (s *ipSliceValue) Set(val string) error {
+
+	// remove all quote characters
+	rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
+
+	// read flag arguments with CSV parser
+	ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
+	if err != nil && err != io.EOF {
+		return err
+	}
+
+	// parse ip values into slice
+	out := make([]net.IP, 0, len(ipStrSlice))
+	for _, ipStr := range ipStrSlice {
+		ip := net.ParseIP(strings.TrimSpace(ipStr))
+		if ip == nil {
+			return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
+		}
+		out = append(out, ip)
+	}
+
+	if !s.changed {
+		*s.value = out
+	} else {
+		*s.value = append(*s.value, out...)
+	}
+
+	s.changed = true
+
+	return nil
+}
+
+// Type returns a string that uniquely represents this flag's type.
+func (s *ipSliceValue) Type() string {
+	return "ipSlice"
+}
+
+// String defines a "native" format for this net.IP slice flag value.
+func (s *ipSliceValue) String() string {
+
+	ipStrSlice := make([]string, len(*s.value))
+	for i, ip := range *s.value {
+		ipStrSlice[i] = ip.String()
+	}
+
+	out, _ := writeAsCSV(ipStrSlice)
+
+	return "[" + out + "]"
+}
+
+func ipSliceConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// Emtpy string would cause a slice with one (empty) entry
+	if len(val) == 0 {
+		return []net.IP{}, nil
+	}
+	ss := strings.Split(val, ",")
+	out := make([]net.IP, len(ss))
+	for i, sval := range ss {
+		ip := net.ParseIP(strings.TrimSpace(sval))
+		if ip == nil {
+			return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
+		}
+		out[i] = ip
+	}
+	return out, nil
+}
+
+// GetIPSlice returns the []net.IP value of a flag with the given name
+func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
+	val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
+	if err != nil {
+		return []net.IP{}, err
+	}
+	return val.([]net.IP), nil
+}
+
+// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
+// The argument p points to a []net.IP variable in which to store the value of the flag.
+func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
+	f.VarP(newIPSliceValue(value, p), name, "", usage)
+}
+
+// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
+	f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
+}
+
+// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
+// The argument p points to a []net.IP variable in which to store the value of the flag.
+func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
+	CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
+}
+
+// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
+	CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
+}
+
+// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
+// The return value is the address of a []net.IP variable that stores the value of that flag.
+func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
+	p := []net.IP{}
+	f.IPSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
+	p := []net.IP{}
+	f.IPSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
+// The return value is the address of a []net.IP variable that stores the value of the flag.
+func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
+	return CommandLine.IPSliceP(name, "", value, usage)
+}
+
+// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
+func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
+	return CommandLine.IPSliceP(name, shorthand, value, usage)
+}
diff --git a/ip_slice_test.go b/ip_slice_test.go
new file mode 100644
index 0000000..b0c681c
--- /dev/null
+++ b/ip_slice_test.go
@@ -0,0 +1,222 @@
+package pflag
+
+import (
+	"fmt"
+	"net"
+	"strings"
+	"testing"
+)
+
+func setUpIPSFlagSet(ipsp *[]net.IP) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.IPSliceVar(ipsp, "ips", []net.IP{}, "Command separated list!")
+	return f
+}
+
+func setUpIPSFlagSetWithDefault(ipsp *[]net.IP) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.IPSliceVar(ipsp, "ips",
+		[]net.IP{
+			net.ParseIP("192.168.1.1"),
+			net.ParseIP("0:0:0:0:0:0:0:1"),
+		},
+		"Command separated list!")
+	return f
+}
+
+func TestEmptyIP(t *testing.T) {
+	var ips []net.IP
+	f := setUpIPSFlagSet(&ips)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getIPS, err := f.GetIPSlice("ips")
+	if err != nil {
+		t.Fatal("got an error from GetIPSlice():", err)
+	}
+	if len(getIPS) != 0 {
+		t.Fatalf("got ips %v with len=%d but expected length=0", getIPS, len(getIPS))
+	}
+}
+
+func TestIPS(t *testing.T) {
+	var ips []net.IP
+	f := setUpIPSFlagSet(&ips)
+
+	vals := []string{"192.168.1.1", "10.0.0.1", "0:0:0:0:0:0:0:2"}
+	arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ips {
+		if ip := net.ParseIP(vals[i]); ip == nil {
+			t.Fatalf("invalid string being converted to IP address: %s", vals[i])
+		} else if !ip.Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s from GetIPSlice", i, vals[i], v)
+		}
+	}
+}
+
+func TestIPSDefault(t *testing.T) {
+	var ips []net.IP
+	f := setUpIPSFlagSetWithDefault(&ips)
+
+	vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ips {
+		if ip := net.ParseIP(vals[i]); ip == nil {
+			t.Fatalf("invalid string being converted to IP address: %s", vals[i])
+		} else if !ip.Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+
+	getIPS, err := f.GetIPSlice("ips")
+	if err != nil {
+		t.Fatal("got an error from GetIPSlice")
+	}
+	for i, v := range getIPS {
+		if ip := net.ParseIP(vals[i]); ip == nil {
+			t.Fatalf("invalid string being converted to IP address: %s", vals[i])
+		} else if !ip.Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+}
+
+func TestIPSWithDefault(t *testing.T) {
+	var ips []net.IP
+	f := setUpIPSFlagSetWithDefault(&ips)
+
+	vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
+	arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ips {
+		if ip := net.ParseIP(vals[i]); ip == nil {
+			t.Fatalf("invalid string being converted to IP address: %s", vals[i])
+		} else if !ip.Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+
+	getIPS, err := f.GetIPSlice("ips")
+	if err != nil {
+		t.Fatal("got an error from GetIPSlice")
+	}
+	for i, v := range getIPS {
+		if ip := net.ParseIP(vals[i]); ip == nil {
+			t.Fatalf("invalid string being converted to IP address: %s", vals[i])
+		} else if !ip.Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+}
+
+func TestIPSCalledTwice(t *testing.T) {
+	var ips []net.IP
+	f := setUpIPSFlagSet(&ips)
+
+	in := []string{"192.168.1.2,0:0:0:0:0:0:0:1", "10.0.0.1"}
+	expected := []net.IP{net.ParseIP("192.168.1.2"), net.ParseIP("0:0:0:0:0:0:0:1"), net.ParseIP("10.0.0.1")}
+	argfmt := "ips=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ips {
+		if !expected[i].Equal(v) {
+			t.Fatalf("expected ips[%d] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+}
+
+func TestIPSBadQuoting(t *testing.T) {
+
+	tests := []struct {
+		Want    []net.IP
+		FlagArg []string
+	}{
+		{
+			Want: []net.IP{
+				net.ParseIP("a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568"),
+				net.ParseIP("203.107.49.208"),
+				net.ParseIP("14.57.204.90"),
+			},
+			FlagArg: []string{
+				"a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568",
+				"203.107.49.208",
+				"14.57.204.90",
+			},
+		},
+		{
+			Want: []net.IP{
+				net.ParseIP("204.228.73.195"),
+				net.ParseIP("86.141.15.94"),
+			},
+			FlagArg: []string{
+				"204.228.73.195",
+				"86.141.15.94",
+			},
+		},
+		{
+			Want: []net.IP{
+				net.ParseIP("c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f"),
+				net.ParseIP("4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472"),
+			},
+			FlagArg: []string{
+				"c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f",
+				"4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472",
+			},
+		},
+		{
+			Want: []net.IP{
+				net.ParseIP("5170:f971:cfac:7be3:512a:af37:952c:bc33"),
+				net.ParseIP("93.21.145.140"),
+				net.ParseIP("2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca"),
+			},
+			FlagArg: []string{
+				" 5170:f971:cfac:7be3:512a:af37:952c:bc33  , 93.21.145.140     ",
+				"2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca",
+			},
+		},
+		{
+			Want: []net.IP{
+				net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
+				net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
+				net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
+				net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
+			},
+			FlagArg: []string{
+				`"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,        2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b     "`,
+				" 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"},
+		},
+	}
+
+	for i, test := range tests {
+
+		var ips []net.IP
+		f := setUpIPSFlagSet(&ips)
+
+		if err := f.Parse([]string{fmt.Sprintf("--ips=%s", strings.Join(test.FlagArg, ","))}); err != nil {
+			t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s",
+				err, test.FlagArg, test.Want[i])
+		}
+
+		for j, b := range ips {
+			if !b.Equal(test.Want[j]) {
+				t.Fatalf("bad value parsed for test %d on net.IP %d:\nwant:\t%s\ngot:\t%s", i, j, test.Want[j], b)
+			}
+		}
+	}
+}
diff --git a/uint_slice.go b/uint_slice.go
new file mode 100644
index 0000000..edd94c6
--- /dev/null
+++ b/uint_slice.go
@@ -0,0 +1,126 @@
+package pflag
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// -- uintSlice Value
+type uintSliceValue struct {
+	value   *[]uint
+	changed bool
+}
+
+func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
+	uisv := new(uintSliceValue)
+	uisv.value = p
+	*uisv.value = val
+	return uisv
+}
+
+func (s *uintSliceValue) Set(val string) error {
+	ss := strings.Split(val, ",")
+	out := make([]uint, len(ss))
+	for i, d := range ss {
+		u, err := strconv.ParseUint(d, 10, 0)
+		if err != nil {
+			return err
+		}
+		out[i] = uint(u)
+	}
+	if !s.changed {
+		*s.value = out
+	} else {
+		*s.value = append(*s.value, out...)
+	}
+	s.changed = true
+	return nil
+}
+
+func (s *uintSliceValue) Type() string {
+	return "uintSlice"
+}
+
+func (s *uintSliceValue) String() string {
+	out := make([]string, len(*s.value))
+	for i, d := range *s.value {
+		out[i] = fmt.Sprintf("%d", d)
+	}
+	return "[" + strings.Join(out, ",") + "]"
+}
+
+func uintSliceConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// Empty string would cause a slice with one (empty) entry
+	if len(val) == 0 {
+		return []uint{}, nil
+	}
+	ss := strings.Split(val, ",")
+	out := make([]uint, len(ss))
+	for i, d := range ss {
+		u, err := strconv.ParseUint(d, 10, 0)
+		if err != nil {
+			return nil, err
+		}
+		out[i] = uint(u)
+	}
+	return out, nil
+}
+
+// GetUintSlice returns the []uint value of a flag with the given name.
+func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
+	val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
+	if err != nil {
+		return []uint{}, err
+	}
+	return val.([]uint), nil
+}
+
+// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
+// The argument p points to a []uint variable in which to store the value of the flag.
+func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
+	f.VarP(newUintSliceValue(value, p), name, "", usage)
+}
+
+// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
+	f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
+}
+
+// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
+// The argument p points to a uint[] variable in which to store the value of the flag.
+func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
+	CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
+}
+
+// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
+	CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
+}
+
+// UintSlice defines a []uint flag with specified name, default value, and usage string.
+// The return value is the address of a []uint variable that stores the value of the flag.
+func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
+	p := []uint{}
+	f.UintSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
+	p := []uint{}
+	f.UintSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// UintSlice defines a []uint flag with specified name, default value, and usage string.
+// The return value is the address of a []uint variable that stores the value of the flag.
+func UintSlice(name string, value []uint, usage string) *[]uint {
+	return CommandLine.UintSliceP(name, "", value, usage)
+}
+
+// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
+func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
+	return CommandLine.UintSliceP(name, shorthand, value, usage)
+}
diff --git a/uint_slice_test.go b/uint_slice_test.go
new file mode 100644
index 0000000..db1a19d
--- /dev/null
+++ b/uint_slice_test.go
@@ -0,0 +1,161 @@
+package pflag
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func setUpUISFlagSet(uisp *[]uint) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.UintSliceVar(uisp, "uis", []uint{}, "Command separated list!")
+	return f
+}
+
+func setUpUISFlagSetWithDefault(uisp *[]uint) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.UintSliceVar(uisp, "uis", []uint{0, 1}, "Command separated list!")
+	return f
+}
+
+func TestEmptyUIS(t *testing.T) {
+	var uis []uint
+	f := setUpUISFlagSet(&uis)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getUIS, err := f.GetUintSlice("uis")
+	if err != nil {
+		t.Fatal("got an error from GetUintSlice():", err)
+	}
+	if len(getUIS) != 0 {
+		t.Fatalf("got is %v with len=%d but expected length=0", getUIS, len(getUIS))
+	}
+}
+
+func TestUIS(t *testing.T) {
+	var uis []uint
+	f := setUpUISFlagSet(&uis)
+
+	vals := []string{"1", "2", "4", "3"}
+	arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range uis {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expected uis[%d] to be %s but got %d", i, vals[i], v)
+		}
+	}
+	getUIS, err := f.GetUintSlice("uis")
+	if err != nil {
+		t.Fatalf("got error: %v", err)
+	}
+	for i, v := range getUIS {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expected uis[%d] to be %s but got: %d from GetUintSlice", i, vals[i], v)
+		}
+	}
+}
+
+func TestUISDefault(t *testing.T) {
+	var uis []uint
+	f := setUpUISFlagSetWithDefault(&uis)
+
+	vals := []string{"0", "1"}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range uis {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expect uis[%d] to be %d but got: %d", i, u, v)
+		}
+	}
+
+	getUIS, err := f.GetUintSlice("uis")
+	if err != nil {
+		t.Fatal("got an error from GetUintSlice():", err)
+	}
+	for i, v := range getUIS {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatal("got an error from GetIntSlice():", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
+		}
+	}
+}
+
+func TestUISWithDefault(t *testing.T) {
+	var uis []uint
+	f := setUpUISFlagSetWithDefault(&uis)
+
+	vals := []string{"1", "2"}
+	arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range uis {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
+		}
+	}
+
+	getUIS, err := f.GetUintSlice("uis")
+	if err != nil {
+		t.Fatal("got an error from GetUintSlice():", err)
+	}
+	for i, v := range getUIS {
+		u, err := strconv.ParseUint(vals[i], 10, 0)
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if uint(u) != v {
+			t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
+		}
+	}
+}
+
+func TestUISCalledTwice(t *testing.T) {
+	var uis []uint
+	f := setUpUISFlagSet(&uis)
+
+	in := []string{"1,2", "3"}
+	expected := []int{1, 2, 3}
+	argfmt := "--uis=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range uis {
+		if uint(expected[i]) != v {
+			t.Fatalf("expected uis[%d] to be %d but got: %d", i, expected[i], v)
+		}
+	}
+}