forked from mirror/readline
Merge pull request #42 from chzyer/bugfix/use_single_again
Fix breaking scroll buffer
This commit is contained in:
commit
91ba4d48f0
64
runebuf.go
64
runebuf.go
|
@ -3,7 +3,6 @@ package readline
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
|
@ -31,17 +30,7 @@ type RuneBuffer struct {
|
|||
}
|
||||
|
||||
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.print()
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) Backup() {
|
||||
|
@ -348,8 +337,20 @@ func (r *RuneBuffer) MoveTo(ch rune, prevChar, reverse bool) (success bool) {
|
|||
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 {
|
||||
sp := SplitByLine(r.PromptLen(), width, r.buf[:r.idx])
|
||||
sp := r.getSplitByLine(r.buf[:r.idx])
|
||||
return len(sp) - 1
|
||||
}
|
||||
|
||||
|
@ -391,39 +392,14 @@ func (r *RuneBuffer) output() []byte {
|
|||
}
|
||||
|
||||
} else {
|
||||
sp := SplitByLine(r.PromptLen(), r.width, r.buf)
|
||||
written := 0
|
||||
idxInLine := 0
|
||||
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)
|
||||
buf.Write([]byte(string(r.buf)))
|
||||
if r.isInLineEdge() {
|
||||
buf.Write([]byte(" \b"))
|
||||
}
|
||||
}
|
||||
|
||||
if idx < len(sp)-1 && !isWindows {
|
||||
buf.Write([]byte{'\n'})
|
||||
}
|
||||
}
|
||||
if len(r.buf) > r.idx {
|
||||
targetLine := r.IdxLine(r.width)
|
||||
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,
|
||||
))
|
||||
}
|
||||
}
|
||||
if len(r.buf) > r.idx {
|
||||
buf.Write(runes.Backspace(r.buf[r.idx:]))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
|
23
utils.go
23
utils.go
|
@ -86,29 +86,6 @@ func escapeKey(r rune) rune {
|
|||
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 {
|
||||
var ret []string
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
|
|
@ -1,15 +1 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue