Consider terminal screen size

This commit is contained in:
c-bata 2017-07-16 01:04:18 +09:00
parent 97bc3aed07
commit e8a654ce06
3 changed files with 50 additions and 6 deletions

27
main.go
View File

@ -15,7 +15,32 @@ func completer(b *prompt.Buffer) []string {
if w := b.Document().GetWordBeforeCursor(); w == "" {
return []string{}
} else {
return []string{"select", "from", "insert", "where"}
if []rune(w)[0] == []rune("s")[0] {
return []string{"select"}
} else if []rune(w)[0] == []rune("w")[0] {
return []string{"where"}
} else if []rune(w)[0] == []rune("d")[0] {
return []string{"drop", "delete"}
} else if []rune(w)[0] == []rune("f")[0] {
return []string{"from"}
}
}
return []string{
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
"select",
}
}

View File

@ -76,6 +76,9 @@ func (p *Prompt) Run() {
p.renderer.Render(p.buf, completions, p.chosen)
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)
case e := <-exitCh:
if e {
return
@ -89,6 +92,7 @@ func (p *Prompt) Run() {
func (p *Prompt) setUp() {
p.in.Setup()
p.renderer.Setup()
p.renderer.UpdateWinSize(p.in.GetWinSize())
}
func (p *Prompt) tearDown() {
@ -143,7 +147,7 @@ func handleSignals(in *VT100Parser, exitCh chan bool, winSizeCh chan *WinSize) {
}
}
func NewPrompt(executor Executor, completer Completer, maxCompletions uint8) *Prompt {
func NewPrompt(executor Executor, completer Completer, maxCompletions uint16) *Prompt {
return &Prompt{
in: NewVT100Parser(),
renderer: &Render{

View File

@ -6,7 +6,7 @@ type Render struct {
out *VT100Writer
row uint16
col uint16 // sigwinchで送られてくる列数を常に見ながら、prefixのlengthとbufferのcursor positionを比べて、completionの表示位置をずらす
maxCompletions uint8
maxCompletions uint16
}
func (r *Render) Setup() {
@ -39,14 +39,26 @@ func (r *Render) UpdateWinSize(ws *WinSize) {
return
}
func (r *Render) RenderCompletion(words []string, chosen int) {
if len(words) == 0 {
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)
@ -60,6 +72,9 @@ func (r *Render) RenderCompletion(words []string, chosen int) {
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")
@ -79,7 +94,7 @@ 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(completions, chosen)
r.renderCompletion(buffer, completions, chosen)
if chosen != -1 {
c := completions[chosen]
r.out.CursorBackward(len([]rune(buffer.Document().GetWordBeforeCursor())))