2017-05-05 08:57:22 -05:00
|
|
|
package complete
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
envComplete = "COMP_LINE"
|
|
|
|
envDebug = "COMP_DEBUG"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Completer struct {
|
|
|
|
Command
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(c Command) *Completer {
|
2017-05-05 13:57:21 -05:00
|
|
|
return &Completer{Command: c}
|
2017-05-05 08:57:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Completer) Complete() {
|
|
|
|
args := getLine()
|
2017-05-05 13:57:21 -05:00
|
|
|
logger("Completing args: %s", args)
|
2017-05-05 08:57:22 -05:00
|
|
|
|
|
|
|
options := c.complete(args)
|
|
|
|
|
2017-05-05 13:57:21 -05:00
|
|
|
logger("Completion: %s", options)
|
2017-05-05 08:57:22 -05:00
|
|
|
output(options)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Completer) complete(args []string) []string {
|
|
|
|
all, _ := c.options(args[:len(args)-1])
|
|
|
|
return c.chooseRelevant(last(args), all)
|
|
|
|
}
|
|
|
|
|
2017-05-05 13:59:10 -05:00
|
|
|
func (c *Completer) chooseRelevant(last string, options []Option) (relevant []string) {
|
|
|
|
for _, option := range options {
|
|
|
|
if option.Matches(last) {
|
|
|
|
relevant = append(relevant, option.String())
|
2017-05-05 08:57:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func getLine() []string {
|
|
|
|
line := os.Getenv(envComplete)
|
|
|
|
if line == "" {
|
|
|
|
panic("should be run as a complete script")
|
|
|
|
}
|
|
|
|
return strings.Split(line, " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func last(args []string) (last string) {
|
|
|
|
if len(args) > 0 {
|
|
|
|
last = args[len(args)-1]
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func output(options []string) {
|
|
|
|
// stdout of program defines the complete options
|
|
|
|
for _, option := range options {
|
|
|
|
fmt.Println(option)
|
|
|
|
}
|
|
|
|
}
|