]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/eventhandler.go
Fix replace cursor relocation
[micro.git] / cmd / micro / eventhandler.go
index 2c0e6482e977e3afe94fba4ad8565881beb79d57..eed62484b374bd2adeb8b788b77226f4de823e84 100644 (file)
@@ -2,6 +2,8 @@ package main
 
 import (
        "time"
+
+       dmp "github.com/sergi/go-diff/diffmatchpatch"
 )
 
 const (
@@ -19,15 +21,15 @@ type TextEvent struct {
 
        EventType int
        Text      string
-       Start     int
-       End       int
+       Start     Loc
+       End       Loc
        Time      time.Time
 }
 
 // ExecuteTextEvent runs a text event
 func ExecuteTextEvent(t *TextEvent, buf *Buffer) {
        if t.EventType == TextEventInsert {
-               buf.insert(t.Start, t.Text)
+               buf.insert(t.Start, []byte(t.Text))
        } else if t.EventType == TextEventRemove {
                t.Text = buf.remove(t.Start, t.End)
        }
@@ -55,21 +57,41 @@ 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) {
+       differ := dmp.New()
+       diff := differ.DiffMain(eh.buf.String(), new, false)
+       loc := eh.buf.Start()
+       for _, d := range diff {
+               if d.Type == dmp.DiffDelete {
+                       eh.Remove(loc, loc.Move(Count(d.Text), eh.buf))
+               } else {
+                       if d.Type == dmp.DiffInsert {
+                               eh.Insert(loc, d.Text)
+                       }
+                       loc = loc.Move(Count(d.Text), eh.buf)
+               }
+       }
+}
+
 // Insert creates an insert text event and executes it
-func (eh *EventHandler) Insert(start int, text string) {
+func (eh *EventHandler) Insert(start Loc, text string) {
        e := &TextEvent{
                C:         eh.buf.Cursor,
                EventType: TextEventInsert,
                Text:      text,
                Start:     start,
-               End:       start + Count(text),
                Time:      time.Now(),
        }
        eh.Execute(e)
+       e.End = start.Move(Count(text), eh.buf)
 }
 
 // Remove creates a remove text event and executes it
-func (eh *EventHandler) Remove(start, end int) {
+func (eh *EventHandler) Remove(start, end Loc) {
        e := &TextEvent{
                C:         eh.buf.Cursor,
                EventType: TextEventRemove,
@@ -81,7 +103,7 @@ func (eh *EventHandler) Remove(start, end int) {
 }
 
 // Replace deletes from start to end and replaces it with the given string
-func (eh *EventHandler) Replace(start, end int, replace string) {
+func (eh *EventHandler) Replace(start, end Loc, replace string) {
        eh.Remove(start, end)
        eh.Insert(start, replace)
 }