github.com/aretext/aretext@v1.3.0/state/undo.go (about) 1 package state 2 3 import ( 4 "log" 5 6 "github.com/aretext/aretext/undo" 7 ) 8 9 // BeginUndoEntry begins a new undo entry. 10 // This should be called before tracking any undo operations. 11 func BeginUndoEntry(state *EditorState) { 12 if state.macroState.isReplayingUserMacro { 13 log.Printf("Skip begin undo entry because we're replaying a user macro\n") 14 return 15 } 16 17 log.Printf("Begin undo entry\n") 18 buffer := state.documentBuffer 19 buffer.undoLog.BeginEntry(buffer.cursor.position) 20 } 21 22 // CommitUndoEntry commits the current undo entry. 23 // This should be called after completing an action that can be undone. 24 func CommitUndoEntry(state *EditorState) { 25 if state.macroState.isReplayingUserMacro { 26 log.Printf("Skip commit undo entry because we're replaying a user macro\n") 27 return 28 } 29 30 log.Printf("Commit undo entry\n") 31 buffer := state.documentBuffer 32 buffer.undoLog.CommitEntry(buffer.cursor.position) 33 } 34 35 // Undo returns the document to its state at the last undo entry. 36 func Undo(state *EditorState) { 37 hasEntry, undoOps, cursor := state.documentBuffer.undoLog.UndoToLastCommitted() 38 if !hasEntry { 39 return 40 } 41 42 for _, op := range undoOps { 43 log.Printf("Undo operation: %#v\n", op) 44 if err := applyOpFromUndoLog(state, op); err != nil { 45 log.Printf("Could not apply undo op %v: %v\n", op, err) 46 continue 47 } 48 } 49 50 MoveCursor(state, func(LocatorParams) uint64 { 51 return cursor 52 }) 53 } 54 55 // Redo reverses the last undo operation. 56 func Redo(state *EditorState) { 57 hasEntry, redoOps, cursor := state.documentBuffer.undoLog.RedoToNextCommitted() 58 if !hasEntry { 59 return 60 } 61 62 for _, op := range redoOps { 63 log.Printf("Redo operation: %#v\n", op) 64 if err := applyOpFromUndoLog(state, op); err != nil { 65 log.Printf("Could not apply redo op %v: %v\n", op, err) 66 continue 67 } 68 } 69 70 MoveCursor(state, func(LocatorParams) uint64 { 71 return cursor 72 }) 73 } 74 75 func applyOpFromUndoLog(state *EditorState, op undo.Op) error { 76 pos := op.Position() 77 if s := op.TextToInsert(); len(s) > 0 { 78 return insertTextAtPosition(state, s, pos, false) 79 } else if n := op.NumRunesToDelete(); n > 0 { 80 deleteRunes(state, pos, uint64(n), false) 81 } 82 return nil 83 }