Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package backend
import (
"fmt"

"github.com/limetext/backend/render"
"github.com/limetext/text"
)

Expand All @@ -17,21 +18,24 @@ type (
//
// Think of it a bit like an SQL transaction.
Edit struct {
invalid bool
composite text.CompositeAction
savedSel text.RegionSet
savedCount int
command string
args Args
v *View
bypassUndo bool
invalid bool
composite text.CompositeAction
savedSel text.RegionSet
savedRegs render.ViewRegionMap
appliedRegs render.ViewRegionMap
savedCount int
command string
args Args
v *View
bypassUndo bool
}
)

func newEdit(v *View) *Edit {
ret := &Edit{
v: v,
savedCount: v.ChangeCount(),
savedRegs: v.cloneRegions(),
}
for _, r := range v.Sel().Regions() {
ret.savedSel.Add(r)
Expand All @@ -47,13 +51,41 @@ func (e *Edit) String() string {
// Applies the action of this Edit object. Should typically not be manually called.
func (e *Edit) Apply() {
e.composite.Apply()
if e.appliedRegs != nil {
e.v.restoreRegions(e.appliedRegs)
}
}

// Reverses the application of this Edit object. Should typically not be manually called.
func (e *Edit) Undo() {
e.composite.Undo()
if e.savedRegs != nil {
e.v.restoreRegions(e.savedRegs)
}
e.v.Sel().Clear()
for _, r := range e.savedSel.Regions() {
e.v.Sel().Add(r)
}
}

func cloneViewRegions(regions render.ViewRegionMap) render.ViewRegionMap {
ret := make(render.ViewRegionMap, len(regions))
for key, value := range regions {
ret[key] = *value.Clone()
}
return ret
}

func (v *View) cloneRegions() render.ViewRegionMap {
v.lock.Lock()
defer v.lock.Unlock()

return cloneViewRegions(v.regions)
}

func (v *View) restoreRegions(regions render.ViewRegionMap) {
v.lock.Lock()
defer v.lock.Unlock()

v.regions = cloneViewRegions(regions)
}
4 changes: 4 additions & 0 deletions undo.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,17 @@ func (us *UndoStack) GlueFrom(mark int) {
}
e.v = us.actions[mark].v
e.savedSel.AddAll(us.actions[mark].savedSel.Regions())
e.savedRegs = cloneViewRegions(us.actions[mark].savedRegs)

entries := make([]entry, us.position-mark)
for i := range entries {
a := us.actions[i+mark]
entries[i].name = a.command
entries[i].args = a.args
e.composite.Add(a)
if a.appliedRegs != nil {
e.appliedRegs = cloneViewRegions(a.appliedRegs)
}
}
us.position = mark
us.actions = us.actions[:mark+1]
Expand Down
1 change: 1 addition & 0 deletions view.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ func (v *View) EndEdit(edit *Edit) {
for j := len(v.editstack) - 1; j >= i; j-- {
current_edit := v.editstack[j]
current_edit.invalid = true
current_edit.appliedRegs = v.cloneRegions()
sel_same := reflect.DeepEqual(*v.Sel(), current_edit.savedSel)
buf_same := v.ChangeCount() == current_edit.savedCount
eq := (sel_same && buf_same && current_edit.composite.Len() == 0)
Expand Down
29 changes: 29 additions & 0 deletions view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"testing"
"time"

"github.com/limetext/backend/render"
"github.com/limetext/text"
"github.com/limetext/util"
)
Expand Down Expand Up @@ -146,6 +147,34 @@ func TestErase(t *testing.T) {
}
}

func TestUndoRestoresRegions(t *testing.T) {
w := GetEditor().NewWindow()
defer w.Close()

v := w.NewFile()
defer func() {
v.SetScratch(true)
v.Close()
}()

edit := v.BeginEdit()
v.Insert(edit, 0, "abcdefghij")
v.EndEdit(edit)

expected := []text.Region{{A: 1, B: 3}, {A: 6, B: 9}}
v.AddRegions("test.regions", expected, "comment", "", render.DEFAULT)

edit = v.BeginEdit()
v.Erase(edit, text.Region{A: 0, B: v.Size()})
v.EndEdit(edit)

v.undoStack.Undo(true)

if regions := v.GetRegions("test.regions"); !reflect.DeepEqual(regions, expected) {
t.Errorf("expected regions %v after undo, got %v", expected, regions)
}
}

func TestSaveAsNewFile(t *testing.T) {
tests := []struct {
text string
Expand Down