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
60
runebuf.go
60
runebuf.go
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
23
utils.go
23
utils.go
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue