Merge pull request #228 from nickwei84/master
Completion on short option names allows for exploration of short and long option names
diff --git a/completion.go b/completion.go
index 6a0432b..7a7a08b 100644
--- a/completion.go
+++ b/completion.go
@@ -73,27 +73,8 @@
}
}
-func (c *completion) completeOptionNames(names map[string]*Option, prefix string, match string) []Completion {
- n := make([]Completion, 0, len(names))
-
- for k, opt := range names {
- if strings.HasPrefix(k, match) && !opt.Hidden {
- n = append(n, Completion{
- Item: prefix + k,
- Description: opt.Description,
- })
- }
- }
-
- return n
-}
-
-func (c *completion) completeLongNames(s *parseState, prefix string, match string) []Completion {
- return c.completeOptionNames(s.lookup.longNames, prefix, match)
-}
-
-func (c *completion) completeShortNames(s *parseState, prefix string, match string) []Completion {
- if len(match) != 0 {
+func (c *completion) completeOptionNames(s *parseState, prefix string, match string, short bool) []Completion {
+ if short && len(match) != 0 {
return []Completion{
Completion{
Item: prefix + match,
@@ -101,7 +82,42 @@
}
}
- return c.completeOptionNames(s.lookup.shortNames, prefix, match)
+ var results []Completion
+ repeats := map[string]bool{}
+
+ for name, opt := range s.lookup.longNames {
+ if strings.HasPrefix(name, match) && !opt.Hidden {
+ results = append(results, Completion{
+ Item: defaultLongOptDelimiter + name,
+ Description: opt.Description,
+ })
+
+ if short {
+ repeats[string(opt.ShortName)] = true
+ }
+ }
+ }
+
+ if short {
+ for name, opt := range s.lookup.shortNames {
+ if _, exist := repeats[name]; !exist && strings.HasPrefix(name, match) && !opt.Hidden {
+ results = append(results, Completion{
+ Item: string(defaultShortOptDelimiter) + name,
+ Description: opt.Description,
+ })
+ }
+ }
+ }
+
+ return results
+}
+
+func (c *completion) completeNamesForLongPrefix(s *parseState, prefix string, match string) []Completion {
+ return c.completeOptionNames(s, prefix, match, false)
+}
+
+func (c *completion) completeNamesForShortPrefix(s *parseState, prefix string, match string) []Completion {
+ return c.completeOptionNames(s, prefix, match, true)
}
func (c *completion) completeCommands(s *parseState, match string) []Completion {
@@ -237,7 +253,7 @@
if opt := s.lookup.shortNames[sname]; opt != nil && opt.canArgument() {
ret = c.completeValue(opt.value, prefix+sname, optname[n:])
} else {
- ret = c.completeShortNames(s, prefix, optname)
+ ret = c.completeNamesForShortPrefix(s, prefix, optname)
}
} else if argument != nil {
if islong {
@@ -250,9 +266,9 @@
ret = c.completeValue(opt.value, prefix+optname+split, *argument)
}
} else if islong {
- ret = c.completeLongNames(s, prefix, optname)
+ ret = c.completeNamesForLongPrefix(s, prefix, optname)
} else {
- ret = c.completeShortNames(s, prefix, optname)
+ ret = c.completeNamesForShortPrefix(s, prefix, optname)
}
} else if len(s.positional) > 0 {
// Complete for positional argument
diff --git a/completion_test.go b/completion_test.go
index af81993..26f70e4 100644
--- a/completion_test.go
+++ b/completion_test.go
@@ -38,6 +38,7 @@
var completionTestOptions struct {
Verbose bool `short:"v" long:"verbose" description:"Verbose messages"`
Debug bool `short:"d" long:"debug" description:"Enable debug"`
+ Info bool `short:"i" description:"Display info"`
Version bool `long:"version" description:"Show version"`
Required bool `long:"required" required:"true" description:"This is required"`
Hidden bool `long:"hidden" hidden:"true" description:"This is hidden"`
@@ -87,7 +88,14 @@
{
// Short names
[]string{"-"},
- []string{"-d", "-v"},
+ []string{"--debug", "--required", "--verbose", "--version", "-i"},
+ false,
+ },
+
+ {
+ // Short names full
+ []string{"-i"},
+ []string{"-i"},
false,
},