Merge pull request #24 from DanCripe/master

An extended prefix completion implementation
This commit is contained in:
Chzyer 2016-01-08 00:00:53 +08:00
commit cbab1f1566
1 changed files with 40 additions and 16 deletions

View File

@ -7,9 +7,16 @@ import (
"github.com/chzyer/readline/runes" "github.com/chzyer/readline/runes"
) )
type PrefixCompleterInterface interface {
Print(prefix string, level int, buf *bytes.Buffer)
Do(line []rune, pos int) (newLine [][]rune, length int)
GetName() []rune
GetChildren() []PrefixCompleterInterface
}
type PrefixCompleter struct { type PrefixCompleter struct {
Name []rune Name []rune
Children []*PrefixCompleter Children []PrefixCompleterInterface
} }
func (p *PrefixCompleter) Tree(prefix string) string { func (p *PrefixCompleter) Tree(prefix string) string {
@ -18,27 +25,39 @@ func (p *PrefixCompleter) Tree(prefix string) string {
return buf.String() return buf.String()
} }
func (p *PrefixCompleter) Print(prefix string, level int, buf *bytes.Buffer) { func Print(p PrefixCompleterInterface, prefix string, level int, buf *bytes.Buffer) {
if strings.TrimSpace(string(p.Name)) != "" { if strings.TrimSpace(string(p.GetName())) != "" {
buf.WriteString(prefix) buf.WriteString(prefix)
if level > 0 { if level > 0 {
buf.WriteString("├") buf.WriteString("├")
buf.WriteString(strings.Repeat("─", (level*4)-2)) buf.WriteString(strings.Repeat("─", (level*4)-2))
buf.WriteString(" ") buf.WriteString(" ")
} }
buf.WriteString(string(p.Name) + "\n") buf.WriteString(string(p.GetName()) + "\n")
level++ level++
} }
for _, ch := range p.Children { for _, ch := range p.GetChildren() {
ch.Print(prefix, level, buf) ch.Print(prefix, level, buf)
} }
} }
func NewPrefixCompleter(pc ...*PrefixCompleter) *PrefixCompleter { 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
}
func NewPrefixCompleter(pc ...PrefixCompleterInterface) *PrefixCompleter {
return PcItem("", pc...) return PcItem("", pc...)
} }
func PcItem(name string, pc ...*PrefixCompleter) *PrefixCompleter { func PcItem(name string, pc ...PrefixCompleterInterface) *PrefixCompleter {
name += " " name += " "
return &PrefixCompleter{ return &PrefixCompleter{
Name: []rune(name), Name: []rune(name),
@ -47,24 +66,29 @@ func PcItem(name string, pc ...*PrefixCompleter) *PrefixCompleter {
} }
func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int) { func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int) {
return Do(p, line, pos)
}
func Do(p PrefixCompleterInterface, line []rune, pos int) (newLine [][]rune, offset int) {
line = line[:pos] line = line[:pos]
goNext := false goNext := false
var lineCompleter *PrefixCompleter var lineCompleter PrefixCompleterInterface
for _, child := range p.Children { for _, child := range p.GetChildren() {
if len(line) >= len(child.Name) { childName := child.GetName()
if runes.HasPrefix(line, child.Name) { if len(line) >= len(childName) {
if len(line) == len(child.Name) { if runes.HasPrefix(line, childName) {
if len(line) == len(childName) {
newLine = append(newLine, []rune{' '}) newLine = append(newLine, []rune{' '})
} else { } else {
newLine = append(newLine, child.Name) newLine = append(newLine, childName)
} }
offset = len(child.Name) offset = len(childName)
lineCompleter = child lineCompleter = child
goNext = true goNext = true
} }
} else { } else {
if runes.HasPrefix(child.Name, line) { if runes.HasPrefix(childName, line) {
newLine = append(newLine, child.Name[len(line):]) newLine = append(newLine, childName[len(line):])
offset = len(line) offset = len(line)
lineCompleter = child lineCompleter = child
} }