commands: Changed Option to an interface

This commit is contained in:
Matt Bell 2014-11-19 00:24:55 -08:00
parent 277ba26120
commit bbf3a1f4d4
4 changed files with 37 additions and 30 deletions

View File

@ -239,7 +239,7 @@ func optionText(cmd ...*cmds.Command) []string {
lines = append(lines, "")
}
names := sortByLength(opt.Names)
names := sortByLength(opt.Names())
if len(names) >= j+1 {
lines[i] += fmt.Sprintf(optionFlag, names[j])
}
@ -268,7 +268,7 @@ func optionText(cmd ...*cmds.Command) []string {
// add option descriptions to output
for i, opt := range options {
lines[i] += " - " + opt.Description
lines[i] += " - " + opt.Description()
}
return lines

View File

@ -167,7 +167,7 @@ func (c *Command) Get(path []string) (*Command, error) {
// GetOptions gets the options in the given path of commands
func (c *Command) GetOptions(path []string) (map[string]Option, error) {
options := make([]Option, len(c.Options))
options := make([]Option, 0, len(c.Options))
cmds, err := c.Resolve(path)
if err != nil {
@ -181,7 +181,7 @@ func (c *Command) GetOptions(path []string) (map[string]Option, error) {
optionsMap := make(map[string]Option)
for _, opt := range options {
for _, name := range opt.Names {
for _, name := range opt.Names() {
if _, found := optionsMap[name]; found {
return nil, fmt.Errorf("Option name '%s' used multiple times", name)
}

View File

@ -17,14 +17,28 @@ const (
)
// Option is used to specify a field that will be provided by a consumer
type Option struct {
Names []string // a list of unique names to
Type reflect.Kind // value must be this type
Description string // a short string to describe this option
type Option interface {
Names() []string // a list of unique names matched with user-provided flags
Type() reflect.Kind // value must be this type
Description() string // a short string that describes this option
}
// MAYBE_TODO: add more features(?):
//Default interface{} // the default value (ignored if `Required` is true)
//Required bool // whether or not the option must be provided
type option struct {
names []string
kind reflect.Kind
description string
}
func (o *option) Names() []string {
return o.names
}
func (o *option) Type() reflect.Kind {
return o.kind
}
func (o *option) Description() string {
return o.description
}
// constructor helper functions
@ -37,10 +51,10 @@ func NewOption(kind reflect.Kind, names ...string) Option {
desc := names[len(names)-1]
names = names[:len(names)-1]
return Option{
Names: names,
Type: kind,
Description: desc,
return &option{
names: names,
kind: kind,
description: desc,
}
}

View File

@ -92,13 +92,6 @@ func (r *request) Path() []string {
// Option returns the value of the option for given name.
func (r *request) Option(name string) *OptionValue {
val, found := r.options[name]
if found {
return &OptionValue{val, found}
}
// if a value isn't defined for that name, we will try to look it up by its aliases
// find the option with the specified name
option, found := r.optionDefs[name]
if !found {
@ -106,8 +99,8 @@ func (r *request) Option(name string) *OptionValue {
}
// try all the possible names, break if we find a value
for _, n := range option.Names {
val, found = r.options[n]
for _, n := range option.Names() {
val, found := r.options[n]
if found {
return &OptionValue{val, found}
}
@ -135,7 +128,7 @@ func (r *request) SetOption(name string, val interface{}) {
}
// try all the possible names, if we already have a value then set over it
for _, n := range option.Names {
for _, n := range option.Names() {
_, found := r.options[n]
if found {
r.options[n] = val
@ -222,9 +215,9 @@ func (r *request) ConvertOptions() error {
}
kind := reflect.TypeOf(v).Kind()
if kind != opt.Type {
if kind != opt.Type() {
if kind == String {
convert := converters[opt.Type]
convert := converters[opt.Type()]
str, ok := v.(string)
if !ok {
return u.ErrCast()
@ -236,19 +229,19 @@ func (r *request) ConvertOptions() error {
value = "empty value"
}
return fmt.Errorf("Could not convert %s to type '%s' (for option '-%s')",
value, opt.Type.String(), k)
value, opt.Type().String(), k)
}
r.options[k] = val
} else {
return fmt.Errorf("Option '%s' should be type '%s', but got type '%s'",
k, opt.Type.String(), kind.String())
k, opt.Type().String(), kind.String())
}
} else {
r.options[k] = v
}
for _, name := range opt.Names {
for _, name := range opt.Names() {
if _, ok := r.options[name]; name != k && ok {
return fmt.Errorf("Duplicate command options were provided ('%s' and '%s')",
k, name)