summary refs log tree commit diff
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 0000000..58d7248
--- /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
+}