summaryrefslogtreecommitdiff
path: root/complete.go
diff options
context:
space:
mode:
authorEyal Posener <[email protected]>2017-05-05 16:57:22 +0300
committerEyal Posener <[email protected]>2017-05-05 18:01:08 +0300
commit04e78e42abea95d46d09f7de563ca50d78d3e108 (patch)
treef67a4877c550eb9eafc8eb6314ebbaffe2beb87b /complete.go
Initial commit
Diffstat (limited to 'complete.go')
-rw-r--r--complete.go73
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)
+ }
+}