111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// SliceBase wraps []T to satisfy flag.Value
|
|
type SliceBase[T any, C any, VC ValueCreator[T, C]] struct {
|
|
slice *[]T
|
|
hasBeenSet bool
|
|
value Value
|
|
}
|
|
|
|
func (i SliceBase[T, C, VC]) Create(val []T, p *[]T, c C) Value {
|
|
*p = []T{}
|
|
*p = append(*p, val...)
|
|
var t T
|
|
np := new(T)
|
|
var vc VC
|
|
return &SliceBase[T, C, VC]{
|
|
slice: p,
|
|
value: vc.Create(t, np, c),
|
|
}
|
|
}
|
|
|
|
// NewSliceBase makes a *SliceBase with default values
|
|
func NewSliceBase[T any, C any, VC ValueCreator[T, C]](defaults ...T) *SliceBase[T, C, VC] {
|
|
return &SliceBase[T, C, VC]{
|
|
slice: &defaults,
|
|
}
|
|
}
|
|
|
|
// SetOne directly adds a value to the list of values
|
|
func (i *SliceBase[T, C, VC]) SetOne(value T) {
|
|
if !i.hasBeenSet {
|
|
*i.slice = []T{}
|
|
i.hasBeenSet = true
|
|
}
|
|
|
|
*i.slice = append(*i.slice, value)
|
|
}
|
|
|
|
// Set parses the value and appends it to the list of values
|
|
func (i *SliceBase[T, C, VC]) Set(value string) error {
|
|
if !i.hasBeenSet {
|
|
*i.slice = []T{}
|
|
i.hasBeenSet = true
|
|
}
|
|
|
|
if strings.HasPrefix(value, slPfx) {
|
|
// Deserializing assumes overwrite
|
|
_ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice)
|
|
i.hasBeenSet = true
|
|
return nil
|
|
}
|
|
|
|
for _, s := range flagSplitMultiValues(value) {
|
|
if err := i.value.Set(strings.TrimSpace(s)); err != nil {
|
|
return err
|
|
}
|
|
tmp, ok := i.value.Get().(T)
|
|
if !ok {
|
|
return fmt.Errorf("unable to cast %v", i.value)
|
|
}
|
|
*i.slice = append(*i.slice, tmp)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// String returns a readable representation of this value (for usage defaults)
|
|
func (i *SliceBase[T, C, VC]) String() string {
|
|
v := i.Value()
|
|
var t T
|
|
if reflect.TypeOf(t).Kind() == reflect.String {
|
|
return fmt.Sprintf("%v", v)
|
|
}
|
|
return fmt.Sprintf("%T{%s}", v, i.ToString(v))
|
|
}
|
|
|
|
// Serialize allows SliceBase to fulfill Serializer
|
|
func (i *SliceBase[T, C, VC]) Serialize() string {
|
|
jsonBytes, _ := json.Marshal(i.slice)
|
|
return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
|
|
}
|
|
|
|
// Value returns the slice of values set by this flag
|
|
func (i *SliceBase[T, C, VC]) Value() []T {
|
|
if i.slice == nil {
|
|
return []T{}
|
|
}
|
|
return *i.slice
|
|
}
|
|
|
|
// Get returns the slice of values set by this flag
|
|
func (i *SliceBase[T, C, VC]) Get() interface{} {
|
|
return *i.slice
|
|
}
|
|
|
|
func (i SliceBase[T, C, VC]) ToString(t []T) string {
|
|
var defaultVals []string
|
|
var v VC
|
|
for _, s := range t {
|
|
defaultVals = append(defaultVals, v.ToString(s))
|
|
}
|
|
return strings.Join(defaultVals, ", ")
|
|
}
|