...

Source file src/github.com/urfave/cli/v2/flag_uint_slice.go

Documentation: github.com/urfave/cli/v2

     1  package cli
     2  
     3  import (
     4  	"encoding/json"
     5  	"flag"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // UintSlice wraps []int to satisfy flag.Value
    12  type UintSlice struct {
    13  	slice      []uint
    14  	separator  separatorSpec
    15  	hasBeenSet bool
    16  }
    17  
    18  // NewUintSlice makes an *UintSlice with default values
    19  func NewUintSlice(defaults ...uint) *UintSlice {
    20  	return &UintSlice{slice: append([]uint{}, defaults...)}
    21  }
    22  
    23  // clone allocate a copy of self object
    24  func (i *UintSlice) clone() *UintSlice {
    25  	n := &UintSlice{
    26  		slice:      make([]uint, len(i.slice)),
    27  		hasBeenSet: i.hasBeenSet,
    28  	}
    29  	copy(n.slice, i.slice)
    30  	return n
    31  }
    32  
    33  // TODO: Consistently have specific Set function for Int64 and Float64 ?
    34  // SetInt directly adds an integer to the list of values
    35  func (i *UintSlice) SetUint(value uint) {
    36  	if !i.hasBeenSet {
    37  		i.slice = []uint{}
    38  		i.hasBeenSet = true
    39  	}
    40  
    41  	i.slice = append(i.slice, value)
    42  }
    43  
    44  // Set parses the value into an integer and appends it to the list of values
    45  func (i *UintSlice) Set(value string) error {
    46  	if !i.hasBeenSet {
    47  		i.slice = []uint{}
    48  		i.hasBeenSet = true
    49  	}
    50  
    51  	if strings.HasPrefix(value, slPfx) {
    52  		// Deserializing assumes overwrite
    53  		_ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice)
    54  		i.hasBeenSet = true
    55  		return nil
    56  	}
    57  
    58  	for _, s := range i.separator.flagSplitMultiValues(value) {
    59  		tmp, err := strconv.ParseUint(strings.TrimSpace(s), 0, 32)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		i.slice = append(i.slice, uint(tmp))
    65  	}
    66  
    67  	return nil
    68  }
    69  
    70  func (i *UintSlice) WithSeparatorSpec(spec separatorSpec) {
    71  	i.separator = spec
    72  }
    73  
    74  // String returns a readable representation of this value (for usage defaults)
    75  func (i *UintSlice) String() string {
    76  	v := i.slice
    77  	if v == nil {
    78  		// treat nil the same as zero length non-nil
    79  		v = make([]uint, 0)
    80  	}
    81  	str := fmt.Sprintf("%d", v)
    82  	str = strings.Replace(str, " ", ", ", -1)
    83  	str = strings.Replace(str, "[", "{", -1)
    84  	str = strings.Replace(str, "]", "}", -1)
    85  	return fmt.Sprintf("[]uint%s", str)
    86  }
    87  
    88  // Serialize allows UintSlice to fulfill Serializer
    89  func (i *UintSlice) Serialize() string {
    90  	jsonBytes, _ := json.Marshal(i.slice)
    91  	return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
    92  }
    93  
    94  // Value returns the slice of ints set by this flag
    95  func (i *UintSlice) Value() []uint {
    96  	return i.slice
    97  }
    98  
    99  // Get returns the slice of ints set by this flag
   100  func (i *UintSlice) Get() interface{} {
   101  	return *i
   102  }
   103  
   104  // String returns a readable representation of this value
   105  // (for usage defaults)
   106  func (f *UintSliceFlag) String() string {
   107  	return FlagStringer(f)
   108  }
   109  
   110  // TakesValue returns true of the flag takes a value, otherwise false
   111  func (f *UintSliceFlag) TakesValue() bool {
   112  	return true
   113  }
   114  
   115  // GetUsage returns the usage string for the flag
   116  func (f *UintSliceFlag) GetUsage() string {
   117  	return f.Usage
   118  }
   119  
   120  // GetCategory returns the category for the flag
   121  func (f *UintSliceFlag) GetCategory() string {
   122  	return f.Category
   123  }
   124  
   125  // GetValue returns the flags value as string representation and an empty
   126  // string if the flag takes no value at all.
   127  func (f *UintSliceFlag) GetValue() string {
   128  	var defaultVals []string
   129  	if f.Value != nil && len(f.Value.Value()) > 0 {
   130  		for _, i := range f.Value.Value() {
   131  			defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10))
   132  		}
   133  	}
   134  	return strings.Join(defaultVals, ", ")
   135  }
   136  
   137  // GetDefaultText returns the default text for this flag
   138  func (f *UintSliceFlag) GetDefaultText() string {
   139  	if f.DefaultText != "" {
   140  		return f.DefaultText
   141  	}
   142  	return f.GetValue()
   143  }
   144  
   145  // GetEnvVars returns the env vars for this flag
   146  func (f *UintSliceFlag) GetEnvVars() []string {
   147  	return f.EnvVars
   148  }
   149  
   150  // IsSliceFlag implements DocGenerationSliceFlag.
   151  func (f *UintSliceFlag) IsSliceFlag() bool {
   152  	return true
   153  }
   154  
   155  // Apply populates the flag given the flag set and environment
   156  func (f *UintSliceFlag) Apply(set *flag.FlagSet) error {
   157  	// apply any default
   158  	if f.Destination != nil && f.Value != nil {
   159  		f.Destination.slice = make([]uint, len(f.Value.slice))
   160  		copy(f.Destination.slice, f.Value.slice)
   161  	}
   162  
   163  	// resolve setValue (what we will assign to the set)
   164  	var setValue *UintSlice
   165  	switch {
   166  	case f.Destination != nil:
   167  		setValue = f.Destination
   168  	case f.Value != nil:
   169  		setValue = f.Value.clone()
   170  	default:
   171  		setValue = new(UintSlice)
   172  		setValue.WithSeparatorSpec(f.separator)
   173  	}
   174  
   175  	if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" {
   176  		for _, s := range f.separator.flagSplitMultiValues(val) {
   177  			if err := setValue.Set(strings.TrimSpace(s)); err != nil {
   178  				return fmt.Errorf("could not parse %q as uint slice value from %s for flag %s: %s", val, source, f.Name, err)
   179  			}
   180  		}
   181  
   182  		// Set this to false so that we reset the slice if we then set values from
   183  		// flags that have already been set by the environment.
   184  		setValue.hasBeenSet = false
   185  		f.HasBeenSet = true
   186  	}
   187  
   188  	for _, name := range f.Names() {
   189  		set.Var(setValue, name, f.Usage)
   190  	}
   191  
   192  	return nil
   193  }
   194  
   195  func (f *UintSliceFlag) WithSeparatorSpec(spec separatorSpec) {
   196  	f.separator = spec
   197  }
   198  
   199  // Get returns the flag’s value in the given Context.
   200  func (f *UintSliceFlag) Get(ctx *Context) []uint {
   201  	return ctx.UintSlice(f.Name)
   202  }
   203  
   204  // RunAction executes flag action if set
   205  func (f *UintSliceFlag) RunAction(c *Context) error {
   206  	if f.Action != nil {
   207  		return f.Action(c, c.UintSlice(f.Name))
   208  	}
   209  
   210  	return nil
   211  }
   212  
   213  // UintSlice looks up the value of a local UintSliceFlag, returns
   214  // nil if not found
   215  func (cCtx *Context) UintSlice(name string) []uint {
   216  	if fs := cCtx.lookupFlagSet(name); fs != nil {
   217  		return lookupUintSlice(name, fs)
   218  	}
   219  	return nil
   220  }
   221  
   222  func lookupUintSlice(name string, set *flag.FlagSet) []uint {
   223  	f := set.Lookup(name)
   224  	if f != nil {
   225  		if slice, ok := unwrapFlagValue(f.Value).(*UintSlice); ok {
   226  			return slice.Value()
   227  		}
   228  	}
   229  	return nil
   230  }
   231  

View as plain text