mirror of https://github.com/liamg/aminal.git
buffer is getting pretty solid
This commit is contained in:
parent
9ac2e9cba0
commit
11b4a2e487
163
buffer/buffer.go
163
buffer/buffer.go
|
@ -115,12 +115,6 @@ func (buffer *Buffer) ViewHeight() uint16 {
|
||||||
return buffer.viewHeight
|
return buffer.viewHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) ensureLinesExistToRawHeight() {
|
|
||||||
for int(buffer.RawLine()) >= len(buffer.lines) {
|
|
||||||
buffer.lines = append(buffer.lines, newLine())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write will write a rune to the terminal at the position of the cursor, and increment the cursor position
|
// Write will write a rune to the terminal at the position of the cursor, and increment the cursor position
|
||||||
func (buffer *Buffer) Write(runes ...rune) {
|
func (buffer *Buffer) Write(runes ...rune) {
|
||||||
for _, r := range runes {
|
for _, r := range runes {
|
||||||
|
@ -131,14 +125,44 @@ func (buffer *Buffer) Write(runes ...rune) {
|
||||||
buffer.CarriageReturn()
|
buffer.CarriageReturn()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buffer.ensureLinesExistToRawHeight()
|
line := buffer.getCurrentLine()
|
||||||
line := &buffer.lines[buffer.RawLine()]
|
|
||||||
for int(buffer.CursorColumn()) >= len(line.cells) {
|
if buffer.CursorColumn() >= buffer.Width() { // if we're after the line, move to next
|
||||||
line.cells = append(line.cells, newCell())
|
buffer.cursorX = 0
|
||||||
|
|
||||||
|
if buffer.cursorY >= buffer.ViewHeight()-1 {
|
||||||
|
buffer.lines = append(buffer.lines, newLine())
|
||||||
|
} else {
|
||||||
|
buffer.cursorY++
|
||||||
|
}
|
||||||
|
|
||||||
|
//if int(buffer.RawLine()) >= len(buffer.lines) { // if we need to create a new line, set it to wrapped and write to it
|
||||||
|
|
||||||
|
newLine := buffer.getCurrentLine()
|
||||||
|
newLine.setWrapped(true)
|
||||||
|
if len(newLine.cells) == 0 {
|
||||||
|
newLine.cells = []Cell{Cell{}}
|
||||||
|
}
|
||||||
|
cell := &newLine.cells[buffer.CursorColumn()]
|
||||||
|
cell.setRune(r)
|
||||||
|
cell.attr = buffer.cursorAttr
|
||||||
|
//} else {
|
||||||
|
//newLine := &buffer.lines[buffer.RawLine()]
|
||||||
|
//}
|
||||||
|
|
||||||
|
// @todo if next line is wrapped then prepend to it and shuffle characters along line, wrapping to next if necessary
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for int(buffer.CursorColumn()) >= len(line.cells) {
|
||||||
|
line.cells = append(line.cells, newCell())
|
||||||
|
}
|
||||||
|
|
||||||
|
cell := &line.cells[buffer.CursorColumn()]
|
||||||
|
cell.setRune(r)
|
||||||
|
cell.attr = buffer.cursorAttr
|
||||||
|
|
||||||
}
|
}
|
||||||
cell := &line.cells[buffer.CursorColumn()]
|
|
||||||
cell.setRune(r)
|
|
||||||
cell.attr = buffer.cursorAttr
|
|
||||||
buffer.incrementCursorPosition()
|
buffer.incrementCursorPosition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,78 +171,30 @@ func (buffer *Buffer) incrementCursorPosition() {
|
||||||
|
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
|
|
||||||
if buffer.CursorColumn()+1 < buffer.Width() { // if not at end of line
|
// we can increment one column past the end of the line.
|
||||||
|
// this is effectively the beginning of the next line, except when we \r etc.
|
||||||
|
if buffer.CursorColumn() < buffer.Width() { // if not at end of line
|
||||||
|
|
||||||
buffer.cursorX++
|
buffer.cursorX++
|
||||||
|
|
||||||
} else { // we're at the end of the current line
|
} else {
|
||||||
|
panic("bad")
|
||||||
if buffer.cursorY == buffer.viewHeight-1 {
|
|
||||||
// if we're on the last line, we can't move the cursor down, we have to move the buffer up, i.e. add a new line
|
|
||||||
|
|
||||||
line := newLine()
|
|
||||||
line.setWrapped(true)
|
|
||||||
buffer.lines = append(buffer.lines, line)
|
|
||||||
buffer.cursorX = 0
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// if we're not on the bottom line...
|
|
||||||
|
|
||||||
buffer.cursorX = 0
|
|
||||||
buffer.cursorY++
|
|
||||||
|
|
||||||
rawLine := int(buffer.RawLine())
|
|
||||||
|
|
||||||
line := newLine()
|
|
||||||
line.setWrapped(true)
|
|
||||||
buffer.lines = append(append(buffer.lines[:rawLine], line), buffer.lines[rawLine:]...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) CarriageReturn() {
|
func (buffer *Buffer) CarriageReturn() {
|
||||||
|
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
|
buffer.cursorX = 0
|
||||||
line, err := buffer.getCurrentLine()
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
fmt.Println("Failed to get new line during carriage return")
|
|
||||||
|
|
||||||
buffer.cursorX = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer.cursorX == 0 && line.wrapped {
|
|
||||||
if len(line.cells) == 0 {
|
|
||||||
rawLine := int(buffer.RawLine())
|
|
||||||
buffer.lines = append(buffer.lines[:rawLine], buffer.lines[rawLine+1:]...)
|
|
||||||
}
|
|
||||||
buffer.cursorY--
|
|
||||||
} else {
|
|
||||||
buffer.cursorX = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) NewLine() {
|
func (buffer *Buffer) NewLine() {
|
||||||
|
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
|
if buffer.cursorY >= buffer.ViewHeight()-1 {
|
||||||
// if we're at the beginning of a line which wrapped from the previous one, and we need a new line, we can effectively not add a new line, and set the current one to non-wrapped
|
|
||||||
if buffer.cursorX == 0 {
|
|
||||||
line, err := buffer.getCurrentLine()
|
|
||||||
if err == nil && line != nil && line.wrapped {
|
|
||||||
line.setWrapped(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer.cursorY == buffer.viewHeight-1 {
|
|
||||||
buffer.ensureLinesExistToRawHeight()
|
|
||||||
buffer.lines = append(buffer.lines, newLine())
|
buffer.lines = append(buffer.lines, newLine())
|
||||||
} else {
|
} else {
|
||||||
buffer.cursorY++
|
buffer.cursorY++
|
||||||
}
|
}
|
||||||
|
buffer.cursorX = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) MovePosition(x int16, y int16) {
|
func (buffer *Buffer) MovePosition(x int16, y int16) {
|
||||||
|
@ -287,30 +263,36 @@ func (buffer *Buffer) Clear() {
|
||||||
buffer.SetPosition(0, 0) // do we need to set position?
|
buffer.SetPosition(0, 0) // do we need to set position?
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) getCurrentLine() (*Line, error) {
|
// creates if necessary
|
||||||
|
func (buffer *Buffer) getCurrentLine() *Line {
|
||||||
|
|
||||||
if int(buffer.RawLine()) < len(buffer.lines) {
|
if buffer.cursorY >= buffer.ViewHeight() {
|
||||||
return &buffer.lines[buffer.RawLine()], nil
|
panic(fmt.Sprintf("cursor is outside of view: %d %d", buffer.cursorX, buffer.cursorY))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("Line %d does not exist", buffer.cursorY)
|
if len(buffer.lines) < int(buffer.ViewHeight()) {
|
||||||
|
for int(buffer.cursorY) >= len(buffer.lines) {
|
||||||
|
buffer.lines = append(buffer.lines, newLine())
|
||||||
|
}
|
||||||
|
return &buffer.lines[int(buffer.cursorY)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(buffer.RawLine()) < len(buffer.lines) {
|
||||||
|
return &buffer.lines[buffer.RawLine()]
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("Failed to retrieve line for %d %d", buffer.cursorX, buffer.cursorY))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) EraseLine() {
|
func (buffer *Buffer) EraseLine() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
line, err := buffer.getCurrentLine()
|
line := buffer.getCurrentLine()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
line.cells = []Cell{}
|
line.cells = []Cell{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) EraseLineToCursor() {
|
func (buffer *Buffer) EraseLineToCursor() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
line, err := buffer.getCurrentLine()
|
line := buffer.getCurrentLine()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 0; i <= int(buffer.cursorX); i++ {
|
for i := 0; i <= int(buffer.cursorX); i++ {
|
||||||
if i < len(line.cells) {
|
if i < len(line.cells) {
|
||||||
line.cells[i].erase()
|
line.cells[i].erase()
|
||||||
|
@ -320,10 +302,7 @@ func (buffer *Buffer) EraseLineToCursor() {
|
||||||
|
|
||||||
func (buffer *Buffer) EraseLineFromCursor() {
|
func (buffer *Buffer) EraseLineFromCursor() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
line, err := buffer.getCurrentLine()
|
line := buffer.getCurrentLine()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if line.wrapped && buffer.cursorX == 0 {
|
if line.wrapped && buffer.cursorX == 0 {
|
||||||
//panic("wtf")
|
//panic("wtf")
|
||||||
|
@ -335,8 +314,6 @@ func (buffer *Buffer) EraseLineFromCursor() {
|
||||||
max = len(line.cells)
|
max = len(line.cells)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Erase line from cursor, cursor is at %d\n", buffer.cursorX)
|
|
||||||
|
|
||||||
for c := int(buffer.cursorX); c < len(line.cells); c++ {
|
for c := int(buffer.cursorX); c < len(line.cells); c++ {
|
||||||
line.cells[c].erase()
|
line.cells[c].erase()
|
||||||
}
|
}
|
||||||
|
@ -354,10 +331,8 @@ func (buffer *Buffer) EraseDisplay() {
|
||||||
|
|
||||||
func (buffer *Buffer) EraseDisplayFromCursor() {
|
func (buffer *Buffer) EraseDisplayFromCursor() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
line, err := buffer.getCurrentLine()
|
line := buffer.getCurrentLine()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
line.cells = line.cells[:buffer.cursorX]
|
line.cells = line.cells[:buffer.cursorX]
|
||||||
for i := buffer.cursorY + 1; i < buffer.ViewHeight(); i++ {
|
for i := buffer.cursorY + 1; i < buffer.ViewHeight(); i++ {
|
||||||
rawLine := buffer.convertViewLineToRawLine(i)
|
rawLine := buffer.convertViewLineToRawLine(i)
|
||||||
|
@ -369,10 +344,8 @@ func (buffer *Buffer) EraseDisplayFromCursor() {
|
||||||
|
|
||||||
func (buffer *Buffer) EraseDisplayToCursor() {
|
func (buffer *Buffer) EraseDisplayToCursor() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
line, err := buffer.getCurrentLine()
|
line := buffer.getCurrentLine()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 0; i < int(buffer.cursorX); i++ {
|
for i := 0; i < int(buffer.cursorX); i++ {
|
||||||
line.cells[i].erase()
|
line.cells[i].erase()
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,99 +31,74 @@ func TestBufferCreation(t *testing.T) {
|
||||||
assert.NotNil(t, b.lines)
|
assert.NotNil(t, b.lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBufferCursorIncrement(t *testing.T) {
|
func TestBufferWriteIncrementsCursorCorrectly(t *testing.T) {
|
||||||
|
|
||||||
b := NewBuffer(5, 4, CellAttributes{})
|
b := NewBuffer(5, 4, CellAttributes{})
|
||||||
b.incrementCursorPosition()
|
|
||||||
|
/*01234
|
||||||
|
|-----
|
||||||
|
0|xxxxx
|
||||||
|
1|
|
||||||
|
2|
|
||||||
|
3|
|
||||||
|
|-----
|
||||||
|
*/
|
||||||
|
|
||||||
|
b.Write('x')
|
||||||
require.Equal(t, uint16(1), b.CursorColumn())
|
require.Equal(t, uint16(1), b.CursorColumn())
|
||||||
require.Equal(t, uint16(0), b.CursorLine())
|
require.Equal(t, uint16(0), b.CursorLine())
|
||||||
|
|
||||||
b.incrementCursorPosition()
|
b.Write('x')
|
||||||
require.Equal(t, uint16(2), b.CursorColumn())
|
require.Equal(t, uint16(2), b.CursorColumn())
|
||||||
require.Equal(t, uint16(0), b.CursorLine())
|
require.Equal(t, uint16(0), b.CursorLine())
|
||||||
|
|
||||||
b.incrementCursorPosition()
|
b.Write('x')
|
||||||
require.Equal(t, uint16(3), b.CursorColumn())
|
require.Equal(t, uint16(3), b.CursorColumn())
|
||||||
require.Equal(t, uint16(0), b.CursorLine())
|
require.Equal(t, uint16(0), b.CursorLine())
|
||||||
|
|
||||||
b.incrementCursorPosition()
|
b.Write('x')
|
||||||
require.Equal(t, uint16(4), b.CursorColumn())
|
require.Equal(t, uint16(4), b.CursorColumn())
|
||||||
require.Equal(t, uint16(0), b.CursorLine())
|
require.Equal(t, uint16(0), b.CursorLine())
|
||||||
|
|
||||||
b.incrementCursorPosition()
|
b.Write('x')
|
||||||
require.Equal(t, uint16(0), b.CursorColumn())
|
require.Equal(t, uint16(5), b.CursorColumn())
|
||||||
|
require.Equal(t, uint16(0), b.CursorLine())
|
||||||
|
|
||||||
|
b.Write('x')
|
||||||
|
require.Equal(t, uint16(1), b.CursorColumn())
|
||||||
require.Equal(t, uint16(1), b.CursorLine())
|
require.Equal(t, uint16(1), b.CursorLine())
|
||||||
|
|
||||||
b.incrementCursorPosition()
|
b.Write('x')
|
||||||
b.incrementCursorPosition()
|
require.Equal(t, uint16(2), b.CursorColumn())
|
||||||
b.incrementCursorPosition()
|
require.Equal(t, uint16(1), b.CursorLine())
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
|
|
||||||
require.Equal(t, uint16(0), b.CursorColumn())
|
lines := b.GetVisibleLines()
|
||||||
require.Equal(t, uint16(3), b.CursorLine())
|
require.Equal(t, 2, len(lines))
|
||||||
|
assert.Equal(t, "xxxxx", lines[0].String())
|
||||||
b.Write([]rune("hello\r\n")...)
|
assert.Equal(t, "xx", lines[1].String())
|
||||||
b.Write([]rune("hello\r\n")...)
|
|
||||||
b.Write([]rune("hello\r\n")...)
|
|
||||||
b.Write([]rune("hello\r\n")...)
|
|
||||||
b.Write([]rune("hello\r\n")...)
|
|
||||||
b.Write([]rune("hello")...)
|
|
||||||
b.SetPosition(0, 2)
|
|
||||||
b.incrementCursorPosition()
|
|
||||||
|
|
||||||
}
|
|
||||||
func TestBufferWrite(t *testing.T) {
|
|
||||||
|
|
||||||
b := NewBuffer(5, 20, CellAttributes{})
|
|
||||||
|
|
||||||
assert.Equal(t, uint16(0), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(0), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('a')
|
|
||||||
assert.Equal(t, uint16(1), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(0), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('b')
|
|
||||||
assert.Equal(t, uint16(2), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(0), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('c')
|
|
||||||
assert.Equal(t, uint16(3), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(0), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('d')
|
|
||||||
assert.Equal(t, uint16(4), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(0), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('e')
|
|
||||||
assert.Equal(t, uint16(0), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(1), b.CursorLine())
|
|
||||||
|
|
||||||
b.Write('f')
|
|
||||||
assert.Equal(t, uint16(1), b.CursorColumn())
|
|
||||||
assert.Equal(t, uint16(1), b.CursorLine())
|
|
||||||
|
|
||||||
//b.lines[0].cells[]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWritingNewLineAsFirstRuneOnWrappedLine(t *testing.T) {
|
func TestWritingNewLineAsFirstRuneOnWrappedLine(t *testing.T) {
|
||||||
b := NewBuffer(3, 20, CellAttributes{})
|
b := NewBuffer(3, 20, CellAttributes{})
|
||||||
b.Write('a', 'b', 'c')
|
b.Write('a', 'b', 'c')
|
||||||
assert.Equal(t, uint16(0), b.cursorX)
|
assert.Equal(t, uint16(3), b.cursorX)
|
||||||
|
assert.Equal(t, uint16(0), b.cursorY)
|
||||||
b.Write(0x0a)
|
b.Write(0x0a)
|
||||||
|
assert.Equal(t, uint16(0), b.cursorX)
|
||||||
|
assert.Equal(t, uint16(1), b.cursorY)
|
||||||
|
|
||||||
b.Write('d', 'e', 'f')
|
b.Write('d', 'e', 'f')
|
||||||
|
assert.Equal(t, uint16(3), b.cursorX)
|
||||||
|
assert.Equal(t, uint16(1), b.cursorY)
|
||||||
b.Write(0x0a)
|
b.Write(0x0a)
|
||||||
|
|
||||||
|
assert.Equal(t, uint16(0), b.cursorX)
|
||||||
|
assert.Equal(t, uint16(2), b.cursorY)
|
||||||
|
|
||||||
|
require.Equal(t, 2, len(b.lines))
|
||||||
assert.Equal(t, "abc", b.lines[0].String())
|
assert.Equal(t, "abc", b.lines[0].String())
|
||||||
assert.Equal(t, "def", b.lines[1].String())
|
assert.Equal(t, "def", b.lines[1].String())
|
||||||
assert.Equal(t, "", b.lines[2].String())
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +107,7 @@ func TestWritingNewLineAsSecondRuneOnWrappedLine(t *testing.T) {
|
||||||
/*
|
/*
|
||||||
|abc
|
|abc
|
||||||
|d
|
|d
|
||||||
|_ef
|
|ef
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
|z
|
|z
|
||||||
|
@ -148,7 +123,7 @@ func TestWritingNewLineAsSecondRuneOnWrappedLine(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, "abc", b.lines[0].String())
|
assert.Equal(t, "abc", b.lines[0].String())
|
||||||
assert.Equal(t, "d", b.lines[1].String())
|
assert.Equal(t, "d", b.lines[1].String())
|
||||||
assert.Equal(t, "\x00ef", b.lines[2].String())
|
assert.Equal(t, "ef", b.lines[2].String())
|
||||||
assert.Equal(t, "", b.lines[3].String())
|
assert.Equal(t, "", b.lines[3].String())
|
||||||
assert.Equal(t, "", b.lines[4].String())
|
assert.Equal(t, "", b.lines[4].String())
|
||||||
assert.Equal(t, "z", b.lines[5].String())
|
assert.Equal(t, "z", b.lines[5].String())
|
||||||
|
@ -261,14 +236,28 @@ func TestCarriageReturnOnWrappedLine(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCarriageReturnOnOverWrappedLine(t *testing.T) {
|
func TestCarriageReturnOnOverWrappedLine(t *testing.T) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|hello
|
||||||
|
|secret
|
||||||
|
| sauce
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
b := NewBuffer(6, 10, CellAttributes{})
|
b := NewBuffer(6, 10, CellAttributes{})
|
||||||
b.Write([]rune("hello there!\rsecret sauce")...)
|
b.Write([]rune("hello there!\rsecret sauce")...)
|
||||||
lines := b.GetVisibleLines()
|
lines := b.GetVisibleLines()
|
||||||
require.Equal(t, 4, len(lines))
|
require.Equal(t, 3, len(lines))
|
||||||
assert.Equal(t, "hello ", lines[0].String())
|
assert.Equal(t, "hello ", lines[0].String())
|
||||||
assert.Equal(t, "secret", lines[1].String())
|
assert.Equal(t, "secret", lines[1].String())
|
||||||
|
assert.True(t, b.lines[1].wrapped)
|
||||||
assert.Equal(t, " sauce", lines[2].String())
|
assert.Equal(t, " sauce", lines[2].String())
|
||||||
assert.Equal(t, "", lines[3].String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCarriageReturnOnLineThatDoesntExist(t *testing.T) {
|
func TestCarriageReturnOnLineThatDoesntExist(t *testing.T) {
|
||||||
|
@ -380,7 +369,7 @@ func TestEraseLineAfterCursor(t *testing.T) {
|
||||||
b.MovePosition(-3, 0)
|
b.MovePosition(-3, 0)
|
||||||
b.EraseLineFromCursor()
|
b.EraseLineFromCursor()
|
||||||
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, "dele", b.lines[1].String())
|
assert.Equal(t, "dele\x00\x00\x00", b.lines[1].String())
|
||||||
}
|
}
|
||||||
func TestEraseDisplay(t *testing.T) {
|
func TestEraseDisplay(t *testing.T) {
|
||||||
b := NewBuffer(80, 5, CellAttributes{})
|
b := NewBuffer(80, 5, CellAttributes{})
|
||||||
|
|
|
@ -186,7 +186,7 @@ func (gui *GUI) Render() error {
|
||||||
gui.font.SetColor(1, 0.5, 0.5, 0.5)
|
gui.font.SetColor(1, 0.5, 0.5, 0.5)
|
||||||
fpsData := ""
|
fpsData := ""
|
||||||
if gui.config.Rendering.AlwaysRepaint {
|
if gui.config.Rendering.AlwaysRepaint {
|
||||||
fpsData = fmt.Sprintf("%d FPS", fps)
|
fpsData = fmt.Sprintf("%d FPS | %d,%d", fps, gui.terminal.GetLogicalCursorX(), gui.terminal.GetLogicalCursorY())
|
||||||
}
|
}
|
||||||
gui.font.Print(10, float32(gui.height-20), 1.5, fmt.Sprintf("%s", fpsData))
|
gui.font.Print(10, float32(gui.height-20), 1.5, fmt.Sprintf("%s", fpsData))
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (terminal *Terminal) processInput(ctx context.Context, buffer chan rune) {
|
||||||
// backspace
|
// backspace
|
||||||
terminal.buffer.MovePosition(-1, 0)
|
terminal.buffer.MovePosition(-1, 0)
|
||||||
case 0x07:
|
case 0x07:
|
||||||
// @todo ring bell
|
// @todo ring bell - flash red or some shit?
|
||||||
default:
|
default:
|
||||||
// render character at current location
|
// render character at current location
|
||||||
// fmt.Printf("%s\n", string([]byte{b}))
|
// fmt.Printf("%s\n", string([]byte{b}))
|
||||||
|
|
|
@ -76,6 +76,22 @@ func (terminal *Terminal) emitTitleChange() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (terminal *Terminal) GetLogicalCursorX() uint16 {
|
||||||
|
if terminal.buffer.CursorColumn() >= terminal.buffer.Width() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return terminal.buffer.CursorColumn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (terminal *Terminal) GetLogicalCursorY() uint16 {
|
||||||
|
if terminal.buffer.CursorColumn() >= terminal.buffer.Width() {
|
||||||
|
return terminal.buffer.CursorLine() + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return terminal.buffer.CursorLine()
|
||||||
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetTitle() string {
|
func (terminal *Terminal) GetTitle() string {
|
||||||
return terminal.title
|
return terminal.title
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue