From 6dcb8dfe6e33370702182cc9d332e27952cb31fb Mon Sep 17 00:00:00 2001 From: c-bata Date: Tue, 18 Jul 2017 00:52:55 +0900 Subject: [PATCH] Fix bug when specified max completions --- prompt/option.go | 6 +++--- prompt/prompt.go | 53 ++++++++++++++++++++++++++++-------------------- prompt/render.go | 20 ++++++++---------- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/prompt/option.go b/prompt/option.go index 3136745..64f20eb 100644 --- a/prompt/option.go +++ b/prompt/option.go @@ -118,7 +118,7 @@ func OptionSelectedSuggestionBGColor(x Color) option { func OptionMaxCompletions(x uint16) option { return func(p *Prompt) error { - p.renderer.maxCompletions = x + p.maxCompletions = x return nil } } @@ -141,12 +141,12 @@ func NewPrompt(executor Executor, completer Completer, opts ...option) *Prompt { suggestionBGColor: Cyan, selectedSuggestionTextColor: Black, selectedSuggestionBGColor: Turquoise, - maxCompletions: 10, }, buf: NewBuffer(), executor: executor, completer: completer, - chosen: -1, + maxCompletions: 6, + selected: -1, } for _, opt := range opts { diff --git a/prompt/prompt.go b/prompt/prompt.go index 1bb2cd9..c6e6c9e 100644 --- a/prompt/prompt.go +++ b/prompt/prompt.go @@ -11,12 +11,13 @@ type Executor func(*Buffer) string type Completer func(*Buffer) []string type Prompt struct { - in ConsoleParser - buf *Buffer - renderer *Render - executor Executor - completer Completer - chosen int // -1 means nothing one is chosen. + in ConsoleParser + buf *Buffer + renderer *Render + executor Executor + completer Completer + maxCompletions uint16 + selected int // -1 means nothing one is selected. } func (p *Prompt) Run() { @@ -36,19 +37,19 @@ func (p *Prompt) Run() { p.renderer.Erase(p.buf) ac := p.in.GetASCIICode(b) if ac == nil { - if p.chosen != -1 { - c := p.completer(p.buf)[p.chosen] + if p.selected != -1 { + c := p.completer(p.buf)[p.selected] w := p.buf.Document().GetWordBeforeCursor() if w != "" { p.buf.DeleteBeforeCursor(len([]rune(w))) } p.buf.InsertText(c, false, true) } - p.chosen = -1 + p.selected = -1 p.buf.InsertText(string(b), false, true) } else if ac.Key == ControlJ || ac.Key == Enter { - if p.chosen != -1 { - c := p.completer(p.buf)[p.chosen] + if p.selected != -1 { + c := p.completer(p.buf)[p.selected] w := p.buf.Document().GetWordBeforeCursor() if w != "" { p.buf.DeleteBeforeCursor(len([]rune(w))) @@ -58,30 +59,26 @@ func (p *Prompt) Run() { res := p.executor(p.buf) p.renderer.BreakLine(p.buf, res) p.buf = NewBuffer() - p.chosen = -1 + p.selected = -1 } else if ac.Key == ControlC || ac.Key == ControlD { return } 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 { - p.chosen += 1 + p.selected += 1 } else { InputHandler(ac, p.buf) - p.chosen = -1 + p.selected = -1 } completions := p.completer(p.buf) - if p.chosen >= len(completions) { - p.chosen = -1 - } else if p.chosen < -1 { - p.chosen = len(completions) - 1 - } - p.renderer.Render(p.buf, completions, p.chosen) + p.updateSelectedCompletion(completions) + p.renderer.Render(p.buf, completions, p.maxCompletions, p.selected) case w := <-winSizeCh: p.renderer.UpdateWinSize(w) p.renderer.Erase(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: if e { 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() { p.in.Setup() p.renderer.Setup() diff --git a/prompt/render.go b/prompt/render.go index 622dab3..22e5063 100644 --- a/prompt/render.go +++ b/prompt/render.go @@ -8,7 +8,6 @@ type Render struct { title string row uint16 col uint16 - maxCompletions uint16 // colors prefixTextColor Color prefixBGColor Color @@ -60,15 +59,14 @@ func (r *Render) UpdateWinSize(ws *WinSize) { return } -func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) { - max := int(r.maxCompletions) - if r.maxCompletions > r.row { - max = int(r.row) +func (r *Render) renderCompletion(buf *Buffer, words []string, max uint16, selected int) { + if max > r.row { + max = r.row } if l := len(words); l == 0 { return - } else if l > max { + } else if l > int(max) { words = words[:max] } @@ -89,7 +87,7 @@ func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) { r.out.SetColor(White, Cyan) for i := 0; i < l; i++ { r.out.CursorDown(1) - if i == chosen { + if i == selected { r.out.SetColor(r.selectedSuggestionTextColor, r.selectedSuggestionBGColor) } else { r.out.SetColor(r.suggestionTextColor, r.suggestionBGColor) @@ -114,15 +112,15 @@ func (r *Render) Erase(buffer *Buffer) { 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() r.out.SetColor(r.inputTextColor, r.inputBGColor) r.out.WriteStr(line) r.out.SetColor(DefaultColor, DefaultColor) r.out.CursorBackward(len(line) - buffer.CursorPosition) - r.renderCompletion(buffer, completions, chosen) - if chosen != -1 { - c := completions[chosen] + r.renderCompletion(buffer, completions, maxCompletions, selected) + if selected != -1 { + c := completions[selected] r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor()))) r.out.SetColor(r.previewSuggestionTextColor, r.previewSuggestionBGColor) r.out.WriteStr(c)