allow redoing after changing the document

pull/85/head
nightwing 2014-12-22 00:59:08 +04:00
rodzic 9405b78dce
commit f04f22076c
4 zmienionych plików z 342 dodań i 104 usunięć

32
node_modules/ace/lib/ace/edit_session.js wygenerowano vendored
Wyświetl plik

@ -255,7 +255,7 @@ var EditSession = function(text, mode) {
this.$resetRowCache(delta.start.row);
var removedFolds = this.$updateInternalDataOnChange(delta);
if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
if (!this.$fromUndo && this.$undoManager) {
if (removedFolds && removedFolds.length) {
this.$undoManager.add({
action: "removeFolds",
@ -266,13 +266,6 @@ var EditSession = function(text, mode) {
this.$undoManager.add(delta, this);
this.mergeUndoDeltas = true;
var g = this.$undoManager.lastDeltas;
if (g && this.curOp && !this.curOp.group) {
this.curOp.group = g;
if (!g.selectionBefore)
g.selectionBefore = this.curOp.selectionBefore;
}
this.$informUndoManager.schedule();
}
@ -383,6 +376,7 @@ var EditSession = function(text, mode) {
if (undoManager) {
var self = this;
undoManager.$session = this;
this.$syncInformUndoManager = function() {
self.$informUndoManager.cancel();
self.mergeUndoDeltas = false;
@ -406,7 +400,8 @@ var EditSession = function(text, mode) {
redo: function() {},
reset: function() {},
add: function() {},
startGroup: function() {},
addSelection: function() {},
startNewGroup: function() {},
};
/**
@ -1156,15 +1151,18 @@ var EditSession = function(text, mode) {
var delta = deltas[i];
if (delta.action == "insert" || delta.action == "remove") {
this.doc.revertDelta(delta);
} else {
} else if (delta.folds) {
this.addFolds(delta.folds);
}
}
if (!dontSelect) {
// console.log(deltas.selectionBefore + "uuu")
if (deltas.selectionBefore)
this.selection.fromJSON(deltas.selectionBefore);
else
this.selection.setRange(this.$getUndoSelection(deltas, true));
}
this.$fromUndo = false;
if (deltas.selectionBefore)
this.selection.fromJSON(deltas.selectionBefore);
else
this.selection.setRange(this.$getUndoSelection(deltas, true));
};
/**
@ -1173,7 +1171,7 @@ var EditSession = function(text, mode) {
* @param {Boolean} dontSelect {:dontSelect}
*
* @returns {Range}
**/
**/
this.redoChanges = function(deltas, dontSelect) {
if (!deltas.length)
return;
@ -1195,7 +1193,7 @@ var EditSession = function(text, mode) {
/**
* Enables or disables highlighting of the range where an undo occured.
* @param {Boolean} enable If `true`, selects the range of the reinserted change
*
*
**/
this.setUndoSelect = function(enable) {
this.$undoSelect = enable;
@ -1214,7 +1212,7 @@ var EditSession = function(text, mode) {
i = deltas.length - 1;
while (!deltas[i].end && i >= 0)
i--;
}
}
var pos = isInsert(deltas[i]) ? deltas[i].end : deltas[i].start;
return Range.fromPoints(pos, pos);
};

32
node_modules/ace/lib/ace/editor.js wygenerowano vendored
Wyświetl plik

@ -111,21 +111,27 @@ var Editor = function(renderer, session) {
oop.implement(this, EventEmitter);
this.$initOperationListeners = function() {
function last(a) {return a[a.length - 1]}
this.selections = [];
this.commands.toggleRecording();
this.commands.on("exec", this.startOperation.bind(this), true);
this.commands.on("afterExec", this.endOperation.bind(this), true);
this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
// todo: add before change events?
this.on("change", function() {
this.curOp || this.startOperation();
if (!this.curOp) {
this.startOperation();
this.curOp.selectionBefore = this.$lastSel;
}
this.curOp.docChanged = true;
}.bind(this), true);
this.on("changeSelection", function() {
this.curOp || this.startOperation();
if (!this.curOp) {
this.startOperation();
this.curOp.selectionBefore = this.$lastSel;
}
this.curOp.selectionChanged = true;
}.bind(this), true);
};
@ -150,13 +156,12 @@ var Editor = function(renderer, session) {
scrollTop: this.renderer.scrollTop
};
this.curOp.selectionBefore = this.selection.toJSON();
// this.selections.push();
};
this.endOperation = function(e) {
if (this.curOp) {
if (e && e.returnValue === false)
return this.curOp = null;
return (this.curOp = null);
this._signal("beforeEndOperation");
var command = this.curOp.command;
var scrollIntoView = command && command.scrollIntoView;
@ -185,9 +190,12 @@ var Editor = function(renderer, session) {
if (scrollIntoView == "animate")
this.renderer.animateScrolling(this.curOp.scrollTop);
}
this.curOp.selectionAfter = this.selection.toJSON();
if (this.curOp.group)
this.curOp.group.selectionAfter = this.curOp.selectionAfter;
var sel = this.selection.toJSON();
this.curOp.selectionAfter = sel;
this.$lastSel = this.selection.toJSON();
// console.log(this.$lastSel+" endOP")
this.session.getUndoManager().addSelection(sel);
this.prevOp = this.curOp;
this.curOp = null;
}

380
node_modules/ace/lib/ace/undomanager.js wygenerowano vendored
Wyświetl plik

@ -56,52 +56,101 @@ var UndoManager = function() {
* @param {Object} options Contains additional properties
*
**/
this.add = function(delta, doc) {
// Normalize deltas for storage.
// var deltaSets = this.$serializeDeltas(options.args[0]);
// Add deltas to undo stack.
this.$doc = doc;
// if (options.merge && this.hasUndo()){
// this.dirtyCounter--;
// deltaSets = this.$undoStack.pop().concat(deltaSets);
// }
if (doc.mergeUndoDeltas === false || !this.lastDeltas) {
this.add = function(delta) {
if (this.$session.mergeUndoDeltas === false || !this.lastDeltas) {
this.lastDeltas = [];
this.$undoStack.push(this.lastDeltas);
this.$rev++;
delta.id = this.$rev;
}
this.lastDeltas.push(delta);
// Reset redo stack.
this.$redoStack = [];
if (this.dirtyCounter < 0) {
// The user has made a change after undoing past the last clean state.
// We can never get back to a clean state now until markClean() is called.
this.dirtyCounter = NaN;
}
this.dirtyCounter++;
};
this.startGroup = function() {
this.addSelection = function(selection, rev) {
this.selections.push({
value: selection,
rev: rev || this.$rev
});
};
this.startNewGroup = function() {
this.lastDeltas = null;
return this.$rev;
};
this.markIgnored = function(from, to) {
if (to == null) to = this.$rev + 1;
var stack = this.$undoStack;
for (var i = stack.length; i--;) {
var delta = stack[i][0];
if (delta.id < to)
delta.ignore = true;
if (delta.id <= from)
break;
}
this.lastDeltas = null;
};
this.getSelection = function(rev, after) {
var stack = this.selections;
for (var i = stack.length; i--;) {
var selection = stack[i];
if (selection.rev < rev) {
if (after)
selection = stack[i + 1];
return selection;
}
}
};
this.getRevision = function() {
return this.$rev;
};
this.getDeltas = function(from, to) {
if (to == null) to = this.$rev + 1;
var stack = this.$undoStack;
var end = null, start = 0;
for (var i = stack.length; i--;) {
var delta = stack[i][0];
if (delta.id < to && !end)
end = i+1;
if (delta.id <= from) {
start = i + 1;
break;
}
}
return stack.slice(start, end);
};
this.getChangedRanges = function(from, to) {
};
this.getChangedLines = function(from, to) {
};
/**
* [Perform an undo operation on the document, reverting the last change.]{: #UndoManager.undo}
* @param {Boolean} dontSelect {:dontSelect}
*
* @returns {Range} The range of the undo.
**/
this.undo = function() {
this.undo = function(dontSelect) {
this.lastDeltas = null;
var stack = this.$undoStack;
UndoManager.rebase(stack, stack.length);
findDelta(stack, stack.length);
var deltaSet = stack.pop();
var undoSelectionRange = null;
if (deltaSet) {
undoSelectionRange = this.$doc.undoChanges(deltaSet);
if (deltaSet && deltaSet.length) {
var id = deltaSet[0].id;
undoSelectionRange = this.$session.undoChanges(deltaSet, dontSelect);
if (this.$redoStackBaseRev !== id) {
this.$redoStack = [];
}
this.$redoStack.push(deltaSet);
this.dirtyCounter--;
this.$syncRev();
}
return undoSelectionRange;
@ -114,23 +163,39 @@ var UndoManager = function() {
**/
this.redo = function(dontSelect) {
this.lastDeltas = null;
if (this.$redoStackBaseRev != this.$rev) {
var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
rebaseRedoStack(this.$redoStack, diff);
this.$redoStackBaseRev = this.$rev;
}
var deltaSet = this.$redoStack.pop();
var redoSelectionRange = null;
if (deltaSet) {
redoSelectionRange = this.$doc.redoChanges(deltaSet);
redoSelectionRange = this.$session.redoChanges(deltaSet, dontSelect);
this.$undoStack.push(deltaSet);
this.dirtyCounter++;
this.$syncRev();
}
return redoSelectionRange;
};
this.$syncRev = function() {
var stack = this.$undoStack;
var nextDelta = stack[stack.length - 1];
var id = nextDelta && nextDelta[0].id || 0;
this.$redoStackBaseRev = id;
this.$rev = id;
};
/**
* Destroys the stack of undo and redo redo operations.
**/
this.reset = function() {
this.lastDeltas = null;
this.$undoStack = [];
this.$redoStack = [];
this.dirtyCounter = 0;
this.$rev = 0;
this.selections = [];
};
/**
@ -164,22 +229,13 @@ var UndoManager = function() {
return this.dirtyCounter === 0;
};
// // Serializes deltaSets to reduce memory usage.
// this.$serializeDeltas = function(deltaSets) {
// return cloneDeltaSetsObj(deltaSets, $serializeDelta);
// };
// // Deserializes deltaSets to allow application to the document.
// this.$deserializeDeltas = function(deltaSets) {
// return cloneDeltaSetsObj(deltaSets, $deserializeDelta);
// };
}).call(UndoManager.prototype);
UndoManager.rebase = function(stack, pos) {
function findDelta(stack, pos) {
for (var i = pos; i--; ) {
var deltaSet = stack[i];
if (deltaSet && !deltaSet[0].disabled) {
if (deltaSet && !deltaSet[0].ignore) {
while(i < pos - 1) {
var swapped = swapGroups(stack[i], stack[i + 1]);
stack[i] = swapped[0];
@ -191,7 +247,91 @@ UndoManager.rebase = function(stack, pos) {
}
};
var Range = require("./range").Range;
var cmp = Range.comparePoints;
var comparePoints = Range.comparePoints;
function $updateMarkers(delta) {
var isInsert = delta.action == "insert";
var start = delta.start;
var end = delta.end;
var rowShift = (end.row - start.row) * (isInsert ? 1 : -1);
var colShift = (end.column - start.column) * (isInsert ? 1 : -1);
if (isInsert) end = start;
for (var i in this.marks) {
var point = this.marks[i];
var cmp = comparePoints(point, start);
if (cmp < 0) {
continue; // delta starts after the range
}
if (cmp === 0) {
if (isInsert) {
if (point.bias == 1) {
cmp = 1;
}
else {
point.bias == -1;
continue;
}
}
}
var cmp2 = isInsert ? cmp : comparePoints(point, end);
if (cmp2 > 0) {
point.row += rowShift;
point.column += point.row == end.row ? colShift : 0;
continue;
}
if (!isInsert && cmp2 <= 0) {
point.row = start.row;
point.column = start.column;
if (cmp2 === 0)
point.bias = 1;
}
}
}
function clonePos(pos) {
return {row: pos.row,column: pos.column};
}
function cloneDelta(d) {
return {
start: clonePos(d.start),
end: clonePos(d.end),
action: d.action,
lines: d.lines.slice()
};
}
function stringifyDelta(d) {
d = d || this;
if (Array.isArray(d)) {
return d.map(stringifyDelta).join("\n");
}
var type = "";
if (d.action) {
type = d.action == "insert" ? "+" : "-";
type += "[" + d.lines + "]";
} else if (d.value) {
if (Array.isArray(d.value)) {
type = d.value.map(stringifyRange).join("\n");
} else {
type = stringifyRange(d.value);
}
}
if (d.start) {
type += stringifyRange(d);
}
if (d.id || d.rev) {
type += "\t(" + (d.id || d.rev) + ")";
}
return type;
}
function stringifyRange(r) {
return r.start.row + ":" + r.start.column
+ "=>" + r.end.row + ":" + r.end.column;
}
/*
* i i d1 d2
* |/ |/ d2.s >= d1.e shift(d2, d1, -1)
@ -213,8 +353,7 @@ UndoManager.rebase = function(stack, pos) {
* d2.e <= d1.s shift(d1, d2, -1)
* d2.s < d1.s < d2.e // can split
*/
var Range = require("./range").Range;
var cmp = Range.comparePoints;
function swap(d1, d2) {
var i1 = d1.action == "insert";
var i2 = d2.action == "insert";
@ -253,36 +392,6 @@ function swap(d1, d2) {
}
}
return [d2, d1];
function shift(d1, d2, dir) {
shiftPos(d1.start, d2.start, d2.end, dir);
shiftPos(d1.end, d2.start, d2.end, dir);
}
function shiftPos(pos, start, end, dir) {
if (pos.row == (dir == 1 ? start : end).row) {
pos.column += dir * (end.column - start.column);
}
pos.row += dir * (end.row - start.row);
}
}
function clonePos(pos) {
return {row: pos.row,column: pos.column};
}
function cloneDelta(d) {
return {
start: clonePos(d.start),
end: clonePos(d.end),
action: d.action,
lines: d.lines.slice(),
toString: logDelta
};
}
function logDelta(d) {
d = d || this;
var type = d.action == "insert" ? "+" : "-";
return type + "[" + d.lines + "]"
+ d.start.row + ":" + d.start.column + "=>"
+ d.end.row + ":" + d.end.column;
}
function swapGroups(ds1, ds2) {
for (var i = ds1.length; i--; ) {
@ -305,6 +414,129 @@ function swapGroups(ds1, ds2) {
return [ds2, ds1];
}
/*
d2 xform(d1, c1) = [d2, c2]
o<---o xform(c1, d1) = [c2, d2]
c2 | | d1
o<---o
c1
*/
function xform(d1, c1) {
var i1 = d1.action == "insert";
var i2 = c1.action == "insert";
if (i1 && i2) {
if (cmp(d1.start, c1.start) < 0) {
shift(c1, d1, 1);
} else {
shift(d1, c1, 1);
}
} else if (i1 && !i2) {
if (cmp(d1.start, c1.end) >= 0) {
shift(d1, c1, -1);
} else if (cmp(d1.start, c1.start) <= 0) {
shift(c1, d1, +1);
} else {
shift(d1, Range.fromPoints(c1.start, d1.start), -1);
shift(c1, d1, +1);
}
} else if (!i1 && i2) {
if (cmp(c1.start, d1.end) >= 0) {
shift(c1, d1, -1);
} else if (cmp(c1.start, d1.start) <= 0) {
shift(d1, c1, +1);
} else {
shift(c1, Range.fromPoints(d1.start, c1.start), -1);
shift(d1, c1, +1);
}
} else if (!i1 && !i2) {
if (cmp(c1.start, d1.end) >= 0) {
shift(c1, d1, -1);
} else if (cmp(c1.end, d1.start) <= 0) {
shift(d1, c1, -1);
} else {
var before, after;
if (cmp(d1.start, c1.start) < 0) {
before = d1;
d1 = splitDelta(d1, c1.start);
}
if (cmp(d1.end, c1.end) > 0) {
after = splitDelta(d1, c1.end);
}
shiftPos(c1.end, d1.start, d1.end, -1);
if (after && !before) {
d1.lines = after.lines;
d1.start = after.start;
d1.end = after.end;
after = d1;
}
return [c1, before, after].filter(Boolean);
}
}
return [c1, d1];
}
function shift(d1, d2, dir) {
shiftPos(d1.start, d2.start, d2.end, dir);
shiftPos(d1.end, d2.start, d2.end, dir);
}
function shiftPos(pos, start, end, dir) {
if (pos.row == (dir == 1 ? start : end).row) {
pos.column += dir * (end.column - start.column);
}
pos.row += dir * (end.row - start.row);
}
function splitDelta(c, pos) {
var lines = c.lines;
var end = c.end;
c.end = clonePos(pos);
var rowsBefore = c.end.row - c.start.row;
var otherLines = lines.splice(rowsBefore, lines.length);
var col = rowsBefore ? pos.column : pos.column - c.start.column;
lines.push(otherLines[0].substring(0, col));
otherLines[0] = otherLines[0].substr(col) ;
var rest = {
start: clonePos(pos),
end: end,
lines: otherLines,
action: c.action
};
return rest;
}
function moveDeltasByOne(redoStack, d) {
d = cloneDelta(d);
for (var j = redoStack.length; j--;) {
var deltaSet = redoStack[j];
for (var i = deltaSet.length; i--;) {
var x = deltaSet[i];
var xformed = xform(x, d);
d = xformed[0];
if (xformed.length != 2) {
if (xformed[2]) {
redoStack.splice(i + 1, 1, xformed[1], xformed[2]);
i++;
} else if (!xformed[1]) {
redoStack.splice(i, 1);
i--;
}
}
}
}
return redoStack;
}
function rebaseRedoStack(redoStack, deltaSets) {
for (var i = 0; i < deltaSets.length; i++) {
var deltas = deltaSets[i];
for (var j = 0; j < deltas.length; j++) {
moveDeltasByOne(redoStack, deltas[j]);
}
}
}
UndoManager.swapGroups = swapGroups;
exports.UndoManager = UndoManager;
});

Wyświetl plik

@ -60,7 +60,7 @@
"c9.ide.language.javascript.tern": "#7aab8b0b6a",
"c9.ide.language.javascript.infer": "#cfec494a3c",
"c9.ide.language.jsonalyzer": "#21b64e5820",
"c9.ide.collab": "#749c26b859",
"c9.ide.collab": "#da4d09ae6a",
"c9.ide.local": "#2bfd7ff051",
"c9.ide.find": "#6cc6d3379d",
"c9.ide.find.infiles": "#72582de3cd",