]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/eventhandler.go
Use messenger error instead of termerror
[micro.git] / cmd / micro / eventhandler.go
index 0a6658daae6e19752be9ea3d9ee2ba0499a692e7..1a94813f266695cc8d072507de1bc7e33ccc5046 100644 (file)
@@ -1,9 +1,11 @@
 package main
 
 import (
+       "strings"
        "time"
 
        dmp "github.com/sergi/go-diff/diffmatchpatch"
+       "github.com/yuin/gopher-lua"
 )
 
 const (
@@ -13,6 +15,8 @@ const (
        TextEventInsert = 1
        // TextEventRemove represents a deletion event
        TextEventRemove = -1
+
+       TextEventReplace = 0
 )
 
 // TextEvent holds data for a manipulation on some text that can be undone
@@ -20,18 +24,31 @@ type TextEvent struct {
        C Cursor
 
        EventType int
-       Text      string
-       Start     Loc
-       End       Loc
+       Deltas    []Delta
        Time      time.Time
 }
 
+type Delta struct {
+       Text  string
+       Start Loc
+       End   Loc
+}
+
 // ExecuteTextEvent runs a text event
 func ExecuteTextEvent(t *TextEvent, buf *Buffer) {
        if t.EventType == TextEventInsert {
-               buf.insert(t.Start, []byte(t.Text))
+               for _, d := range t.Deltas {
+                       buf.insert(d.Start, []byte(d.Text))
+               }
        } else if t.EventType == TextEventRemove {
-               t.Text = buf.remove(t.Start, t.End)
+               for i, d := range t.Deltas {
+                       t.Deltas[i].Text = buf.remove(d.Start, d.End)
+               }
+       } else if t.EventType == TextEventReplace {
+               for i, d := range t.Deltas {
+                       t.Deltas[i].Text = buf.remove(d.Start, d.End)
+                       buf.insert(d.Start, []byte(d.Text))
+               }
        }
 }
 
@@ -66,12 +83,14 @@ func (eh *EventHandler) ApplyDiff(new string) {
        diff := differ.DiffMain(eh.buf.String(), new, false)
        loc := eh.buf.Start()
        for _, d := range diff {
-               if d.Type == dmp.DiffInsert {
-                       eh.Insert(loc, d.Text)
-               } else if d.Type == dmp.DiffDelete {
+               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)
                }
-               loc = loc.Move(Count(d.Text), eh.buf)
        }
 }
 
@@ -80,12 +99,11 @@ func (eh *EventHandler) Insert(start Loc, text string) {
        e := &TextEvent{
                C:         eh.buf.Cursor,
                EventType: TextEventInsert,
-               Text:      text,
-               Start:     start,
+               Deltas:    []Delta{Delta{text, start, Loc{0, 0}}},
                Time:      time.Now(),
        }
        eh.Execute(e)
-       e.End = start.Move(Count(text), eh.buf)
+       e.Deltas[0].End = start.Move(Count(text), eh.buf)
 }
 
 // Remove creates a remove text event and executes it
@@ -93,8 +111,18 @@ func (eh *EventHandler) Remove(start, end Loc) {
        e := &TextEvent{
                C:         eh.buf.Cursor,
                EventType: TextEventRemove,
-               Start:     start,
-               End:       end,
+               Deltas:    []Delta{Delta{"", start, end}},
+               Time:      time.Now(),
+       }
+       eh.Execute(e)
+}
+
+// Multiple creates an multiple insertions executes them
+func (eh *EventHandler) MultipleReplace(deltas []Delta) {
+       e := &TextEvent{
+               C:         eh.buf.Cursor,
+               EventType: TextEventReplace,
+               Deltas:    deltas,
                Time:      time.Now(),
        }
        eh.Execute(e)
@@ -112,6 +140,17 @@ func (eh *EventHandler) Execute(t *TextEvent) {
                eh.RedoStack = new(Stack)
        }
        eh.UndoStack.Push(t)
+
+       for pl := range loadedPlugins {
+               ret, err := Call(pl+".onBeforeTextEvent", t)
+               if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
+                       TermMessage(err)
+               }
+               if val, ok := ret.(lua.LBool); ok && val == lua.LFalse {
+                       return
+               }
+       }
+
        ExecuteTextEvent(t, eh.buf)
 }