3 // Command represents a command line
4 // It holds the data that enables auto completion of command line
5 // Command can also be a sub command.
7 // Sub is map of sub commands of the current command
8 // The key refer to the sub command name, and the value is it's
9 // Command descriptive struct.
12 // Flags is a map of flags that the command accepts.
13 // The key is the flag name, and the value is it's predictions.
16 // GlobalFlags is a map of flags that the command accepts.
17 // Global flags that can appear also after a sub command.
20 // Args are extra arguments that the command accepts, those who are
21 // given without any flag before.
25 // Predict returns all possible predictions for args according to the command struct
26 func (c *Command) Predict(a Args) []string {
27 options, _ := c.predict(a)
31 // Commands is the type of Sub member, it maps a command name to a command struct
32 type Commands map[string]Command
34 // Predict completion of sub command names names according to command line arguments
35 func (c Commands) Predict(a Args) (prediction []string) {
37 prediction = append(prediction, sub)
42 // Flags is the type Flags of the Flags member, it maps a flag name to the flag predictions.
43 type Flags map[string]Predictor
45 // Predict completion of flags names according to command line arguments
46 func (f Flags) Predict(a Args) (prediction []string) {
48 // If the flag starts with a hyphen, we avoid emitting the prediction
49 // unless the last typed arg contains a hyphen as well.
50 flagHyphenStart := len(flag) != 0 && flag[0] == '-'
51 lastHyphenStart := len(a.Last) != 0 && a.Last[0] == '-'
52 if flagHyphenStart && !lastHyphenStart {
55 prediction = append(prediction, flag)
61 // only is set to true if no more options are allowed to be returned
62 // those are in cases of special flag that has specific completion arguments,
63 // and other flags or sub commands can't come after it.
64 func (c *Command) predict(a Args) (options []string, only bool) {
66 // search sub commands for predictions first
67 subCommandFound := false
68 for i, arg := range a.Completed {
69 if cmd, ok := c.Sub[arg]; ok {
70 subCommandFound = true
72 // recursive call for sub command
73 options, only = cmd.predict(a.from(i))
78 // We matched so stop searching. Continuing to search can accidentally
79 // match a subcommand with current set of commands, see issue #46.
84 // if last completed word is a global flag that we need to complete
85 if predictor, ok := c.GlobalFlags[a.LastCompleted]; ok && predictor != nil {
86 Log("Predicting according to global flag %s", a.LastCompleted)
87 return predictor.Predict(a), true
90 options = append(options, c.GlobalFlags.Predict(a)...)
92 // if a sub command was entered, we won't add the parent command
93 // completions and we return here.
98 // if last completed word is a command flag that we need to complete
99 if predictor, ok := c.Flags[a.LastCompleted]; ok && predictor != nil {
100 Log("Predicting according to flag %s", a.LastCompleted)
101 return predictor.Predict(a), true
104 options = append(options, c.Sub.Predict(a)...)
105 options = append(options, c.Flags.Predict(a)...)
107 options = append(options, c.Args.Predict(a)...)