go-prompt/completion.go

136 lines
3.1 KiB
Go
Raw Normal View History

2017-08-04 11:19:12 +00:00
package prompt
2017-08-09 12:33:47 +00:00
import (
"log"
"strings"
)
2017-08-04 11:30:50 +00:00
type Suggest struct {
2017-08-04 11:19:12 +00:00
Text string
Description string
}
type CompletionManager struct {
2017-08-09 12:33:47 +00:00
selected int // -1 means nothing one is selected.
tmp []Suggest
Max uint16
completer Completer
}
func (c *CompletionManager) GetSelectedSuggestion() (s Suggest, ok bool) {
if c.selected == -1 {
return Suggest{}, false
} else if c.selected < -1 {
log.Printf("[ERROR] shoud be reached here, selected=%d", c.selected)
return Suggest{}, false
}
return c.tmp[c.selected], true
}
func (c *CompletionManager) GetSuggestions() []Suggest {
return c.tmp
2017-08-04 11:19:12 +00:00
}
func (c *CompletionManager) Reset() {
c.selected = -1
2017-08-09 12:33:47 +00:00
c.Update("")
2017-08-04 11:19:12 +00:00
return
}
2017-08-09 12:33:47 +00:00
func (c *CompletionManager) Update(in string) {
c.tmp = c.completer(in)
2017-08-04 11:19:12 +00:00
return
}
func (c *CompletionManager) Previous() {
c.selected--
2017-08-09 12:33:47 +00:00
c.update()
2017-08-04 11:19:12 +00:00
return
}
func (c *CompletionManager) Next() {
c.selected++
2017-08-09 12:33:47 +00:00
c.update()
2017-08-04 11:19:12 +00:00
return
}
func (c *CompletionManager) Completing() bool {
return c.selected != -1
}
2017-08-09 12:33:47 +00:00
func (c *CompletionManager) update() {
2017-08-04 11:19:12 +00:00
max := int(c.Max)
2017-08-09 12:33:47 +00:00
if len(c.tmp) < max {
max = len(c.tmp)
2017-08-04 11:19:12 +00:00
}
if c.selected >= max {
c.Reset()
} else if c.selected < -1 {
c.selected = max - 1
}
}
2017-08-09 12:33:47 +00:00
func formatCompletions(completions []Suggest, max int) (new []Suggest, width int) {
num := len(completions)
new = make([]Suggest, num)
leftWidth := 0
rightWidth := 0
for i := 0; i < num; i++ {
if leftWidth < len([]rune(completions[i].Text)) {
leftWidth = len([]rune(completions[i].Text))
}
if rightWidth < len([]rune(completions[i].Description)) {
rightWidth = len([]rune(completions[i].Description))
}
}
if diff := max - completionMargin - leftWidth - rightWidth; diff < 0 {
if rightWidth > diff {
rightWidth += diff
} else if rightWidth+rightMargin > -diff {
leftWidth += rightWidth + rightMargin + diff
rightWidth = 0
}
}
if rightWidth == 0 {
width = leftWidth + leftMargin
} else {
width = leftWidth + leftMargin + rightWidth + rightMargin
}
for i := 0; i < num; i++ {
var newText string
var newDescription string
if l := len(completions[i].Text); l > leftWidth {
newText = leftPrefix + completions[i].Text[:leftWidth-len("...")] + "..." + leftSuffix
} else if l < width {
spaces := strings.Repeat(" ", leftWidth-len([]rune(completions[i].Text)))
newText = leftPrefix + completions[i].Text + spaces + leftSuffix
} else {
newText = leftPrefix + completions[i].Text + leftSuffix
}
if rightWidth == 0 {
newDescription = ""
} else if l := len(completions[i].Description); l > rightWidth {
newDescription = rightPrefix + completions[i].Description[:rightWidth-len("...")] + "..." + rightSuffix
} else if l < width {
spaces := strings.Repeat(" ", rightWidth-len([]rune(completions[i].Description)))
newDescription = rightPrefix + completions[i].Description + spaces + rightSuffix
} else {
newDescription = rightPrefix + completions[i].Description + rightSuffix
}
new[i] = Suggest{Text: newText, Description: newDescription}
}
return
}
func NewCompletionManager(completer Completer, max uint16) *CompletionManager {
2017-08-04 11:19:12 +00:00
return &CompletionManager{
2017-08-09 12:33:47 +00:00
selected: -1,
Max: max,
completer: completer,
2017-08-04 11:19:12 +00:00
}
}