Ensure slice types can safely round-trip through flag.FlagSet

This commit is contained in:
Dan Buch 2016-04-29 02:30:49 -04:00
parent ee736e063a
commit d1b0c49a98
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC
2 changed files with 32 additions and 1 deletions

View File

@ -362,7 +362,8 @@ func lookupBoolT(name string, set *flag.FlagSet) bool {
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) {
case *StringSlice:
case Serializeder:
set.Set(name, ff.Value.(Serializeder).Serialized())
default:
set.Set(name, ff.Value.String())
}

30
flag.go
View File

@ -1,6 +1,7 @@
package cli
import (
"encoding/json"
"flag"
"fmt"
"os"
@ -10,6 +11,10 @@ import (
"time"
)
var (
slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano())
)
// This flag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{
Name: "generate-bash-completion",
@ -29,6 +34,11 @@ var HelpFlag = BoolFlag{
Usage: "show help",
}
// Serializeder is used to circumvent the limitations of flag.FlagSet.Set
type Serializeder interface {
Serialized() string
}
// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that
// this interface be implemented.
@ -130,6 +140,13 @@ func (f *StringSlice) Set(value string) error {
f.hasBeenSet = true
}
if strings.HasPrefix(value, slPfx) {
v := []string{}
_ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), v)
f.slice = append(f.slice, v...)
return nil
}
f.slice = append(f.slice, value)
return nil
}
@ -139,6 +156,12 @@ func (f *StringSlice) String() string {
return fmt.Sprintf("%s", f.slice)
}
// Serialized allows StringSlice to fulfill Serializeder
func (f *StringSlice) Serialized() string {
jsonBytes, _ := json.Marshal(f.slice)
return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
}
// Value returns the slice of strings set by this flag
func (f *StringSlice) Value() []string {
return f.slice
@ -219,6 +242,13 @@ func (i *IntSlice) Set(value string) error {
i.hasBeenSet = true
}
if strings.HasPrefix(slPfx, value) {
v := []int{}
_ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), v)
i.slice = append(i.slice, v...)
return nil
}
tmp, err := strconv.Atoi(value)
if err != nil {
return err