From ef17306f8b57e2477d9c77d17926b80f48dc53ef Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 30 May 2016 21:01:40 -0400 Subject: [PATCH] Allow changes from external programs to be undone We use a diff to be able to transform the buffer into an arbitrary string (usually when we reread the file after an external program such as gofmt has changed it) and still preserve undo/redo. Fixes #136 --- cmd/micro/buffer.go | 6 +----- cmd/micro/eventhandler.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) 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{