Add editor packages
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user