go-prompt/prompt/render.go

163 lines
3.7 KiB
Go
Raw Normal View History

2017-07-14 01:51:19 +00:00
package prompt
type Render struct {
2017-07-16 19:55:05 +00:00
out ConsoleWriter
2017-07-16 17:11:52 +00:00
prefix string
2017-07-16 17:18:11 +00:00
title string
2017-07-15 13:23:47 +00:00
row uint16
2017-07-16 08:20:58 +00:00
col uint16
2017-07-15 16:04:18 +00:00
maxCompletions uint16
2017-07-16 19:32:42 +00:00
// colors
prefixColor Color
textColor Color
2017-07-16 19:55:05 +00:00
outputTextColor Color
completedTextColor Color
2017-07-16 19:32:42 +00:00
completionTextColor Color
completionBGColor Color
selectedCompletionTextColor Color
selectedCompletionBGColor Color
2017-07-15 11:22:56 +00:00
}
func (r *Render) Setup() {
2017-07-16 17:18:11 +00:00
if r.title != "" {
r.out.SetTitle(r.title)
2017-07-15 11:22:56 +00:00
}
2017-07-15 16:18:40 +00:00
r.renderPrefix()
2017-07-15 13:23:47 +00:00
r.out.Flush()
2017-07-15 11:22:56 +00:00
}
2017-07-15 16:18:40 +00:00
func (r *Render) renderPrefix() {
2017-07-16 19:32:42 +00:00
r.out.SetColor(r.prefixColor, DefaultColor)
2017-07-16 17:11:52 +00:00
r.out.WriteStr(r.prefix)
2017-07-16 19:32:42 +00:00
r.out.SetColor(DefaultColor, DefaultColor)
2017-07-15 16:18:40 +00:00
}
2017-07-15 11:22:56 +00:00
func (r *Render) TearDown() {
r.out.ClearTitle()
r.out.EraseDown()
r.out.Flush()
2017-07-15 08:37:54 +00:00
}
func (r *Render) prepareArea(lines int) {
2017-07-15 08:37:54 +00:00
for i := 0; i < lines; i++ {
r.out.ScrollDown()
}
for i := 0; i < lines; i++ {
r.out.ScrollUp()
}
return
2017-07-14 01:51:19 +00:00
}
2017-07-15 09:03:18 +00:00
func (r *Render) UpdateWinSize(ws *WinSize) {
2017-07-14 01:51:19 +00:00
r.row = ws.Row
r.col = ws.Col
return
}
2017-07-15 16:04:18 +00:00
func (r *Render) renderCompletion(buf *Buffer, words []string, chosen int) {
if l := len(words); l == 0 {
2017-07-15 11:22:56 +00:00
return
2017-07-15 16:04:18 +00:00
} 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]
}
2017-07-15 11:22:56 +00:00
}
2017-07-15 16:04:18 +00:00
2017-07-16 17:11:52 +00:00
formatted, width := formatCompletions(words, int(r.col) - len(r.prefix) - 3)
2017-07-15 09:51:33 +00:00
l := len(formatted)
r.prepareArea(l)
2017-07-15 08:37:54 +00:00
2017-07-16 17:11:52 +00:00
d := (len(r.prefix) + len(buf.Document().TextBeforeCursor())) % int(r.col)
2017-07-15 16:04:18 +00:00
if d + width + 3 > int(r.col) {
r.out.CursorBackward(d + width + 3 - int(r.col))
}
2017-07-16 19:32:42 +00:00
r.out.SetColor(White, Cyan)
2017-07-15 09:51:33 +00:00
for i := 0; i < l; i++ {
r.out.CursorDown(1)
2017-07-15 13:55:11 +00:00
if i == chosen {
2017-07-16 19:32:42 +00:00
r.out.SetColor(r.selectedCompletionTextColor, r.selectedCompletionBGColor)
2017-07-15 13:44:10 +00:00
} else {
2017-07-16 19:32:42 +00:00
r.out.SetColor(r.completionTextColor, r.completionBGColor)
2017-07-15 13:44:10 +00:00
}
2017-07-15 09:51:33 +00:00
r.out.WriteStr(" " + formatted[i] + " ")
2017-07-16 19:32:42 +00:00
r.out.SetColor(White, DarkGray)
2017-07-15 09:51:33 +00:00
r.out.Write([]byte(" "))
r.out.CursorBackward(width + 3)
}
2017-07-15 16:04:18 +00:00
if d + width + 3 > int(r.col) {
r.out.CursorForward(d + width + 3 - int(r.col))
}
2017-07-15 08:37:54 +00:00
2017-07-15 09:51:33 +00:00
r.out.CursorUp(l)
2017-07-16 19:32:42 +00:00
r.out.SetColor(DefaultColor, DefaultColor)
2017-07-15 09:51:33 +00:00
return
}
2017-07-15 08:37:54 +00:00
2017-07-15 11:22:56 +00:00
func (r *Render) Erase(buffer *Buffer) {
2017-07-16 14:11:16 +00:00
r.out.CursorBackward(int(r.col))
2017-07-15 11:22:56 +00:00
r.out.EraseDown()
2017-07-15 16:18:40 +00:00
r.renderPrefix()
2017-07-15 13:23:47 +00:00
r.out.Flush()
2017-07-15 11:22:56 +00:00
return
}
2017-07-15 13:55:11 +00:00
func (r *Render) Render(buffer *Buffer, completions []string, chosen int) {
2017-07-15 11:22:56 +00:00
line := buffer.Document().CurrentLine()
2017-07-16 19:55:05 +00:00
r.out.SetColor(r.textColor, DefaultColor)
2017-07-15 11:22:56 +00:00
r.out.WriteStr(line)
2017-07-16 19:55:05 +00:00
r.out.SetColor(DefaultColor, DefaultColor)
2017-07-15 11:22:56 +00:00
r.out.CursorBackward(len(line) - buffer.CursorPosition)
2017-07-15 16:04:18 +00:00
r.renderCompletion(buffer, completions, chosen)
2017-07-15 14:27:49 +00:00
if chosen != -1 {
c := completions[chosen]
r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor())))
2017-07-16 19:55:05 +00:00
r.out.SetColor(r.completedTextColor, DefaultColor)
2017-07-15 14:27:49 +00:00
r.out.WriteStr(c)
2017-07-16 19:55:05 +00:00
r.out.SetColor(DefaultColor, DefaultColor)
2017-07-15 14:27:49 +00:00
}
2017-07-15 11:22:56 +00:00
r.out.Flush()
}
func (r *Render) BreakLine(buffer *Buffer, result string) {
2017-07-16 19:55:05 +00:00
r.out.SetColor(r.textColor, DefaultColor)
r.out.WriteStr(buffer.Document().Text + "\n")
r.out.SetColor(r.outputTextColor, DefaultColor)
r.out.WriteStr(result + "\n")
r.out.SetColor(DefaultColor, DefaultColor)
2017-07-15 16:18:40 +00:00
r.renderPrefix()
2017-07-15 11:22:56 +00:00
}
2017-07-16 14:11:16 +00:00
func formatCompletions(words []string, max int) (new []string, width int) {
2017-07-15 09:51:33 +00:00
num := len(words)
2017-07-15 14:27:49 +00:00
new = make([]string, num)
width = 0
2017-07-15 08:37:54 +00:00
2017-07-15 09:51:33 +00:00
for i := 0; i < num; i++ {
if width < len([]rune(words[i])) {
width = len([]rune(words[i]))
}
}
2017-07-15 08:37:54 +00:00
2017-07-16 14:11:16 +00:00
if width > max {
width = max
}
2017-07-15 09:51:33 +00:00
for i := 0; i < num; i++ {
2017-07-16 14:11:16 +00:00
if l := len(words[i]); l > width {
new[i] = words[i][:width - 3] + "..."
} else if l < width {
spaces := width - len([]rune(words[i]))
new[i] = words[i]
for j := 0; j < spaces; j++ {
new[i] += " "
}
} else {
new[i] = words[i]
2017-07-15 09:51:33 +00:00
}
}
2017-07-15 14:27:49 +00:00
return
2017-07-14 01:51:19 +00:00
}