summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEyal Posener <[email protected]>2017-05-15 19:32:59 +0300
committerEyal Posener <[email protected]>2017-05-15 19:32:59 +0300
commit096b79324eea451a70ffdf8dd3eb80097410a47f (patch)
treedae76c1575fe5c1172ec4e9fe9c3f9550e18b922
parente00c0546bc15809f7ba7c4e7a17b6be3aac56ccf (diff)
Add global flags for command
Fixes #24
-rw-r--r--command.go38
-rw-r--r--complete_test.go38
-rw-r--r--gocomplete/complete.go2
-rw-r--r--readme.md13
4 files changed, 50 insertions, 41 deletions
diff --git a/command.go b/command.go
index bd5dcc4..eeeb9e0 100644
--- a/command.go
+++ b/command.go
@@ -15,6 +15,10 @@ type Command struct {
// The key is the flag name, and the value is it's predictions.
Flags Flags
+ // GlobalFlags is a map of flags that the command accepts.
+ // Global flags that can appear also after a sub command.
+ GlobalFlags Flags
+
// Args are extra arguments that the command accepts, those who are
// given without any flag before.
Args Predictor
@@ -58,14 +62,7 @@ func (f Flags) Predict(a Args) (prediction []string) {
// and other flags or sub commands can't come after it.
func (c *Command) predict(a Args) (options []string, only bool) {
- // if wordCompleted has something that needs to follow it,
- // it is the most relevant completion
- if predictor, ok := c.Flags[a.LastCompleted]; ok && predictor != nil {
- Log("Predicting according to flag %s", a.Last)
- return predictor.Predict(a), true
- }
-
- // search sub commands for predictions
+ // search sub commands for predictions first
subCommandFound := false
for i, arg := range a.Completed {
if cmd, ok := c.Sub[arg]; ok {
@@ -79,15 +76,28 @@ func (c *Command) predict(a Args) (options []string, only bool) {
}
}
- // if no sub command was found, return a list of the sub commands
- if !subCommandFound {
- options = append(options, c.Sub.Predict(a)...)
+ // if last completed word is a global flag that we need to complete
+ if predictor, ok := c.GlobalFlags[a.LastCompleted]; ok && predictor != nil {
+ Log("Predicting according to global flag %s", a.LastCompleted)
+ return predictor.Predict(a), true
}
- // add global available complete options
- options = append(options, c.Flags.Predict(a)...)
+ options = append(options, c.GlobalFlags.Predict(a)...)
- // add additional expected argument of the command
+ // if a sub command was entered, we won't add the parent command
+ // completions and we return here.
+ if subCommandFound {
+ return
+ }
+
+ // if last completed word is a command flag that we need to complete
+ if predictor, ok := c.Flags[a.LastCompleted]; ok && predictor != nil {
+ Log("Predicting according to flag %s", a.LastCompleted)
+ return predictor.Predict(a), true
+ }
+
+ options = append(options, c.Sub.Predict(a)...)
+ options = append(options, c.Flags.Predict(a)...)
if c.Args != nil {
options = append(options, c.Args.Predict(a)...)
}
diff --git a/complete_test.go b/complete_test.go
index 5cc4be0..cd61ceb 100644
--- a/complete_test.go
+++ b/complete_test.go
@@ -11,36 +11,30 @@ func TestCompleter_Complete(t *testing.T) {
initTests()
c := Command{
- Sub: map[string]Command{
+ Sub: Commands{
"sub1": {
- Flags: map[string]Predictor{
+ Flags: Flags{
"-flag1": PredictAnything,
"-flag2": PredictNothing,
},
},
"sub2": {
- Flags: map[string]Predictor{
+ Flags: Flags{
"-flag2": PredictNothing,
"-flag3": PredictSet("opt1", "opt2", "opt12"),
},
Args: PredictFiles("*.md"),
},
},
- Flags: map[string]Predictor{
+ Flags: Flags{
+ "-o": PredictFiles("*.txt"),
+ },
+ GlobalFlags: Flags{
"-h": PredictNothing,
"-global1": PredictAnything,
- "-o": PredictFiles("*.txt"),
},
}
- allGlobals := []string{}
- for sub := range c.Sub {
- allGlobals = append(allGlobals, sub)
- }
- for flag := range c.Flags {
- allGlobals = append(allGlobals, flag)
- }
-
testTXTFiles := []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt"}
tests := []struct {
@@ -49,7 +43,7 @@ func TestCompleter_Complete(t *testing.T) {
}{
{
args: "",
- want: allGlobals,
+ want: []string{"sub1", "sub2", "-h", "-global1", "-o"},
},
{
args: "-",
@@ -57,7 +51,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-h ",
- want: allGlobals,
+ want: []string{"sub1", "sub2", "-h", "-global1", "-o"},
},
{
args: "-global1 ", // global1 is known follow flag
@@ -77,11 +71,11 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub1 ",
- want: []string{"-flag1", "-flag2", "-h", "-global1", "-o"},
+ want: []string{"-flag1", "-flag2", "-h", "-global1"},
},
{
args: "sub2 ",
- want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
+ want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1"},
},
{
args: "sub2 ./",
@@ -93,7 +87,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub2 -flag2 ",
- want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
+ want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1"},
},
{
args: "sub1 -fl",
@@ -109,7 +103,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub1 -flag2 ",
- want: []string{"-flag1", "-flag2", "-h", "-global1", "-o"},
+ want: []string{"-flag1", "-flag2", "-h", "-global1"},
},
{
args: "-no-such-flag",
@@ -117,7 +111,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-no-such-flag ",
- want: allGlobals,
+ want: []string{"sub1", "sub2", "-h", "-global1", "-o"},
},
{
args: "no-such-command",
@@ -125,7 +119,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "no-such-command ",
- want: allGlobals,
+ want: []string{"sub1", "sub2", "-h", "-global1", "-o"},
},
{
args: "-o ",
@@ -149,7 +143,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-o ./readme.md ",
- want: allGlobals,
+ want: []string{"sub1", "sub2", "-h", "-global1", "-o"},
},
{
args: "-o sub2 -flag3 ",
diff --git a/gocomplete/complete.go b/gocomplete/complete.go
index 5c24417..a44d8aa 100644
--- a/gocomplete/complete.go
+++ b/gocomplete/complete.go
@@ -181,7 +181,7 @@ func main() {
"fix": fix,
"version": version,
},
- Flags: complete.Flags{
+ GlobalFlags: complete.Flags{
"-h": complete.PredictNothing,
},
}
diff --git a/readme.md b/readme.md
index 66e327a..274474d 100644
--- a/readme.md
+++ b/readme.md
@@ -85,15 +85,20 @@ func main() {
// define flags of the 'run' main command
Flags: complete.Flags{
-
- // a flag '-h' which does not expects anything after it
- "-h": complete.PredictNothing,
-
// a flag -o, which expects a file ending with .out after
// it, the tab completion will auto complete for files matching
// the given pattern.
"-o": complete.PredictFiles("*.out"),
},
+
+ // define gloabl flags of the 'run' main command
+ // those will show up also when a sub command was entered in the
+ // command line
+ Flags: complete.Flags{
+
+ // a flag '-h' which does not expects anything after it
+ "-h": complete.PredictNothing,
+ },
}
// run the command completion, as part of the main() function.