From c3d9ea142b1de70e68a53bd704b5554a70b72313 Mon Sep 17 00:00:00 2001 From: deoxxa Date: Wed, 27 Apr 2016 16:08:41 +1000 Subject: [PATCH] add tab-complete to repl --- repl/autocompleter.go | 57 +++++++++++++++++++++++++++++++++++++++++++ repl/repl.go | 7 +++++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 repl/autocompleter.go diff --git a/repl/autocompleter.go b/repl/autocompleter.go new file mode 100644 index 0000000..3256678 --- /dev/null +++ b/repl/autocompleter.go @@ -0,0 +1,57 @@ +package repl + +import ( + "regexp" + "strings" + + "github.com/robertkrimen/otto" +) + +type autoCompleter struct { + vm *otto.Otto +} + +var lastExpressionRegex = regexp.MustCompile(`[a-zA-Z0-9]([a-zA-Z0-9\.]*[a-zA-Z0-9])?\.?$`) + +func (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) { + lastExpression := lastExpressionRegex.FindString(string(line)) + + bits := strings.Split(lastExpression, ".") + + first := bits[:len(bits)-1] + last := bits[len(bits)-1] + + var l []string + + if len(first) == 0 { + c := a.vm.Context() + + l = make([]string, len(c.Symbols)) + + i := 0 + for k := range c.Symbols { + l[i] = k + i++ + } + } else { + r, err := a.vm.Eval(strings.Join(bits[:len(bits)-1], ".")) + if err != nil { + return nil, 0 + } + + if o := r.Object(); o != nil { + for _, v := range o.KeysByParent() { + l = append(l, v...) + } + } + } + + var r [][]rune + for _, s := range l { + if strings.HasPrefix(s, last) { + r = append(r, []rune(strings.TrimPrefix(s, last))) + } + } + + return r, len(last) +} diff --git a/repl/repl.go b/repl/repl.go index 0d70cc0..791d336 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -48,7 +48,12 @@ func RunWithPromptAndPrelude(vm *otto.Otto, prompt, prelude string) error { prompt = strings.Trim(prompt, " ") prompt += " " - rl, err := readline.New(prompt) + c := &readline.Config{ + Prompt: prompt, + AutoComplete: &autoCompleter{vm}, + } + + rl, err := readline.NewEx(c) if err != nil { return err }