74 lines
1.2 KiB
Go
74 lines
1.2 KiB
Go
package complete
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
envComplete = "COMP_LINE"
|
|
envDebug = "COMP_DEBUG"
|
|
)
|
|
|
|
type Completer struct {
|
|
Command
|
|
log func(format string, args ...interface{})
|
|
}
|
|
|
|
func New(c Command) *Completer {
|
|
return &Completer{
|
|
Command: c,
|
|
log: logger(),
|
|
}
|
|
}
|
|
|
|
func (c *Completer) Complete() {
|
|
args := getLine()
|
|
c.log("Completing args: %s", args)
|
|
|
|
options := c.complete(args)
|
|
|
|
c.log("Completion: %s", options)
|
|
output(options)
|
|
}
|
|
|
|
func (c *Completer) complete(args []string) []string {
|
|
all, _ := c.options(args[:len(args)-1])
|
|
return c.chooseRelevant(last(args), all)
|
|
}
|
|
|
|
func (c *Completer) chooseRelevant(last string, list []string) (opts []string) {
|
|
if last == "" {
|
|
return list
|
|
}
|
|
for _, sub := range list {
|
|
if strings.HasPrefix(sub, last) {
|
|
opts = append(opts, sub)
|
|
}
|
|
}
|
|
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)
|
|
}
|
|
}
|