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,
 		},