Files
atom/src/app/undo-manager.coffee
Corey Johnson & Nathan Sobo 1b8a8cf939 Make UndoManager.clear not cancel the transaction
If an exception is thrown while running an operation, we clear the
undo manager and re-throw it. But if we were in a transaction, we will
commit it in a `finally` block. If the transaction is set to null,
committing the transaction will then throw an exception which hides
the original exception… we don't want that. Now clear just empties the
current transaction out.
2013-05-03 17:21:50 -06:00

77 lines
1.7 KiB
CoffeeScript

_ = require 'underscore'
# Internal: The object in charge of managing redo and undo operations.
module.exports =
class UndoManager
undoHistory: null
redoHistory: null
currentTransaction: null
constructor: ->
@clear()
clear: ->
@currentTransaction = [] if @currentTransaction?
@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: ->
isNewTransaction = not @currentTransaction?
@currentTransaction ?= []
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