435c0d9fc8
This PR switches the Nomad repository from using govendor to Go modules for managing dependencies. Aspects of the Nomad workflow remain pretty much the same. The usual Makefile targets should continue to work as they always did. The API submodule simply defers to the parent Nomad version on the repository, keeping the semantics of API versioning that currently exists.
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package complete
|
|
|
|
// Command represents a command line
|
|
// It holds the data that enables auto completion of command line
|
|
// Command can also be a sub command.
|
|
type Command struct {
|
|
// Sub is map of sub commands of the current command
|
|
// The key refer to the sub command name, and the value is it's
|
|
// Command descriptive struct.
|
|
Sub Commands
|
|
|
|
// Flags is a map of flags that the command accepts.
|
|
// 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
|
|
}
|
|
|
|
// Predict returns all possible predictions for args according to the command struct
|
|
func (c *Command) Predict(a Args) []string {
|
|
options, _ := c.predict(a)
|
|
return options
|
|
}
|
|
|
|
// Commands is the type of Sub member, it maps a command name to a command struct
|
|
type Commands map[string]Command
|
|
|
|
// Predict completion of sub command names names according to command line arguments
|
|
func (c Commands) Predict(a Args) (prediction []string) {
|
|
for sub := range c {
|
|
prediction = append(prediction, sub)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Flags is the type Flags of the Flags member, it maps a flag name to the flag predictions.
|
|
type Flags map[string]Predictor
|
|
|
|
// Predict completion of flags names according to command line arguments
|
|
func (f Flags) Predict(a Args) (prediction []string) {
|
|
for flag := range f {
|
|
// If the flag starts with a hyphen, we avoid emitting the prediction
|
|
// unless the last typed arg contains a hyphen as well.
|
|
flagHyphenStart := len(flag) != 0 && flag[0] == '-'
|
|
lastHyphenStart := len(a.Last) != 0 && a.Last[0] == '-'
|
|
if flagHyphenStart && !lastHyphenStart {
|
|
continue
|
|
}
|
|
prediction = append(prediction, flag)
|
|
}
|
|
return
|
|
}
|
|
|
|
// predict options
|
|
// only is set to true if no more options are allowed to be returned
|
|
// those are in cases of special flag that has specific completion arguments,
|
|
// and other flags or sub commands can't come after it.
|
|
func (c *Command) predict(a Args) (options []string, only bool) {
|
|
|
|
// search sub commands for predictions first
|
|
subCommandFound := false
|
|
for i, arg := range a.Completed {
|
|
if cmd, ok := c.Sub[arg]; ok {
|
|
subCommandFound = true
|
|
|
|
// recursive call for sub command
|
|
options, only = cmd.predict(a.from(i))
|
|
if only {
|
|
return
|
|
}
|
|
|
|
// We matched so stop searching. Continuing to search can accidentally
|
|
// match a subcommand with current set of commands, see issue #46.
|
|
break
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
options = append(options, c.GlobalFlags.Predict(a)...)
|
|
|
|
// 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)...)
|
|
}
|
|
|
|
return
|
|
}
|