Skip to content

Commit

Permalink
feat: improve rendering performance on windows (c-bata#47)
Browse files Browse the repository at this point in the history
* feat: to ignore the codepoint 0

* feat: hide cursor whole rendering phase

* feat: change EraseDown timing

* feat: add sleep

* feat: to async Read on windows

* style: goimports

* refactor: use defer

* feat: remove ignore flush

* chore: remove ignore output
  • Loading branch information
orisano authored and c-bata committed Feb 18, 2018
1 parent 4dbd0dc commit c618654
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
4 changes: 2 additions & 2 deletions prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,16 +237,16 @@ func (p *Prompt) Input() string {
func (p *Prompt) readBuffer(bufCh chan []byte, stopCh chan struct{}) {
log.Printf("[INFO] readBuffer start")
for {
time.Sleep(10 * time.Millisecond)
select {
case <-stopCh:
log.Print("[INFO] stop readBuffer")
return
default:
if b, err := p.in.Read(); err == nil {
if b, err := p.in.Read(); err == nil && !(len(b) == 1 && b[0] == 0) {
bufCh <- b
}
}
time.Sleep(10 * time.Millisecond)
}
}

Expand Down
18 changes: 11 additions & 7 deletions render.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package prompt

import "runtime"
import (
"runtime"
)

// Render to render prompt information from state of Buffer.
type Render struct {
Expand Down Expand Up @@ -172,9 +174,7 @@ func (r *Render) Render(buffer *Buffer, completion *CompletionManager) {
if r.col == 0 {
return
}

// Erasing
r.clear(r.previousCursor)
r.backward(r.previousCursor, r.previousCursor)

line := buffer.Text()
prefix := r.getCurrentPrefix()
Expand All @@ -189,13 +189,20 @@ func (r *Render) Render(buffer *Buffer, completion *CompletionManager) {
return
}

defer r.out.Flush()

// Rendering
r.out.HideCursor()
defer r.out.ShowCursor()

r.renderPrefix()
r.out.SetColor(r.inputTextColor, r.inputBGColor, false)
r.out.WriteStr(line)
r.out.SetColor(DefaultColor, DefaultColor, false)
r.lineWrap(cursor)

r.out.EraseDown()

cursor = r.backward(cursor, len(line)-buffer.CursorPosition)

r.renderCompletion(buffer, completion)
Expand All @@ -209,9 +216,6 @@ func (r *Render) Render(buffer *Buffer, completion *CompletionManager) {
cursor += len(suggest.Text)
r.lineWrap(cursor)
}

r.out.Flush()

r.previousCursor = cursor
}

Expand Down
21 changes: 19 additions & 2 deletions windows_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ package prompt

import (
"bytes"
"errors"
"syscall"
"unicode/utf8"
"unsafe"

"github.com/mattn/go-tty"
)

const maxReadBytes = 1024

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

var procGetNumberOfConsoleInputEvents = kernel32.NewProc("GetNumberOfConsoleInputEvents")

// WindowsParser is a ConsoleParser implementation for Win32 console.
type WindowsParser struct {
tty *tty.TTY
Expand Down Expand Up @@ -43,11 +50,21 @@ func (p *WindowsParser) GetKey(b []byte) Key {

// Read returns byte array.
func (p *WindowsParser) Read() ([]byte, error) {
buf := make([]byte, maxReadBytes)
var ev uint32
r0, _, err := procGetNumberOfConsoleInputEvents.Call(p.tty.Input().Fd(), uintptr(unsafe.Pointer(&ev)))
if r0 == 0 {
return nil, err
}
if ev == 0 {
return nil, errors.New("EAGAIN")
}

r, err := p.tty.ReadRune()
if err != nil {
return []byte{}, err
return nil, err
}

buf := make([]byte, maxReadBytes)
n := utf8.EncodeRune(buf[:], r)
for p.tty.Buffered() && n < maxReadBytes {
r, err := p.tty.ReadRune()
Expand Down
3 changes: 0 additions & 3 deletions windows_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ type WindowsWriter struct {
// WriteRaw to write raw byte array
func (w *WindowsWriter) WriteRaw(data []byte) {
w.buffer = append(w.buffer, data...)
// Flush because sometimes the render is broken when a large amount data in buffer.
w.Flush()
return
}

Expand Down Expand Up @@ -257,7 +255,6 @@ func (w *WindowsWriter) SetColor(fg, bg Color, bold bool) {
if !ok {
b, _ = backgroundANSIColors[DefaultColor]
}
w.out.Write([]byte{0x1b, 0x5b, 0x33, 0x39, 0x3b, 0x34, 0x39, 0x6d})
w.WriteRaw([]byte{0x1b, 0x5b})
if !bold {
w.WriteRaw([]byte{0x30, 0x3b})
Expand Down

0 comments on commit c618654

Please sign in to comment.