found problem with new line and carriage return handiling

This commit is contained in:
Liam Galvin 2018-08-07 21:26:48 +01:00
parent db99bac004
commit 132ce51f78
4 changed files with 159 additions and 157 deletions

View File

@ -211,9 +211,7 @@ func (buffer *Buffer) NewLine() {
if buffer.cursorY == buffer.viewHeight-1 { if buffer.cursorY == buffer.viewHeight-1 {
buffer.lines = append(buffer.lines, newLine()) buffer.lines = append(buffer.lines, newLine())
buffer.cursorX = 0
} else { } else {
buffer.cursorX = 0
buffer.cursorY++ buffer.cursorY++
} }
} }

View File

@ -11,7 +11,7 @@ import (
func TestOffsets(t *testing.T) { func TestOffsets(t *testing.T) {
b := NewBuffer(10, 8, CellAttributes{}) b := NewBuffer(10, 8, CellAttributes{})
test := "hellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\nhellothere\n?" test := "hellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\nhellothere\r\n?"
b.Write([]rune(test)...) b.Write([]rune(test)...)
assert.Equal(t, uint16(10), b.ViewWidth()) assert.Equal(t, uint16(10), b.ViewWidth())
assert.Equal(t, uint16(10), b.Width()) assert.Equal(t, uint16(10), b.Width())
@ -65,11 +65,11 @@ func TestBufferCursorIncrement(t *testing.T) {
require.Equal(t, uint16(0), b.CursorColumn()) require.Equal(t, uint16(0), b.CursorColumn())
require.Equal(t, uint16(3), b.CursorLine()) require.Equal(t, uint16(3), b.CursorLine())
b.Write([]rune("hello\n")...) b.Write([]rune("hello\r\n")...)
b.Write([]rune("hello\n")...) b.Write([]rune("hello\r\n")...)
b.Write([]rune("hello\n")...) b.Write([]rune("hello\r\n")...)
b.Write([]rune("hello\n")...) b.Write([]rune("hello\r\n")...)
b.Write([]rune("hello\n")...) b.Write([]rune("hello\r\n")...)
b.Write([]rune("hello")...) b.Write([]rune("hello")...)
b.SetPosition(0, 2) b.SetPosition(0, 2)
b.incrementCursorPosition() b.incrementCursorPosition()
@ -183,19 +183,19 @@ func TestMovePosition(t *testing.T) {
func TestVisibleLines(t *testing.T) { func TestVisibleLines(t *testing.T) {
b := NewBuffer(80, 10, CellAttributes{}) b := NewBuffer(80, 10, CellAttributes{})
b.Write([]rune("hello 1\n")...) b.Write([]rune("hello 1\r\n")...)
b.Write([]rune("hello 2\n")...) b.Write([]rune("hello 2\r\n")...)
b.Write([]rune("hello 3\n")...) b.Write([]rune("hello 3\r\n")...)
b.Write([]rune("hello 4\n")...) b.Write([]rune("hello 4\r\n")...)
b.Write([]rune("hello 5\n")...) b.Write([]rune("hello 5\r\n")...)
b.Write([]rune("hello 6\n")...) b.Write([]rune("hello 6\r\n")...)
b.Write([]rune("hello 7\n")...) b.Write([]rune("hello 7\r\n")...)
b.Write([]rune("hello 8\n")...) b.Write([]rune("hello 8\r\n")...)
b.Write([]rune("hello 9\n")...) b.Write([]rune("hello 9\r\n")...)
b.Write([]rune("hello 10\n")...) b.Write([]rune("hello 10\r\n")...)
b.Write([]rune("hello 11\n")...) b.Write([]rune("hello 11\r\n")...)
b.Write([]rune("hello 12\n")...) b.Write([]rune("hello 12\r\n")...)
b.Write([]rune("hello 13\n")...) b.Write([]rune("hello 13\r\n")...)
b.Write([]rune("hello 14")...) b.Write([]rune("hello 14")...)
lines := b.GetVisibleLines() lines := b.GetVisibleLines()
@ -207,8 +207,8 @@ func TestVisibleLines(t *testing.T) {
func TestClearWithoutFullView(t *testing.T) { func TestClearWithoutFullView(t *testing.T) {
b := NewBuffer(80, 10, CellAttributes{}) b := NewBuffer(80, 10, CellAttributes{})
b.Write([]rune("hello 1\n")...) b.Write([]rune("hello 1\r\n")...)
b.Write([]rune("hello 2\n")...) b.Write([]rune("hello 2\r\n")...)
b.Write([]rune("hello 3")...) b.Write([]rune("hello 3")...)
b.Clear() b.Clear()
lines := b.GetVisibleLines() lines := b.GetVisibleLines()
@ -219,14 +219,14 @@ func TestClearWithoutFullView(t *testing.T) {
func TestClearWithFullView(t *testing.T) { func TestClearWithFullView(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello 1\n")...) b.Write([]rune("hello 1\r\n")...)
b.Write([]rune("hello 2\n")...) b.Write([]rune("hello 2\r\n")...)
b.Write([]rune("hello 3\n")...) b.Write([]rune("hello 3\r\n")...)
b.Write([]rune("hello 4\n")...) b.Write([]rune("hello 4\r\n")...)
b.Write([]rune("hello 5\n")...) b.Write([]rune("hello 5\r\n")...)
b.Write([]rune("hello 6\n")...) b.Write([]rune("hello 6\r\n")...)
b.Write([]rune("hello 7\n")...) b.Write([]rune("hello 7\r\n")...)
b.Write([]rune("hello 8\n")...) b.Write([]rune("hello 8\r\n")...)
b.Clear() b.Clear()
lines := b.GetVisibleLines() lines := b.GetVisibleLines()
for _, line := range lines { for _, line := range lines {
@ -274,7 +274,7 @@ func TestResizeView(t *testing.T) {
func TestGetCell(t *testing.T) { func TestGetCell(t *testing.T) {
b := NewBuffer(80, 20, CellAttributes{}) b := NewBuffer(80, 20, CellAttributes{})
b.Write([]rune("Hello\nthere\nsomething...")...) b.Write([]rune("Hello\r\nthere\r\nsomething...")...)
cell := b.GetCell(8, 2) cell := b.GetCell(8, 2)
require.NotNil(t, cell) require.NotNil(t, cell)
assert.Equal(t, 'g', cell.Rune()) assert.Equal(t, 'g', cell.Rune())
@ -282,7 +282,7 @@ func TestGetCell(t *testing.T) {
func TestGetCellWithHistory(t *testing.T) { func TestGetCellWithHistory(t *testing.T) {
b := NewBuffer(80, 2, CellAttributes{}) b := NewBuffer(80, 2, CellAttributes{})
b.Write([]rune("Hello\nthere\nsomething...")...) b.Write([]rune("Hello\r\nthere\r\nsomething...")...)
cell := b.GetCell(8, 1) cell := b.GetCell(8, 1)
require.NotNil(t, cell) require.NotNil(t, cell)
assert.Equal(t, 'g', cell.Rune()) assert.Equal(t, 'g', cell.Rune())
@ -290,7 +290,7 @@ func TestGetCellWithHistory(t *testing.T) {
func TestGetCellWithBadCursor(t *testing.T) { func TestGetCellWithBadCursor(t *testing.T) {
b := NewBuffer(80, 2, CellAttributes{}) b := NewBuffer(80, 2, CellAttributes{})
b.Write([]rune("Hello\nthere\nsomething...")...) b.Write([]rune("Hello\r\nthere\r\nsomething...")...)
require.Nil(t, b.GetCell(8, 3)) require.Nil(t, b.GetCell(8, 3))
require.Nil(t, b.GetCell(8, -1)) require.Nil(t, b.GetCell(8, -1))
require.Nil(t, b.GetCell(-8, 1)) require.Nil(t, b.GetCell(-8, 1))
@ -336,7 +336,7 @@ func TestCursorPositionQuerying(t *testing.T) {
func TestRawPositionQuerying(t *testing.T) { func TestRawPositionQuerying(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("a\na\na\na\na\na\na\na\na\na")...) b.Write([]rune("a\r\na\r\na\r\na\r\na\r\na\r\na\r\na\r\na\r\na")...)
b.cursorX = 3 b.cursorX = 3
b.cursorY = 4 b.cursorY = 4
assert.Equal(t, uint64(9), b.RawLine()) assert.Equal(t, uint64(9), b.RawLine())
@ -345,7 +345,7 @@ func TestRawPositionQuerying(t *testing.T) {
// CSI 2 K // CSI 2 K
func TestEraseLine(t *testing.T) { func TestEraseLine(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello, this is a test\nthis line should be deleted")...) b.Write([]rune("hello, this is a test\r\nthis line should be deleted")...)
b.EraseLine() b.EraseLine()
assert.Equal(t, "hello, this is a test", b.lines[0].String()) assert.Equal(t, "hello, this is a test", b.lines[0].String())
assert.Equal(t, "", b.lines[1].String()) assert.Equal(t, "", b.lines[1].String())
@ -354,7 +354,7 @@ func TestEraseLine(t *testing.T) {
// CSI 1 K // CSI 1 K
func TestEraseLineToCursor(t *testing.T) { func TestEraseLineToCursor(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello, this is a test\ndeleted")...) b.Write([]rune("hello, this is a test\r\ndeleted")...)
b.MovePosition(-3, 0) b.MovePosition(-3, 0)
b.EraseLineToCursor() b.EraseLineToCursor()
assert.Equal(t, "hello, this is a test", b.lines[0].String()) assert.Equal(t, "hello, this is a test", b.lines[0].String())
@ -364,7 +364,7 @@ func TestEraseLineToCursor(t *testing.T) {
// CSI 0 K // CSI 0 K
func TestEraseLineAfterCursor(t *testing.T) { func TestEraseLineAfterCursor(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello, this is a test\ndeleted")...) b.Write([]rune("hello, this is a test\r\ndeleted")...)
b.MovePosition(-3, 0) b.MovePosition(-3, 0)
b.EraseLineAfterCursor() b.EraseLineAfterCursor()
assert.Equal(t, "hello, this is a test", b.lines[0].String()) assert.Equal(t, "hello, this is a test", b.lines[0].String())
@ -372,7 +372,7 @@ func TestEraseLineAfterCursor(t *testing.T) {
} }
func TestEraseDisplay(t *testing.T) { func TestEraseDisplay(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello\nasdasd\nthing")...) b.Write([]rune("hello\r\nasdasd\r\nthing")...)
b.MovePosition(2, 1) b.MovePosition(2, 1)
b.EraseDisplay() b.EraseDisplay()
lines := b.GetVisibleLines() lines := b.GetVisibleLines()
@ -382,7 +382,7 @@ func TestEraseDisplay(t *testing.T) {
} }
func TestEraseDisplayToCursor(t *testing.T) { func TestEraseDisplayToCursor(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello\nasdasd\nthing")...) b.Write([]rune("hello\r\nasdasd\r\nthing")...)
b.MovePosition(-2, 0) b.MovePosition(-2, 0)
b.EraseDisplayToCursor() b.EraseDisplayToCursor()
lines := b.GetVisibleLines() lines := b.GetVisibleLines()
@ -394,7 +394,7 @@ func TestEraseDisplayToCursor(t *testing.T) {
func TestEraseDisplayAfterCursor(t *testing.T) { func TestEraseDisplayAfterCursor(t *testing.T) {
b := NewBuffer(80, 5, CellAttributes{}) b := NewBuffer(80, 5, CellAttributes{})
b.Write([]rune("hello\nasdasd\nthings")...) b.Write([]rune("hello\r\nasdasd\r\nthings")...)
b.MovePosition(-3, -1) b.MovePosition(-3, -1)
b.EraseDisplayAfterCursor() b.EraseDisplayAfterCursor()
lines := b.GetVisibleLines() lines := b.GetVisibleLines()

View File

@ -19,6 +19,7 @@ type csiSequenceHandler func(params []string, intermediate string, terminal *Ter
func csiHandler(buffer chan rune, terminal *Terminal) error { func csiHandler(buffer chan rune, terminal *Terminal) error {
var final rune var final rune
var b rune var b rune
var err error
param := "" param := ""
intermediate := "" intermediate := ""
CSI: CSI:
@ -40,134 +41,135 @@ CSI:
handler, ok := csiSequenceMap[final] handler, ok := csiSequenceMap[final]
if ok { if ok {
return handler(params, intermediate, terminal) err = handler(params, intermediate, terminal)
} } else {
switch final { switch final {
case 'A': case 'A':
distance := 1 distance := 1
if len(params) > 0 { if len(params) > 0 {
var err error var err error
distance, err = strconv.Atoi(params[0]) distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, -int16(distance))
case 'B':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, int16(distance))
case 'C':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(int16(distance), 0)
case 'D':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(-int16(distance), 0)
case 'E':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, int16(distance))
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
case 'F':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, -int16(distance))
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
case 'G':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil || params[0] == "" {
distance = 1
}
}
terminal.buffer.SetPosition(uint16(distance-1), terminal.buffer.CursorLine())
case 'H', 'f':
x, y := 1, 1
if len(params) == 2 {
var err error
if params[0] != "" {
y, err = strconv.Atoi(string(params[0]))
if err != nil { if err != nil {
y = 1 distance = 1
} }
} }
if params[1] != "" { terminal.buffer.MovePosition(0, -int16(distance))
x, err = strconv.Atoi(string(params[1])) case 'B':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil { if err != nil {
x = 1 distance = 1
} }
} }
}
terminal.buffer.SetPosition(uint16(x-1), uint16(y-1)) terminal.buffer.MovePosition(0, int16(distance))
case 'C':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(int16(distance), 0)
case 'D':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(-int16(distance), 0)
case 'E':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, int16(distance))
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
case 'F':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.buffer.MovePosition(0, -int16(distance))
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
case 'G':
distance := 1
if len(params) > 0 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil || params[0] == "" {
distance = 1
}
}
terminal.buffer.SetPosition(uint16(distance-1), terminal.buffer.CursorLine())
case 'H', 'f':
x, y := 1, 1
if len(params) == 2 {
var err error
if params[0] != "" {
y, err = strconv.Atoi(string(params[0]))
if err != nil {
y = 1
}
}
if params[1] != "" {
x, err = strconv.Atoi(string(params[1]))
if err != nil {
x = 1
}
}
}
terminal.buffer.SetPosition(uint16(x-1), uint16(y-1))
default:
switch param + intermediate + string(final) {
case "?25h":
terminal.buffer.ShowCursor()
case "?25l":
terminal.buffer.HideCursor()
case "?12h":
terminal.buffer.SetCursorBlink(true)
case "?12l":
terminal.buffer.SetCursorBlink(false)
default: default:
return fmt.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final)) switch param + intermediate + string(final) {
} case "?25h":
terminal.buffer.ShowCursor()
case "?25l":
terminal.buffer.HideCursor()
case "?12h":
terminal.buffer.SetCursorBlink(true)
case "?12l":
terminal.buffer.SetCursorBlink(false)
default:
err = fmt.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
}
}
} }
//terminal.logger.Debugf("Received CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final)) terminal.logger.Debugf("Received CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
return nil return err
} }
func csiDeleteHandler(params []string, intermediate string, terminal *Terminal) error { func csiDeleteHandler(params []string, intermediate string, terminal *Terminal) error {

View File

@ -38,6 +38,8 @@ func (terminal *Terminal) processInput(ctx context.Context, buffer chan rune) {
continue continue
} }
terminal.logger.Debugf("Received character 0x%X: %s", b, string(b))
switch b { switch b {
case 0x0a: case 0x0a:
terminal.buffer.NewLine() terminal.buffer.NewLine()