diff --git a/cmd/micro/buffer.go b/cmd/micro/buffer.go index fbcb602a..0357db52 100644 --- a/cmd/micro/buffer.go +++ b/cmd/micro/buffer.go @@ -155,11 +155,7 @@ func (b *Buffer) ReOpen() { messenger.Error(err.Error()) return } - if txt == "" { - b.r = new(rope.Rope) - } else { - b.r = rope.New(txt) - } + b.EventHandler.ApplyDiff(txt) b.ModTime, _ = GetModTime(b.Path) b.IsModified = false diff --git a/cmd/micro/eventhandler.go b/cmd/micro/eventhandler.go index 2c0e6482..84f7465c 100644 --- a/cmd/micro/eventhandler.go +++ b/cmd/micro/eventhandler.go @@ -2,6 +2,8 @@ package main import ( "time" + + dmp "github.com/sergi/go-diff/diffmatchpatch" ) const ( @@ -55,6 +57,25 @@ func NewEventHandler(buf *Buffer) *EventHandler { return eh } +// ApplyDiff takes a string and runs the necessary insertion and deletion events to make +// the buffer equal to that string +// This means that we can transform the buffer into any string and still preserve undo/redo +// through insert and delete events +func (eh *EventHandler) ApplyDiff(new string) { + messenger.Message("Applying diff") + differ := dmp.New() + diff := differ.DiffMain(eh.buf.String(), new, false) + var charNum int + for _, d := range diff { + if d.Type == dmp.DiffInsert { + eh.Insert(charNum, d.Text) + } else if d.Type == dmp.DiffDelete { + eh.Remove(charNum, charNum+Count(d.Text)) + } + charNum += Count(d.Text) + } +} + // Insert creates an insert text event and executes it func (eh *EventHandler) Insert(start int, text string) { e := &TextEvent{