_ = require 'underscore' module.exports = class UndoManager undoHistory: null redoHistory: null currentTransaction: null constructor: -> @clear() clear: -> @currentTransaction = null @undoHistory = [] @redoHistory = [] pushOperation: (operation, editSession) -> if @currentTransaction @currentTransaction.push(operation) else @undoHistory.push([operation]) @redoHistory = [] try operation.do?(editSession) catch e @clear() throw e transact: (fn) -> isNewTransaction = not @currentTransaction? @currentTransaction ?= [] if fn try fn() finally @commit() if isNewTransaction isNewTransaction commit: -> unless @currentTransaction? throw new Error("Trying to commit when there is no current transaction") empty = @currentTransaction.length is 0 @undoHistory.push(@currentTransaction) unless empty @currentTransaction = null not empty abort: -> unless @currentTransaction? throw new Error("Trying to abort when there is no current transaction") if @commit() @undo() @redoHistory.pop() undo: (editSession) -> try if batch = @undoHistory.pop() opsInReverse = new Array(batch...) opsInReverse.reverse() op.undo?(editSession) for op in opsInReverse @redoHistory.push batch batch.oldSelectionRanges catch e @clear() throw e redo: (editSession) -> try if batch = @redoHistory.pop() for op in batch op.do?(editSession) op.redo?(editSession) @undoHistory.push(batch) batch.newSelectionRanges catch e @clear() throw e