github.com/puellanivis/breton@v0.2.16/lib/gnuflag/enum.go (about)

     1  package gnuflag
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // EnumValue defines an string-like flag type that maps strings to uint values.
    10  // It is exported, so that it may be defined in a gnuflags.Struct parameter.
    11  type EnumValue int
    12  
    13  // enumValue describes a String flag that will only accept certain specific values.
    14  type enumValue struct {
    15  	val     *int
    16  	indices map[string]int
    17  	valid   []string
    18  }
    19  
    20  // newEnumValue returns an EnumValue that will only accept the given strings.
    21  func newEnumValue(valid ...string) *enumValue {
    22  	e := &enumValue{
    23  		val: new(int),
    24  	}
    25  
    26  	e.setValid(valid)
    27  
    28  	return e
    29  }
    30  
    31  func (e *enumValue) setValid(valid []string) {
    32  	e.valid = valid
    33  
    34  	e.indices = make(map[string]int)
    35  	for i, v := range valid {
    36  		if v == "" {
    37  			continue
    38  		}
    39  
    40  		v = strings.ToUpper(v)
    41  
    42  		e.indices[v] = i
    43  	}
    44  }
    45  
    46  // ValueType permits an ability for the more standard flags library to support
    47  // a flag displaying values/type allowed beyond the concrete types.
    48  func (e *enumValue) ValueType() string {
    49  	var filtered []string
    50  
    51  	for _, v := range e.valid {
    52  		if v == "" {
    53  			continue
    54  		}
    55  
    56  		filtered = append(filtered, v)
    57  	}
    58  
    59  	return strings.Join(filtered, ", ")
    60  }
    61  
    62  // String returns the canonical valid string of the value of the EnumValue.
    63  func (e *enumValue) String() string {
    64  	var val int
    65  	if e.val != nil {
    66  		val = *e.val
    67  	}
    68  
    69  	if val < 0 || val >= len(e.valid) {
    70  		return strconv.Itoa(val)
    71  	}
    72  
    73  	return e.valid[val]
    74  }
    75  
    76  // ErrBadEnum is the error returned when attempting to set an enum flag with a value not in the Enum
    77  var ErrBadEnum = errors.New("bad enum value")
    78  
    79  // Set attempts to set the given EnumValue to the given string.
    80  func (e *enumValue) Set(s string) error {
    81  	if e.val == nil {
    82  		return errors.New("uninitialized enum usage")
    83  	}
    84  
    85  	if s == "" {
    86  		*e.val = 0
    87  		return nil
    88  	}
    89  
    90  	v, ok := e.indices[strings.ToUpper(s)]
    91  	if !ok {
    92  		return ErrBadEnum
    93  	}
    94  
    95  	*e.val = v
    96  	return nil
    97  }
    98  
    99  // Get returns the value of the enum flag. Expect it to be of type int.
   100  func (e *enumValue) Get() interface{} {
   101  	if e.val == nil {
   102  		return 0
   103  	}
   104  
   105  	return *e.val
   106  }
   107  
   108  // Enum defines an enum flag with specified name, usage, and list of valid values.
   109  // The return value is the address of an EnumValue variable that stores the value of the flag.
   110  func (f *FlagSet) Enum(name string, usage string, valid []string, options ...Option) *EnumValue {
   111  	e := newEnumValue(valid...)
   112  	if err := f.Var(e, name, usage, options...); err != nil {
   113  		panic(err)
   114  	}
   115  	return (*EnumValue)(e.val)
   116  }
   117  
   118  // Enum defines an enum flag with specified name, usage, and list of valid values.
   119  // The return value is the address of an EnumValue variable that stores the value of the flag.
   120  func Enum(name string, usage string, valid []string, options ...Option) *EnumValue {
   121  	return CommandLine.Enum(name, usage, valid, options...)
   122  }