2015-09-25 19:31:09 +03:00
|
|
|
package readline
|
|
|
|
|
2016-01-07 03:46:43 +03:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"strings"
|
2016-04-07 10:55:33 +03:00
|
|
|
|
|
|
|
"github.com/chzyer/readline/runes"
|
2016-01-07 03:46:43 +03:00
|
|
|
)
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
type PrefixCompleterInterface interface {
|
|
|
|
Print(prefix string, level int, buf *bytes.Buffer)
|
|
|
|
Do(line []rune, pos int) (newLine [][]rune, length int)
|
|
|
|
GetName() []rune
|
|
|
|
GetChildren() []PrefixCompleterInterface
|
2016-03-16 13:03:13 +03:00
|
|
|
SetChildren(children []PrefixCompleterInterface)
|
2016-01-07 00:41:13 +03:00
|
|
|
}
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
type PrefixCompleter struct {
|
|
|
|
Name []rune
|
|
|
|
Children []PrefixCompleterInterface
|
2015-09-25 19:31:09 +03:00
|
|
|
}
|
|
|
|
|
2016-01-07 18:54:10 +03:00
|
|
|
func (p *PrefixCompleter) Tree(prefix string) string {
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
p.Print(prefix, 0, buf)
|
|
|
|
return buf.String()
|
|
|
|
}
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
func Print(p PrefixCompleterInterface, prefix string, level int, buf *bytes.Buffer) {
|
|
|
|
if strings.TrimSpace(string(p.GetName())) != "" {
|
2016-01-07 03:46:43 +03:00
|
|
|
buf.WriteString(prefix)
|
|
|
|
if level > 0 {
|
|
|
|
buf.WriteString("├")
|
|
|
|
buf.WriteString(strings.Repeat("─", (level*4)-2))
|
|
|
|
buf.WriteString(" ")
|
|
|
|
}
|
2016-01-07 18:42:12 +03:00
|
|
|
buf.WriteString(string(p.GetName()) + "\n")
|
2016-01-07 03:46:43 +03:00
|
|
|
level++
|
|
|
|
}
|
2016-01-07 18:42:12 +03:00
|
|
|
for _, ch := range p.GetChildren() {
|
2016-01-07 03:46:43 +03:00
|
|
|
ch.Print(prefix, level, buf)
|
|
|
|
}
|
2015-11-20 16:32:53 +03:00
|
|
|
}
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
func (p *PrefixCompleter) Print(prefix string, level int, buf *bytes.Buffer) {
|
|
|
|
Print(p, prefix, level, buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrefixCompleter) GetName() []rune {
|
|
|
|
return p.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrefixCompleter) GetChildren() []PrefixCompleterInterface {
|
|
|
|
return p.Children
|
|
|
|
}
|
|
|
|
|
2016-03-16 13:03:13 +03:00
|
|
|
func (p *PrefixCompleter) SetChildren(children []PrefixCompleterInterface) {
|
|
|
|
p.Children = children
|
|
|
|
}
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
func NewPrefixCompleter(pc ...PrefixCompleterInterface) *PrefixCompleter {
|
2015-09-25 19:31:09 +03:00
|
|
|
return PcItem("", pc...)
|
|
|
|
}
|
|
|
|
|
2016-01-07 18:42:12 +03:00
|
|
|
func PcItem(name string, pc ...PrefixCompleterInterface) *PrefixCompleter {
|
2015-11-14 05:21:55 +03:00
|
|
|
name += " "
|
2016-01-07 03:46:43 +03:00
|
|
|
return &PrefixCompleter{
|
2016-01-07 02:39:08 +03:00
|
|
|
Name: []rune(name),
|
|
|
|
Children: pc,
|
2016-01-07 03:46:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int) {
|
2016-01-07 18:42:12 +03:00
|
|
|
return Do(p, line, pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Do(p PrefixCompleterInterface, line []rune, pos int) (newLine [][]rune, offset int) {
|
2016-04-07 10:55:33 +03:00
|
|
|
line = runes.TrimSpaceLeft(line[:pos])
|
2016-01-07 03:46:43 +03:00
|
|
|
goNext := false
|
2016-01-07 18:42:12 +03:00
|
|
|
var lineCompleter PrefixCompleterInterface
|
|
|
|
for _, child := range p.GetChildren() {
|
|
|
|
childName := child.GetName()
|
|
|
|
if len(line) >= len(childName) {
|
|
|
|
if runes.HasPrefix(line, childName) {
|
|
|
|
if len(line) == len(childName) {
|
2016-01-07 03:46:43 +03:00
|
|
|
newLine = append(newLine, []rune{' '})
|
|
|
|
} else {
|
2016-01-07 18:42:12 +03:00
|
|
|
newLine = append(newLine, childName)
|
2016-01-07 03:46:43 +03:00
|
|
|
}
|
2016-01-07 18:42:12 +03:00
|
|
|
offset = len(childName)
|
2016-01-07 03:46:43 +03:00
|
|
|
lineCompleter = child
|
|
|
|
goNext = true
|
|
|
|
}
|
|
|
|
} else {
|
2016-01-07 18:42:12 +03:00
|
|
|
if runes.HasPrefix(childName, line) {
|
|
|
|
newLine = append(newLine, childName[len(line):])
|
2016-01-07 03:46:43 +03:00
|
|
|
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 lineCompleter.Do(tmpLine, len(tmpLine))
|
|
|
|
}
|
|
|
|
|
|
|
|
if goNext {
|
|
|
|
return lineCompleter.Do(nil, 0)
|
|
|
|
}
|
|
|
|
return
|
2015-09-25 19:31:09 +03:00
|
|
|
}
|