summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Dadgar <[email protected]>2017-08-23 13:58:31 -0700
committerAlex Dadgar <[email protected]>2017-08-23 13:58:31 -0700
commitd3c10410d6ceaf0874b5a646f02c88170be33d4c (patch)
tree939f15bbcc1fdc41140f7918fc865fa7735cdf08
parentf4461a52b6329c11190f11fe3384ec8aa964e21c (diff)
Fix a subcommand matching
This PR fixes an issue where a subcommand matches the current set of commands being examined. Fixes issue https://github.com/posener/complete/issues/46
-rw-r--r--command.go6
-rw-r--r--complete_test.go75
2 files changed, 81 insertions, 0 deletions
diff --git a/command.go b/command.go
index eeeb9e0..de501d5 100644
--- a/command.go
+++ b/command.go
@@ -74,6 +74,12 @@ func (c *Command) predict(a Args) (options []string, only bool) {
return
}
}
+
+ // We matched so stop searching. Continuing to search can accidentally
+ // match a subcommand with current set of commands, see issue #46.
+ if subCommandFound {
+ break
+ }
}
// if last completed word is a global flag that we need to complete
diff --git a/complete_test.go b/complete_test.go
index 135c6ad..1a42da1 100644
--- a/complete_test.go
+++ b/complete_test.go
@@ -184,6 +184,81 @@ func TestCompleter_Complete(t *testing.T) {
}
}
+func TestCompleter_Complete_SharedPrefix(t *testing.T) {
+ t.Parallel()
+ initTests()
+
+ c := Command{
+ Sub: Commands{
+ "status": {
+ Flags: Flags{
+ "-f3": PredictNothing,
+ },
+ },
+ "job": {
+ Sub: Commands{
+ "status": {
+ Flags: Flags{
+ "-f4": PredictNothing,
+ },
+ },
+ },
+ },
+ },
+ Flags: Flags{
+ "-o": PredictFiles("*.txt"),
+ },
+ GlobalFlags: Flags{
+ "-h": PredictNothing,
+ "-global1": PredictAnything,
+ },
+ }
+
+ tests := []struct {
+ args string
+ want []string
+ }{
+ {
+ args: "",
+ want: []string{"status", "job", "-h", "-global1", "-o"},
+ },
+ {
+ args: "-",
+ want: []string{"-h", "-global1", "-o"},
+ },
+ {
+ args: "j",
+ want: []string{"job"},
+ },
+ {
+ args: "job ",
+ want: []string{"-h", "-global1", "status"},
+ },
+ {
+ args: "job status ",
+ want: []string{"-f4", "-h", "-global1"},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.args, func(t *testing.T) {
+
+ tt.args = "cmd " + tt.args
+ os.Setenv(envComplete, tt.args)
+ line, _ := getLine()
+
+ got := c.Predict(newArgs(line))
+
+ sort.Strings(tt.want)
+ sort.Strings(got)
+
+ if !equalSlices(got, tt.want) {
+ t.Errorf("failed '%s'\ngot = %s\nwant: %s", t.Name(), got, tt.want)
+ }
+ })
+ }
+}
+
func equalSlices(a, b []string) bool {
if len(a) != len(b) {
return false