diff options
| author | Eyal Posener <[email protected]> | 2017-05-05 16:57:22 +0300 |
|---|---|---|
| committer | Eyal Posener <[email protected]> | 2017-05-05 18:01:08 +0300 |
| commit | 04e78e42abea95d46d09f7de563ca50d78d3e108 (patch) | |
| tree | f67a4877c550eb9eafc8eb6314ebbaffe2beb87b /complete.go | |
Initial commit
Diffstat (limited to 'complete.go')
| -rw-r--r-- | complete.go | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/complete.go b/complete.go new file mode 100644 index 0000000..eedaa81 --- /dev/null +++ b/complete.go @@ -0,0 +1,73 @@ +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) + } +} |
