185 lines
3.6 KiB
Go
185 lines
3.6 KiB
Go
package buffer
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"io"
|
||
|
|
"log/slog"
|
||
|
|
"reflect"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"code.chimeric.al/dwrz/wen/internal/editor/buffer/line"
|
||
|
|
)
|
||
|
|
|
||
|
|
func newTestBuffer(lines ...string) *Buffer {
|
||
|
|
var b = &Buffer{
|
||
|
|
cursor: &Cursor{},
|
||
|
|
lines: make([]*line.Line, 0, len(lines)),
|
||
|
|
log: slog.New(slog.NewTextHandler(io.Discard, nil)),
|
||
|
|
offset: &offset{},
|
||
|
|
}
|
||
|
|
for _, s := range lines {
|
||
|
|
b.lines = append(b.lines, line.New(s))
|
||
|
|
}
|
||
|
|
if len(b.lines) == 0 {
|
||
|
|
b.lines = append(b.lines, &line.Line{})
|
||
|
|
}
|
||
|
|
|
||
|
|
return b
|
||
|
|
}
|
||
|
|
|
||
|
|
func bufferLines(b *Buffer) []string {
|
||
|
|
var out = make([]string, len(b.lines))
|
||
|
|
for i, l := range b.lines {
|
||
|
|
out[i] = l.String()
|
||
|
|
}
|
||
|
|
|
||
|
|
return out
|
||
|
|
}
|
||
|
|
|
||
|
|
type CursorMoveTest struct {
|
||
|
|
lines []string
|
||
|
|
action func(b *Buffer)
|
||
|
|
want Cursor
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCursorMovement(t *testing.T) {
|
||
|
|
var tests = []CursorMoveTest{
|
||
|
|
{
|
||
|
|
lines: []string{"ab", "cd"},
|
||
|
|
action: func(b *Buffer) { b.CursorRight() },
|
||
|
|
want: Cursor{line: 0, index: 1, glyph: 1},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"a", "b"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorRight()
|
||
|
|
b.CursorRight()
|
||
|
|
},
|
||
|
|
want: Cursor{line: 1, index: 0, glyph: 0},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"ab", "cd"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorDown()
|
||
|
|
b.CursorLeft()
|
||
|
|
},
|
||
|
|
want: Cursor{line: 0, index: 2, glyph: 2},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"hello", "hi"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorEnd()
|
||
|
|
b.CursorDown()
|
||
|
|
},
|
||
|
|
want: Cursor{line: 1, index: 2, glyph: 2},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"abc", "世界"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorRight()
|
||
|
|
b.CursorDown()
|
||
|
|
},
|
||
|
|
want: Cursor{line: 1, index: 0, glyph: 0},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"abc", "世界"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorEnd()
|
||
|
|
b.CursorDown()
|
||
|
|
},
|
||
|
|
want: Cursor{line: 1, index: 3, glyph: 2},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for n, test := range tests {
|
||
|
|
b := newTestBuffer(test.lines...)
|
||
|
|
test.action(b)
|
||
|
|
if got := b.Cursor(); got != test.want {
|
||
|
|
t.Errorf(
|
||
|
|
"#%d: expected cursor %+v, but got %+v",
|
||
|
|
n, test.want, got,
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type EditTest struct {
|
||
|
|
lines []string
|
||
|
|
action func(b *Buffer)
|
||
|
|
wantLines []string
|
||
|
|
wantCursor Cursor
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestEdit(t *testing.T) {
|
||
|
|
var tests = []EditTest{
|
||
|
|
{
|
||
|
|
lines: []string{""},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.Insert('a')
|
||
|
|
b.Insert('世')
|
||
|
|
},
|
||
|
|
wantLines: []string{"a世"},
|
||
|
|
wantCursor: Cursor{line: 0, index: 4, glyph: 3},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"hello"},
|
||
|
|
action: func(b *Buffer) { b.Newline() },
|
||
|
|
wantLines: []string{"", "hello"},
|
||
|
|
wantCursor: Cursor{line: 1, index: 0, glyph: 0},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"abcd"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorRight()
|
||
|
|
b.CursorRight()
|
||
|
|
b.Newline()
|
||
|
|
},
|
||
|
|
wantLines: []string{"ab", "cd"},
|
||
|
|
wantCursor: Cursor{line: 1, index: 0, glyph: 0},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"abcd"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorEnd()
|
||
|
|
b.Newline()
|
||
|
|
},
|
||
|
|
wantLines: []string{"abcd", ""},
|
||
|
|
wantCursor: Cursor{line: 1, index: 0, glyph: 0},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"ab", ""},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorDown()
|
||
|
|
b.Backspace()
|
||
|
|
},
|
||
|
|
wantLines: []string{"ab"},
|
||
|
|
wantCursor: Cursor{line: 0, index: 2, glyph: 2},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
lines: []string{"ab", "cd"},
|
||
|
|
action: func(b *Buffer) {
|
||
|
|
b.CursorDown()
|
||
|
|
b.Backspace()
|
||
|
|
},
|
||
|
|
wantLines: []string{"abcd"},
|
||
|
|
wantCursor: Cursor{line: 0, index: 2, glyph: 2},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for n, test := range tests {
|
||
|
|
b := newTestBuffer(test.lines...)
|
||
|
|
test.action(b)
|
||
|
|
if got := bufferLines(b); !reflect.DeepEqual(got, test.wantLines) {
|
||
|
|
t.Errorf(
|
||
|
|
"#%d: expected lines %q, but got %q",
|
||
|
|
n, test.wantLines, got,
|
||
|
|
)
|
||
|
|
}
|
||
|
|
if got := b.Cursor(); got != test.wantCursor {
|
||
|
|
t.Errorf(
|
||
|
|
"#%d: expected cursor %+v, but got %+v",
|
||
|
|
n, test.wantCursor, got,
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|