open-nomad/vendor/github.com/posener/complete/command.go
Seth Hoenig 435c0d9fc8 deps: Switch to Go modules for dependency management
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.
2020-06-02 14:30:36 -05:00

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
}