summaryrefslogtreecommitdiff
path: root/command.go
diff options
context:
space:
mode:
authorEyal Posener <[email protected]>2019-11-14 06:51:44 +0200
committerEyal Posener <[email protected]>2019-11-18 01:05:47 +0200
commit8724aaf18312e54750540a9578e00d61b1c545d8 (patch)
treed3e736b4fb279975bbcc017ae1bad53e454c5773 /command.go
parent05b68ffc813dd10c420993cb1cf927b346c057b8 (diff)
V2
Diffstat (limited to 'command.go')
-rw-r--r--command.go139
1 files changed, 45 insertions, 94 deletions
diff --git a/command.go b/command.go
index 82d37d5..74ab299 100644
--- a/command.go
+++ b/command.go
@@ -1,111 +1,62 @@
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.
+// Command is an object that can be used to create complete options for a go executable that does
+// not have a good binding to the `Completer` interface, or to use a Go program as complete binary
+// for another executable (see ./gocomplete as an example.)
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.
+ // 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 map[string]*Command
+ // Flags is a map of flags that the command accepts. The key is the flag name, and the value is
+ // it's predictions. In a chain of sub commands, no duplicate flags should be defined.
+ Flags map[string]Predictor
+ // Args are extra arguments that the command accepts, those who are given without any flag
+ // before. In any chain of sub commands, only one of them should predict positional arguments.
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
+// Complete runs the completion of the described command.
+func (c *Command) Complete(name string) {
+ Complete(name, c)
}
-// 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)
+func (c *Command) SubCmdList() []string {
+ subs := make([]string, 0, len(c.Sub))
+ for sub := range c.Sub {
+ subs = append(subs, sub)
}
- return
+ return subs
}
-// 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)
+func (c *Command) SubCmdGet(cmd string) Completer {
+ if c.Sub[cmd] == nil {
+ return nil
}
- return
+ return c.Sub[cmd]
}
-
-// 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
+func (c *Command) FlagList() []string {
+ flags := make([]string, 0, len(c.Flags))
+ for flag := range c.Flags {
+ flags = append(flags, flag)
}
+ return flags
+}
- 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)...)
- }
+func (c *Command) FlagGet(flag string) Predictor {
+ return PredictFunc(func(prefix string) (options []string) {
+ f := c.Flags[flag]
+ if f == nil {
+ return nil
+ }
+ return f.Predict(prefix)
+ })
+}
- return
+func (c *Command) ArgsGet() Predictor {
+ return PredictFunc(func(prefix string) (options []string) {
+ if c.Args == nil {
+ return nil
+ }
+ return c.Args.Predict(prefix)
+ })
}