diff --git a/commands/cli/helptext.go b/commands/cli/helptext.go index 9acc3c7d2..2563dc8e2 100644 --- a/commands/cli/helptext.go +++ b/commands/cli/helptext.go @@ -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 diff --git a/commands/command.go b/commands/command.go index 1f15fdab4..6baddc2b5 100644 --- a/commands/command.go +++ b/commands/command.go @@ -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) } diff --git a/commands/option.go b/commands/option.go index 3252862a6..6aa5f8f00 100644 --- a/commands/option.go +++ b/commands/option.go @@ -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, } } diff --git a/commands/request.go b/commands/request.go index 112e3dde0..7df966e7c 100644 --- a/commands/request.go +++ b/commands/request.go @@ -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)