summaryrefslogtreecommitdiff
path: root/vendor/github.com/chzyer/readline/complete_helper.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/chzyer/readline/complete_helper.go')
-rw-r--r--vendor/github.com/chzyer/readline/complete_helper.go165
1 files changed, 165 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/complete_helper.go b/vendor/github.com/chzyer/readline/complete_helper.go
new file mode 100644
index 000000000..58d724872
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/complete_helper.go
@@ -0,0 +1,165 @@
+package readline
+
+import (
+ "bytes"
+ "strings"
+)
+
+// Caller type for dynamic completion
+type DynamicCompleteFunc func(string) []string
+
+type PrefixCompleterInterface interface {
+ Print(prefix string, level int, buf *bytes.Buffer)
+ Do(line []rune, pos int) (newLine [][]rune, length int)
+ GetName() []rune
+ GetChildren() []PrefixCompleterInterface
+ SetChildren(children []PrefixCompleterInterface)
+}
+
+type DynamicPrefixCompleterInterface interface {
+ PrefixCompleterInterface
+ IsDynamic() bool
+ GetDynamicNames(line []rune) [][]rune
+}
+
+type PrefixCompleter struct {
+ Name []rune
+ Dynamic bool
+ Callback DynamicCompleteFunc
+ Children []PrefixCompleterInterface
+}
+
+func (p *PrefixCompleter) Tree(prefix string) string {
+ buf := bytes.NewBuffer(nil)
+ p.Print(prefix, 0, buf)
+ return buf.String()
+}
+
+func Print(p PrefixCompleterInterface, prefix string, level int, buf *bytes.Buffer) {
+ if strings.TrimSpace(string(p.GetName())) != "" {
+ buf.WriteString(prefix)
+ if level > 0 {
+ buf.WriteString("├")
+ buf.WriteString(strings.Repeat("─", (level*4)-2))
+ buf.WriteString(" ")
+ }
+ buf.WriteString(string(p.GetName()) + "\n")
+ level++
+ }
+ for _, ch := range p.GetChildren() {
+ ch.Print(prefix, level, buf)
+ }
+}
+
+func (p *PrefixCompleter) Print(prefix string, level int, buf *bytes.Buffer) {
+ Print(p, prefix, level, buf)
+}
+
+func (p *PrefixCompleter) IsDynamic() bool {
+ return p.Dynamic
+}
+
+func (p *PrefixCompleter) GetName() []rune {
+ return p.Name
+}
+
+func (p *PrefixCompleter) GetDynamicNames(line []rune) [][]rune {
+ var names = [][]rune{}
+ for _, name := range p.Callback(string(line)) {
+ names = append(names, []rune(name+" "))
+ }
+ return names
+}
+
+func (p *PrefixCompleter) GetChildren() []PrefixCompleterInterface {
+ return p.Children
+}
+
+func (p *PrefixCompleter) SetChildren(children []PrefixCompleterInterface) {
+ p.Children = children
+}
+
+func NewPrefixCompleter(pc ...PrefixCompleterInterface) *PrefixCompleter {
+ return PcItem("", pc...)
+}
+
+func PcItem(name string, pc ...PrefixCompleterInterface) *PrefixCompleter {
+ name += " "
+ return &PrefixCompleter{
+ Name: []rune(name),
+ Dynamic: false,
+ Children: pc,
+ }
+}
+
+func PcItemDynamic(callback DynamicCompleteFunc, pc ...PrefixCompleterInterface) *PrefixCompleter {
+ return &PrefixCompleter{
+ Callback: callback,
+ Dynamic: true,
+ Children: pc,
+ }
+}
+
+func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int) {
+ return doInternal(p, line, pos, line)
+}
+
+func Do(p PrefixCompleterInterface, line []rune, pos int) (newLine [][]rune, offset int) {
+ return doInternal(p, line, pos, line)
+}
+
+func doInternal(p PrefixCompleterInterface, line []rune, pos int, origLine []rune) (newLine [][]rune, offset int) {
+ line = runes.TrimSpaceLeft(line[:pos])
+ goNext := false
+ var lineCompleter PrefixCompleterInterface
+ for _, child := range p.GetChildren() {
+ childNames := make([][]rune, 1)
+
+ childDynamic, ok := child.(DynamicPrefixCompleterInterface)
+ if ok && childDynamic.IsDynamic() {
+ childNames = childDynamic.GetDynamicNames(origLine)
+ } else {
+ childNames[0] = child.GetName()
+ }
+
+ for _, childName := range childNames {
+ if len(line) >= len(childName) {
+ if runes.HasPrefix(line, childName) {
+ if len(line) == len(childName) {
+ newLine = append(newLine, []rune{' '})
+ } else {
+ newLine = append(newLine, childName)
+ }
+ offset = len(childName)
+ lineCompleter = child
+ goNext = true
+ }
+ } else {
+ if runes.HasPrefix(childName, line) {
+ newLine = append(newLine, childName[len(line):])
+ offset = len(line)
+ lineCompleter = child
+ }
+ }
+ }
+ }
+
+ if len(newLine) != 1 {
+ return
+ }
+
+ tmpLine := make([]rune, 0, len(line))
+ for i := offset; i < len(line); i++ {
+ if line[i] == ' ' {
+ continue
+ }
+
+ tmpLine = append(tmpLine, line[i:]...)
+ return doInternal(lineCompleter, tmpLine, len(tmpLine), origLine)
+ }
+
+ if goNext {
+ return doInternal(lineCompleter, nil, 0, origLine)
+ }
+ return
+}