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
This commit is contained in:
Zachary Yedidia
2016-05-30 21:01:40 -04:00
parent d4caf4510c
commit ef17306f8b
2 changed files with 22 additions and 5 deletions

View File

@@ -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

View File

@@ -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{