...

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

View as plain text