Fix bug when specified max completions

This commit is contained in:
c-bata 2017-07-18 00:52:55 +09:00
parent 7b8f4e8e91
commit 6dcb8dfe6e
3 changed files with 43 additions and 36 deletions

@ -118,7 +118,7 @@ func OptionSelectedSuggestionBGColor(x Color) option {
func OptionMaxCompletions(x uint16) option { func OptionMaxCompletions(x uint16) option {
return func(p *Prompt) error { return func(p *Prompt) error {
p.renderer.maxCompletions = x p.maxCompletions = x
return nil return nil
} }
} }
@ -141,12 +141,12 @@ func NewPrompt(executor Executor, completer Completer, opts ...option) *Prompt {
suggestionBGColor: Cyan, suggestionBGColor: Cyan,
selectedSuggestionTextColor: Black, selectedSuggestionTextColor: Black,
selectedSuggestionBGColor: Turquoise, selectedSuggestionBGColor: Turquoise,
maxCompletions: 10,
}, },
buf: NewBuffer(), buf: NewBuffer(),
executor: executor, executor: executor,
completer: completer, completer: completer,
chosen: -1, maxCompletions: 6,
selected: -1,
} }
for _, opt := range opts { for _, opt := range opts {

@ -11,12 +11,13 @@ type Executor func(*Buffer) string
type Completer func(*Buffer) []string type Completer func(*Buffer) []string
type Prompt struct { type Prompt struct {
in ConsoleParser in ConsoleParser
buf *Buffer buf *Buffer
renderer *Render renderer *Render
executor Executor executor Executor
completer Completer completer Completer
chosen int // -1 means nothing one is chosen. maxCompletions uint16
selected int // -1 means nothing one is selected.
} }
func (p *Prompt) Run() { func (p *Prompt) Run() {
@ -36,19 +37,19 @@ func (p *Prompt) Run() {
p.renderer.Erase(p.buf) p.renderer.Erase(p.buf)
ac := p.in.GetASCIICode(b) ac := p.in.GetASCIICode(b)
if ac == nil { if ac == nil {
if p.chosen != -1 { if p.selected != -1 {
c := p.completer(p.buf)[p.chosen] c := p.completer(p.buf)[p.selected]
w := p.buf.Document().GetWordBeforeCursor() w := p.buf.Document().GetWordBeforeCursor()
if w != "" { if w != "" {
p.buf.DeleteBeforeCursor(len([]rune(w))) p.buf.DeleteBeforeCursor(len([]rune(w)))
} }
p.buf.InsertText(c, false, true) p.buf.InsertText(c, false, true)
} }
p.chosen = -1 p.selected = -1
p.buf.InsertText(string(b), false, true) p.buf.InsertText(string(b), false, true)
} else if ac.Key == ControlJ || ac.Key == Enter { } else if ac.Key == ControlJ || ac.Key == Enter {
if p.chosen != -1 { if p.selected != -1 {
c := p.completer(p.buf)[p.chosen] c := p.completer(p.buf)[p.selected]
w := p.buf.Document().GetWordBeforeCursor() w := p.buf.Document().GetWordBeforeCursor()
if w != "" { if w != "" {
p.buf.DeleteBeforeCursor(len([]rune(w))) p.buf.DeleteBeforeCursor(len([]rune(w)))
@ -58,30 +59,26 @@ func (p *Prompt) Run() {
res := p.executor(p.buf) res := p.executor(p.buf)
p.renderer.BreakLine(p.buf, res) p.renderer.BreakLine(p.buf, res)
p.buf = NewBuffer() p.buf = NewBuffer()
p.chosen = -1 p.selected = -1
} else if ac.Key == ControlC || ac.Key == ControlD { } else if ac.Key == ControlC || ac.Key == ControlD {
return return
} else if ac.Key == BackTab || ac.Key == Up { } else if ac.Key == BackTab || ac.Key == Up {
p.chosen -= 1 p.selected -= 1
} else if ac.Key == Tab || ac.Key == ControlI || ac.Key == Down { } else if ac.Key == Tab || ac.Key == ControlI || ac.Key == Down {
p.chosen += 1 p.selected += 1
} else { } else {
InputHandler(ac, p.buf) InputHandler(ac, p.buf)
p.chosen = -1 p.selected = -1
} }
completions := p.completer(p.buf) completions := p.completer(p.buf)
if p.chosen >= len(completions) { p.updateSelectedCompletion(completions)
p.chosen = -1 p.renderer.Render(p.buf, completions, p.maxCompletions, p.selected)
} else if p.chosen < -1 {
p.chosen = len(completions) - 1
}
p.renderer.Render(p.buf, completions, p.chosen)
case w := <-winSizeCh: case w := <-winSizeCh:
p.renderer.UpdateWinSize(w) p.renderer.UpdateWinSize(w)
p.renderer.Erase(p.buf) p.renderer.Erase(p.buf)
completions := p.completer(p.buf) completions := p.completer(p.buf)
p.renderer.Render(p.buf, completions, p.chosen) p.renderer.Render(p.buf, completions, p.maxCompletions, p.selected)
case e := <-exitCh: case e := <-exitCh:
if e { if e {
return return
@ -92,6 +89,18 @@ func (p *Prompt) Run() {
} }
} }
func (p *Prompt) updateSelectedCompletion(completions []string) {
max := int(p.maxCompletions)
if len(completions) < max {
max = len(completions)
}
if p.selected >= max {
p.selected = -1
} else if p.selected < -1 {
p.selected = max - 1
}
}
func (p *Prompt) setUp() { func (p *Prompt) setUp() {
p.in.Setup() p.in.Setup()
p.renderer.Setup() p.renderer.Setup()

@ -8,7 +8,6 @@ type Render struct {
title string title string
row uint16 row uint16
col uint16 col uint16
maxCompletions uint16
// colors // colors
prefixTextColor Color prefixTextColor Color
prefixBGColor Color prefixBGColor Color
@ -60,15 +59,14 @@ func (r *Render) UpdateWinSize(ws *WinSize) {
return return
} }
func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) { func (r *Render) renderCompletion(buf *Buffer, words []string, max uint16, selected int) {
max := int(r.maxCompletions) if max > r.row {
if r.maxCompletions > r.row { max = r.row
max = int(r.row)
} }
if l := len(words); l == 0 { if l := len(words); l == 0 {
return return
} else if l > max { } else if l > int(max) {
words = words[:max] words = words[:max]
} }
@ -89,7 +87,7 @@ func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) {
r.out.SetColor(White, Cyan) r.out.SetColor(White, Cyan)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
r.out.CursorDown(1) r.out.CursorDown(1)
if i == chosen { if i == selected {
r.out.SetColor(r.selectedSuggestionTextColor, r.selectedSuggestionBGColor) r.out.SetColor(r.selectedSuggestionTextColor, r.selectedSuggestionBGColor)
} else { } else {
r.out.SetColor(r.suggestionTextColor, r.suggestionBGColor) r.out.SetColor(r.suggestionTextColor, r.suggestionBGColor)
@ -114,15 +112,15 @@ func (r *Render) Erase(buffer *Buffer) {
return return
} }
func (r *Render) Render(buffer *Buffer, completions []string, chosen int) { func (r *Render) Render(buffer *Buffer, completions []string, maxCompletions uint16, selected int) {
line := buffer.Document().CurrentLine() line := buffer.Document().CurrentLine()
r.out.SetColor(r.inputTextColor, r.inputBGColor) r.out.SetColor(r.inputTextColor, r.inputBGColor)
r.out.WriteStr(line) r.out.WriteStr(line)
r.out.SetColor(DefaultColor, DefaultColor) r.out.SetColor(DefaultColor, DefaultColor)
r.out.CursorBackward(len(line) - buffer.CursorPosition) r.out.CursorBackward(len(line) - buffer.CursorPosition)
r.renderCompletion(buffer, completions, chosen) r.renderCompletion(buffer, completions, maxCompletions, selected)
if chosen != -1 { if selected != -1 {
c := completions[chosen] c := completions[selected]
r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor()))) r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor())))
r.out.SetColor(r.previewSuggestionTextColor, r.previewSuggestionBGColor) r.out.SetColor(r.previewSuggestionTextColor, r.previewSuggestionBGColor)
r.out.WriteStr(c) r.out.WriteStr(c)