Merge pull request #42 from chzyer/bugfix/use_single_again

Fix breaking scroll buffer
This commit is contained in:
chzyer 2016-03-31 08:06:24 +08:00
commit 91ba4d48f0
3 changed files with 20 additions and 81 deletions

View File

@ -3,7 +3,6 @@ package readline
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"fmt"
"io" "io"
"strings" "strings"
@ -31,17 +30,7 @@ type RuneBuffer struct {
} }
func (r *RuneBuffer) OnWidthChange(newWidth int) { func (r *RuneBuffer) OnWidthChange(newWidth int) {
oldWidth := r.width
if newWidth < oldWidth {
sp := SplitByMultiLine(
r.PromptLen(), oldWidth, newWidth, r.buf[:r.idx])
idxLine := len(sp) - 1
r.clean(idxLine)
} else {
r.Clean()
}
r.width = newWidth r.width = newWidth
r.print()
} }
func (r *RuneBuffer) Backup() { func (r *RuneBuffer) Backup() {
@ -348,8 +337,20 @@ func (r *RuneBuffer) MoveTo(ch rune, prevChar, reverse bool) (success bool) {
return return
} }
func (r *RuneBuffer) isInLineEdge() bool {
if isWindows {
return false
}
sp := r.getSplitByLine(r.buf)
return len(sp[len(sp)-1]) == 0
}
func (r *RuneBuffer) getSplitByLine(rs []rune) []string {
return SplitByLine(r.PromptLen(), r.width, rs)
}
func (r *RuneBuffer) IdxLine(width int) int { func (r *RuneBuffer) IdxLine(width int) int {
sp := SplitByLine(r.PromptLen(), width, r.buf[:r.idx]) sp := r.getSplitByLine(r.buf[:r.idx])
return len(sp) - 1 return len(sp) - 1
} }
@ -391,39 +392,14 @@ func (r *RuneBuffer) output() []byte {
} }
} else { } else {
sp := SplitByLine(r.PromptLen(), r.width, r.buf) buf.Write([]byte(string(r.buf)))
written := 0 if r.isInLineEdge() {
idxInLine := 0 buf.Write([]byte(" \b"))
for idx, s := range sp { }
buf.Write([]byte(s))
if r.idx > written && r.idx < written+len(s) {
idxInLine = r.idx - written
} }
written += len(s)
if idx < len(sp)-1 && !isWindows {
buf.Write([]byte{'\n'})
}
}
if len(r.buf) > r.idx { if len(r.buf) > r.idx {
targetLine := r.IdxLine(r.width) buf.Write(runes.Backspace(r.buf[r.idx:]))
currentLine := len(sp) - 1
// assert currentLine >= targetLine
if targetLine == 0 {
idxInLine += r.PromptLen()
}
buf.WriteString("\r")
if currentLine > targetLine {
buf.WriteString(fmt.Sprintf(
"\033[%vA", currentLine-targetLine,
))
}
if idxInLine > 0 {
buf.WriteString(fmt.Sprintf(
"\033[%vC", idxInLine,
))
}
}
} }
return buf.Bytes() return buf.Bytes()
} }

View File

@ -86,29 +86,6 @@ func escapeKey(r rune) rune {
return r return r
} }
func SplitByMultiLine(start, oldWidth, newWidth int, rs []rune) []string {
var ret []string
buf := bytes.NewBuffer(nil)
currentWidth := start
for _, r := range rs {
w := runes.Width(r)
currentWidth += w
buf.WriteRune(r)
if currentWidth == newWidth {
ret = append(ret, buf.String())
buf.Reset()
continue
}
if currentWidth >= oldWidth {
ret = append(ret, buf.String())
buf.Reset()
currentWidth = 0
}
}
ret = append(ret, buf.String())
return ret
}
func SplitByLine(start, screenWidth int, rs []rune) []string { func SplitByLine(start, screenWidth int, rs []rune) []string {
var ret []string var ret []string
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)

View File

@ -1,15 +1 @@
package readline package readline
import (
"reflect"
"testing"
)
func TestSplitByMultiLine(t *testing.T) {
rs := []rune("hello!bye!!!!")
expected := []string{"hell", "o!", "bye!", "!!", "!"}
ret := SplitByMultiLine(0, 6, 4, rs)
if !reflect.DeepEqual(ret, expected) {
t.Fatal(ret, expected)
}
}