From 0452d3e65112cd6bb66280ff77e2c9cb74342b3a Mon Sep 17 00:00:00 2001 From: Robert Kroeger Date: Tue, 8 Feb 2022 19:49:40 -0500 Subject: [PATCH] Basic interactive editing with newtype buffers With this change, Edwood can successfully do interactive editing operations when using the newtype buffers. (Run with --newtypebuffer). Helps with #97. --- file/buffer_adapter.go | 2 +- file/buffer_adapter_test.go | 109 ++++++++++++++++++++++++++++++++++++ file/undo.go | 6 +- file/undo_test.go | 2 +- 4 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 file/buffer_adapter_test.go diff --git a/file/buffer_adapter.go b/file/buffer_adapter.go index a662e17c..b65ed881 100644 --- a/file/buffer_adapter.go +++ b/file/buffer_adapter.go @@ -171,7 +171,7 @@ func (b *Buffer) Mark() { } func (b *Buffer) Read(rq0 int, r []rune) (int, error) { - p0 := b.RuneTuple(0) + p0 := b.RuneTuple(rq0) sr := io.NewSectionReader(b, int64(p0.b), int64(b.Size()-p0.b)) bsr := bufio.NewReader(sr) diff --git a/file/buffer_adapter_test.go b/file/buffer_adapter_test.go new file mode 100644 index 00000000..25d11eb6 --- /dev/null +++ b/file/buffer_adapter_test.go @@ -0,0 +1,109 @@ +package file + +import ( + "fmt" + "io" + "testing" +) + +func TestNewTypeBufferCreation(t *testing.T) { + b := NewTypeBuffer([]rune("hello"), nil) + + if got, want := b.String(), "hello"; got != want { + t.Errorf("didn't load right got %q want %q", got, want) + } +} + +func TestNewDeleteAt(t *testing.T) { + b := NewTypeBuffer([]rune("hello"), nil) + + b.DeleteAt(0, 2, 0) + + if got, want := b.String(), "llo"; got != want { + t.Errorf("didn't run delete correctly got %q want %q", got, want) + } + if got, want := b.HasUndoableChanges(), false; got != want { + t.Errorf("HasUndoableChanges wrong got %v want %v", got, want) + } + if got, want := b.HasRedoableChanges(), false; got != want { + t.Errorf("HasRedoableChanges wrong got %v want %v", got, want) + } + +} + +func TestNewIndexRune(t *testing.T) { + b := NewTypeBuffer([]rune("yi 海老hi 海老麺麺"), nil) + + for _, tc := range []struct { + r rune + offset int + }{ + { + r: 'y', + offset: 0, + }, + { + r: 'h', + offset: 5, + }, + { + r: '|', + offset: -1, + }, + } { + t.Run(fmt.Sprintf("%c->%d", tc.r, tc.offset), func(t *testing.T) { + if got, want := b.IndexRune(tc.r), tc.offset; got != want { + t.Errorf("IndexRune failed, got %d want %d", got, want) + } + + }) + } +} + +func TestNewRead(t *testing.T) { + b := NewTypeBuffer([]rune("yi 海老hi 海老麺麺"), nil) + + for _, tc := range []struct { + o int + r []rune + n int + gr string + err error + }{ + { + o: 0, + r: make([]rune, 1), + n: 1, + gr: "y", + }, + { + o: 3, + r: make([]rune, 4), + n: 4, + gr: "海老hi", + }, + { + o: 3, + r: make([]rune, 10), + n: 9, + gr: "海老hi 海老麺麺", + err: io.EOF, + }, + } { + t.Run(tc.gr, func(t *testing.T) { + + // Test here + n, err := b.Read(tc.o, tc.r) + if got, want := err, tc.err; got != want { + t.Errorf("got error %v want %v", got, want) + } + if got, want := n, tc.n; got != want { + t.Errorf("got length %d want %d", got, want) + } + if got, want := string(tc.r[0:n]), tc.gr; got != want { + t.Errorf("got value %q want %q", got, want) + } + + }) + } +} diff --git a/file/undo.go b/file/undo.go index c7131c85..5572f0d6 100644 --- a/file/undo.go +++ b/file/undo.go @@ -698,9 +698,10 @@ func (b *Buffer) Bytes() []byte { return byteBuf } -// TODO(rjk): This concept is not needed. Handle that later. +// TODO(rjk): This concept is not needed in a file.Buffer world. Improve +// this. func (b *Buffer) HasUncommitedChanges() bool { - return b.cachedPiece != nil || b.currentAction != nil + return false } func (b *Buffer) HasUndoableChanges() bool { @@ -713,6 +714,7 @@ func (b *Buffer) HasRedoableChanges() bool { // RuneTuple creates a byte, rune offset pair (i.e. OffsetTuple) for a // given offset in runes. +// TODO(rjk): Consider using the cached piece to speed this up. func (b *Buffer) RuneTuple(off int) OffSetTuple { b.validateInvariant() diff --git a/file/undo_test.go b/file/undo_test.go index 10041b40..f71c3242 100644 --- a/file/undo_test.go +++ b/file/undo_test.go @@ -257,7 +257,7 @@ func TestBufferSize(t *testing.T) { } } -func disabled_TestUndoRedoReturnedOffsets(t *testing.T) { +func TestUndoRedoReturnedOffsets(t *testing.T) { b := NewBufferNoNr(nil) insert := func(off, len int) { b.insertString(off, strings.Repeat(".", len))