UNPKG

simple-text-buffer

Version:

A version of Atom's text-buffer with marker layers and file support removed

410 lines (375 loc) 12.3 kB
(function() { var Checkpoint, History, Patch, SerializationVersion, Transaction; Patch = require('atom-patch'); SerializationVersion = 5; Checkpoint = (function() { function Checkpoint(id, isBoundary1) { this.id = id; this.isBoundary = isBoundary1; } return Checkpoint; })(); Transaction = (function() { function Transaction(patch1, groupingInterval1) { this.patch = patch1; this.groupingInterval = groupingInterval1 != null ? groupingInterval1 : 0; this.timestamp = Date.now(); } Transaction.prototype.shouldGroupWith = function(previousTransaction) { var timeBetweenTransactions; timeBetweenTransactions = this.timestamp - previousTransaction.timestamp; return timeBetweenTransactions < Math.min(this.groupingInterval, previousTransaction.groupingInterval); }; Transaction.prototype.groupWith = function(previousTransaction) { return new Transaction(Patch.compose([previousTransaction.patch, this.patch]), this.groupingInterval); }; return Transaction; })(); module.exports = History = (function() { History.deserialize = function(state, buffer) { var history; history = new History(buffer); history.deserialize(state); return history; }; function History(buffer1, maxUndoEntries) { this.buffer = buffer1; this.maxUndoEntries = maxUndoEntries; this.nextCheckpointId = 0; this.undoStack = []; this.redoStack = []; } History.prototype.createCheckpoint = function(isBoundary) { var checkpoint; checkpoint = new Checkpoint(this.nextCheckpointId++, isBoundary); this.undoStack.push(checkpoint); return checkpoint.id; }; History.prototype.groupChangesSinceCheckpoint = function(checkpointId, deleteCheckpoint) { var checkpointIndex, composedPatches, entry, i, j, patchesSinceCheckpoint, ref; if (deleteCheckpoint == null) { deleteCheckpoint = false; } checkpointIndex = null; patchesSinceCheckpoint = []; ref = this.undoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (checkpointIndex != null) { break; } switch (entry.constructor) { case Checkpoint: if (entry.id === checkpointId) { checkpointIndex = i; } else if (entry.isBoundary) { return false; } break; case Transaction: patchesSinceCheckpoint.unshift(entry.patch); break; case Patch: patchesSinceCheckpoint.unshift(entry); break; default: throw new Error("Unexpected undo stack entry type: " + entry.constructor.name); } } if (checkpointIndex != null) { composedPatches = Patch.compose(patchesSinceCheckpoint); if (patchesSinceCheckpoint.length > 0) { this.undoStack.splice(checkpointIndex + 1); this.undoStack.push(new Transaction(composedPatches)); } if (deleteCheckpoint) { this.undoStack.splice(checkpointIndex, 1); } return composedPatches; } else { return false; } }; History.prototype.getChangesSinceCheckpoint = function(checkpointId) { var checkpointIndex, entry, i, j, patchesSinceCheckpoint, ref; checkpointIndex = null; patchesSinceCheckpoint = []; ref = this.undoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (checkpointIndex != null) { break; } switch (entry.constructor) { case Checkpoint: if (entry.id === checkpointId) { checkpointIndex = i; } break; case Transaction: patchesSinceCheckpoint.unshift(entry.patch); break; case Patch: patchesSinceCheckpoint.unshift(entry); break; default: throw new Error("Unexpected undo stack entry type: " + entry.constructor.name); } } if (checkpointIndex != null) { return Patch.compose(patchesSinceCheckpoint); } else { return null; } }; History.prototype.enforceUndoStackSizeLimit = function() { if (this.undoStack.length > this.maxUndoEntries) { return this.undoStack.splice(0, this.undoStack.length - this.maxUndoEntries); } }; History.prototype.applyGroupingInterval = function(groupingInterval) { var previousEntry, topEntry; topEntry = this.undoStack[this.undoStack.length - 1]; previousEntry = this.undoStack[this.undoStack.length - 2]; if (topEntry instanceof Transaction) { topEntry.groupingInterval = groupingInterval; } else { return; } if (groupingInterval === 0) { return; } if (previousEntry instanceof Transaction && topEntry.shouldGroupWith(previousEntry)) { return this.undoStack.splice(this.undoStack.length - 2, 2, topEntry.groupWith(previousEntry)); } }; History.prototype.pushChange = function(change) { this.undoStack.push(Patch.hunk(change)); return this.clearRedoStack(); }; History.prototype.popUndoStack = function() { var entry, i, j, patch, ref, ref1, spliceIndex; patch = null; spliceIndex = null; ref = this.undoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (spliceIndex != null) { break; } switch (entry.constructor) { case Checkpoint: if (entry.isBoundary) { return false; } break; case Transaction: patch = Patch.invert(entry.patch); spliceIndex = i; break; case Patch: patch = Patch.invert(entry); spliceIndex = i; break; default: throw new Error("Unexpected entry type when popping undoStack: " + entry.constructor.name); } } if (spliceIndex != null) { (ref1 = this.redoStack).push.apply(ref1, this.undoStack.splice(spliceIndex).reverse()); return { patch: patch }; } else { return false; } }; History.prototype.popRedoStack = function() { var entry, i, j, patch, ref, ref1, spliceIndex; patch = null; spliceIndex = null; ref = this.redoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (spliceIndex != null) { break; } switch (entry.constructor) { case Checkpoint: if (entry.isBoundary) { throw new Error("Invalid redo stack state"); } break; case Transaction: patch = entry.patch; spliceIndex = i; break; case Patch: patch = entry; spliceIndex = i; break; default: throw new Error("Unexpected entry type when popping redoStack: " + entry.constructor.name); } } while (this.redoStack[spliceIndex - 1] instanceof Checkpoint) { spliceIndex--; } if (spliceIndex != null) { (ref1 = this.undoStack).push.apply(ref1, this.redoStack.splice(spliceIndex).reverse()); return { patch: patch }; } else { return false; } }; History.prototype.truncateUndoStack = function(checkpointId) { var entry, i, j, patchesSinceCheckpoint, ref, spliceIndex; spliceIndex = null; patchesSinceCheckpoint = []; ref = this.undoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (spliceIndex != null) { break; } switch (entry.constructor) { case Checkpoint: if (entry.id === checkpointId) { spliceIndex = i; } else if (entry.isBoundary) { return false; } break; case Transaction: patchesSinceCheckpoint.push(Patch.invert(entry.patch)); break; default: patchesSinceCheckpoint.push(Patch.invert(entry)); } } if (spliceIndex != null) { this.undoStack.splice(spliceIndex); return { patch: Patch.compose(patchesSinceCheckpoint) }; } else { return false; } }; History.prototype.clearUndoStack = function() { return this.undoStack.length = 0; }; History.prototype.clearRedoStack = function() { return this.redoStack.length = 0; }; History.prototype.toString = function() { var entry, j, len, output, ref; output = ''; ref = this.undoStack; for (j = 0, len = ref.length; j < len; j++) { entry = ref[j]; switch (entry.constructor) { case Checkpoint: output += "Checkpoint, "; break; case Transaction: output += "Transaction, "; break; case Patch: output += "Patch, "; break; default: output += "Unknown {" + (JSON.stringify(entry)) + "}, "; } } return '[' + output.slice(0, -2) + ']'; }; History.prototype.serialize = function(options) { return { version: SerializationVersion, nextCheckpointId: this.nextCheckpointId, undoStack: this.serializeStack(this.undoStack, options), redoStack: this.serializeStack(this.redoStack, options), maxUndoEntries: this.maxUndoEntries }; }; History.prototype.deserialize = function(state) { if (state.version !== SerializationVersion) { return; } this.nextCheckpointId = state.nextCheckpointId; this.maxUndoEntries = state.maxUndoEntries; this.undoStack = this.deserializeStack(state.undoStack); return this.redoStack = this.deserializeStack(state.redoStack); }; /* Section: Private */ History.prototype.getCheckpointIndex = function(checkpointId) { var entry, i, j, ref; ref = this.undoStack; for (i = j = ref.length - 1; j >= 0; i = j += -1) { entry = ref[i]; if (entry instanceof Checkpoint && entry.id === checkpointId) { return i; } } return null; }; History.prototype.serializeStack = function(stack, options) { var entry, j, len, results; results = []; for (j = 0, len = stack.length; j < len; j++) { entry = stack[j]; switch (entry.constructor) { case Checkpoint: results.push({ type: 'checkpoint', id: entry.id, isBoundary: entry.isBoundary }); break; case Transaction: results.push({ type: 'transaction', patch: entry.patch.serialize() }); break; case Patch: results.push({ type: 'patch', content: entry.serialize() }); break; default: throw new Error("Unexpected undoStack entry type during serialization: " + entry.constructor.name); } } return results; }; History.prototype.deserializeStack = function(stack) { var entry, j, len, results; results = []; for (j = 0, len = stack.length; j < len; j++) { entry = stack[j]; switch (entry.type) { case 'checkpoint': results.push(new Checkpoint(entry.id, entry.isBoundary)); break; case 'transaction': results.push(new Transaction(Patch.deserialize(entry.patch))); break; case 'patch': results.push(Patch.deserialize(entry.content)); break; default: throw new Error("Unexpected undoStack entry type during deserialization: " + entry.type); } } return results; }; return History; })(); }).call(this);