feat: implement pagination
This commit is contained in:
parent
95fb1dd6f4
commit
63302a5036
|
@ -28,6 +28,8 @@ type CompletionManager struct {
|
|||
tmp []Suggest
|
||||
max uint16
|
||||
completer Completer
|
||||
|
||||
verticalScroll int
|
||||
}
|
||||
|
||||
// GetSelectedSuggestion returns the selected item.
|
||||
|
@ -50,6 +52,7 @@ func (c *CompletionManager) GetSuggestions() []Suggest {
|
|||
// Reset to select nothing.
|
||||
func (c *CompletionManager) Reset() {
|
||||
c.selected = -1
|
||||
c.verticalScroll = 0
|
||||
c.Update(*NewDocument())
|
||||
return
|
||||
}
|
||||
|
@ -62,6 +65,9 @@ func (c *CompletionManager) Update(in Document) {
|
|||
|
||||
// Previous to select the previous suggestion item.
|
||||
func (c *CompletionManager) Previous() {
|
||||
if c.verticalScroll == c.selected && c.selected > 0 {
|
||||
c.verticalScroll--
|
||||
}
|
||||
c.selected--
|
||||
c.update()
|
||||
return
|
||||
|
@ -69,6 +75,9 @@ func (c *CompletionManager) Previous() {
|
|||
|
||||
// Next to select the next suggestion item.
|
||||
func (c *CompletionManager) Next() {
|
||||
if c.verticalScroll+int(c.max)-1 == c.selected {
|
||||
c.verticalScroll++
|
||||
}
|
||||
c.selected++
|
||||
c.update()
|
||||
return
|
||||
|
@ -84,10 +93,12 @@ func (c *CompletionManager) update() {
|
|||
if len(c.tmp) < max {
|
||||
max = len(c.tmp)
|
||||
}
|
||||
if c.selected >= max {
|
||||
|
||||
if c.selected >= len(c.tmp) {
|
||||
c.Reset()
|
||||
} else if c.selected < -1 {
|
||||
c.selected = max - 1
|
||||
c.selected = len(c.tmp) - 1
|
||||
c.verticalScroll = len(c.tmp) - max
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,5 +171,7 @@ func NewCompletionManager(completer Completer, max uint16) *CompletionManager {
|
|||
selected: -1,
|
||||
max: max,
|
||||
completer: completer,
|
||||
|
||||
verticalScroll: 0,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,6 +194,8 @@ func New(executor Executor, completer Completer, opts ...Option) *Prompt {
|
|||
descriptionBGColor: Turquoise,
|
||||
selectedDescriptionTextColor: White,
|
||||
selectedDescriptionBGColor: Cyan,
|
||||
scrollbarThumbColor: DarkGray,
|
||||
scrollbarBGColor: Cyan,
|
||||
},
|
||||
buf: NewBuffer(),
|
||||
executor: executor,
|
||||
|
|
45
render.go
45
render.go
|
@ -1,5 +1,9 @@
|
|||
package prompt
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Render to render prompt information from state of Buffer.
|
||||
type Render struct {
|
||||
out ConsoleWriter
|
||||
|
@ -22,6 +26,8 @@ type Render struct {
|
|||
descriptionBGColor Color
|
||||
selectedDescriptionTextColor Color
|
||||
selectedDescriptionBGColor Color
|
||||
scrollbarThumbColor Color
|
||||
scrollbarBGColor Color
|
||||
}
|
||||
|
||||
// Setup to initialize console output.
|
||||
|
@ -72,24 +78,34 @@ func (r *Render) renderWindowTooSmall() {
|
|||
}
|
||||
|
||||
func (r *Render) renderCompletion(buf *Buffer, completions *CompletionManager) {
|
||||
max := completions.max
|
||||
if max > r.row {
|
||||
max = r.row
|
||||
windowHeight := len(completions.tmp)
|
||||
if windowHeight > int(completions.max) {
|
||||
windowHeight = int(completions.max)
|
||||
}
|
||||
contentHeight := len(completions.tmp)
|
||||
|
||||
fractionVisible := float64(windowHeight) / float64(contentHeight)
|
||||
fractionAbove := float64(completions.verticalScroll) / float64(contentHeight)
|
||||
|
||||
scrollbarHeight := int(math.Min(float64(windowHeight), math.Max(1, float64(windowHeight)*fractionVisible)))
|
||||
scrollbarTop := int(float64(windowHeight) * fractionAbove)
|
||||
|
||||
isScrollThumb := func(row int) bool {
|
||||
return scrollbarTop <= row && row <= scrollbarTop+scrollbarHeight
|
||||
}
|
||||
|
||||
suggestions := completions.GetSuggestions()
|
||||
if l := len(completions.GetSuggestions()); l == 0 {
|
||||
return
|
||||
} else if l > int(max) {
|
||||
suggestions = suggestions[:max]
|
||||
}
|
||||
|
||||
formatted, width := formatSuggestions(
|
||||
suggestions,
|
||||
int(r.col)-len(r.prefix),
|
||||
int(r.col)-len(r.prefix)-1,
|
||||
)
|
||||
formatted = formatted[completions.verticalScroll : completions.verticalScroll+windowHeight]
|
||||
l := len(formatted)
|
||||
r.prepareArea(l)
|
||||
r.prepareArea(windowHeight)
|
||||
|
||||
d := (len(r.prefix) + len(buf.Document().TextBeforeCursor())) % int(r.col)
|
||||
if d == 0 { // the cursor is on right end.
|
||||
|
@ -98,23 +114,32 @@ func (r *Render) renderCompletion(buf *Buffer, completions *CompletionManager) {
|
|||
r.out.CursorBackward(d + width - int(r.col))
|
||||
}
|
||||
|
||||
selected := completions.selected - completions.verticalScroll
|
||||
|
||||
r.out.SetColor(White, Cyan, false)
|
||||
for i := 0; i < l; i++ {
|
||||
r.out.CursorDown(1)
|
||||
if i == completions.selected {
|
||||
if i == selected {
|
||||
r.out.SetColor(r.selectedSuggestionTextColor, r.selectedSuggestionBGColor, true)
|
||||
} else {
|
||||
r.out.SetColor(r.suggestionTextColor, r.suggestionBGColor, false)
|
||||
}
|
||||
r.out.WriteStr(formatted[i].Text)
|
||||
|
||||
if i == completions.selected {
|
||||
if i == selected {
|
||||
r.out.SetColor(r.selectedDescriptionTextColor, r.selectedDescriptionBGColor, false)
|
||||
} else {
|
||||
r.out.SetColor(r.descriptionTextColor, r.descriptionBGColor, false)
|
||||
}
|
||||
r.out.WriteStr(formatted[i].Description)
|
||||
r.out.CursorBackward(width)
|
||||
|
||||
if isScrollThumb(i) {
|
||||
r.out.SetColor(DefaultColor, r.scrollbarThumbColor, false)
|
||||
} else {
|
||||
r.out.SetColor(DefaultColor, r.scrollbarBGColor, false)
|
||||
}
|
||||
r.out.WriteStr(" ")
|
||||
r.out.CursorBackward(width + 1)
|
||||
}
|
||||
if d == 0 { // the cursor is on right end.
|
||||
// DON'T CURSOR DOWN HERE. Because the line doesn't erase properly.
|
||||
|
|
Loading…
Reference in New Issue