140 lines
2.9 KiB
Go
140 lines
2.9 KiB
Go
package prompt
|
|
|
|
type Render struct {
|
|
Prefix string
|
|
Title string
|
|
out ConsoleWriter
|
|
row uint16
|
|
col uint16
|
|
maxCompletions uint16
|
|
}
|
|
|
|
func (r *Render) Setup() {
|
|
if r.Title != "" {
|
|
r.out.SetTitle(r.Title)
|
|
}
|
|
r.renderPrefix()
|
|
r.out.Flush()
|
|
}
|
|
|
|
func (r *Render) renderPrefix() {
|
|
r.out.SetColor("green", "default")
|
|
r.out.WriteStr(r.Prefix)
|
|
r.out.SetColor("default", "default")
|
|
}
|
|
|
|
func (r *Render) TearDown() {
|
|
r.out.ClearTitle()
|
|
r.out.EraseDown()
|
|
r.out.Flush()
|
|
}
|
|
|
|
func (r *Render) prepareArea(lines int) {
|
|
for i := 0; i < lines; i++ {
|
|
r.out.ScrollDown()
|
|
}
|
|
for i := 0; i < lines; i++ {
|
|
r.out.ScrollUp()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *Render) UpdateWinSize(ws *WinSize) {
|
|
r.row = ws.Row
|
|
r.col = ws.Col
|
|
return
|
|
}
|
|
|
|
func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) {
|
|
if l := len(words); l == 0 {
|
|
return
|
|
} else if l > int(r.maxCompletions) - 2 || l >= int(r.row) - 2 {
|
|
if r.maxCompletions > r.row {
|
|
words = words[:int(r.row) - 2]
|
|
} else {
|
|
words = words[:int(r.maxCompletions) - 2]
|
|
}
|
|
}
|
|
|
|
formatted, width := formatCompletions(words)
|
|
l := len(formatted)
|
|
r.prepareArea(l)
|
|
|
|
d := (len(r.Prefix) + len(buf.Document().TextBeforeCursor())) % int(r.col)
|
|
if d + width + 3 > int(r.col) {
|
|
r.out.CursorBackward(d + width + 3 - int(r.col))
|
|
}
|
|
|
|
r.out.SetColor("white", "teal")
|
|
for i := 0; i < l; i++ {
|
|
r.out.CursorDown(1)
|
|
if i == chosen {
|
|
r.out.SetColor("black", "turquoise")
|
|
} else {
|
|
r.out.SetColor("white", "cyan")
|
|
}
|
|
r.out.WriteStr(" " + formatted[i] + " ")
|
|
r.out.SetColor("white", "darkGray")
|
|
r.out.Write([]byte(" "))
|
|
r.out.CursorBackward(width + 3)
|
|
}
|
|
if d + width + 3 > int(r.col) {
|
|
r.out.CursorForward(d + width + 3 - int(r.col))
|
|
}
|
|
|
|
r.out.CursorUp(l)
|
|
r.out.SetColor("default", "default")
|
|
return
|
|
}
|
|
|
|
func (r *Render) Erase(buffer *Buffer) {
|
|
r.out.CursorBackward(len(r.Prefix))
|
|
r.out.CursorBackward(buffer.CursorPosition + 100)
|
|
r.out.EraseDown()
|
|
r.renderPrefix()
|
|
r.out.Flush()
|
|
return
|
|
}
|
|
|
|
func (r *Render) Render(buffer *Buffer, completions []string, chosen int) {
|
|
line := buffer.Document().CurrentLine()
|
|
r.out.WriteStr(line)
|
|
r.out.CursorBackward(len(line) - buffer.CursorPosition)
|
|
r.renderCompletion(buffer, completions, chosen)
|
|
if chosen != -1 {
|
|
c := completions[chosen]
|
|
r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor())))
|
|
r.out.WriteStr(c)
|
|
}
|
|
r.out.Flush()
|
|
}
|
|
|
|
func (r *Render) BreakLine(buffer *Buffer, result string) {
|
|
r.out.WriteStr(buffer.Document().Text)
|
|
r.out.WriteStr("\n")
|
|
r.out.WriteStr(result)
|
|
r.out.WriteStr("\n")
|
|
r.renderPrefix()
|
|
}
|
|
|
|
func formatCompletions(words []string) (new []string, width int) {
|
|
num := len(words)
|
|
new = make([]string, num)
|
|
width = 0
|
|
|
|
for i := 0; i < num; i++ {
|
|
if width < len([]rune(words[i])) {
|
|
width = len([]rune(words[i]))
|
|
}
|
|
}
|
|
|
|
for i := 0; i < num; i++ {
|
|
spaces := width - len([]rune(words[i]))
|
|
new[i] = words[i]
|
|
for j := 0; j < spaces; j++ {
|
|
new[i] += " "
|
|
}
|
|
}
|
|
return
|
|
}
|