remove delta.range

This commit is contained in:
nightwing 2014-01-18 17:24:11 +04:00
commit 4299db01bd
15 changed files with 136 additions and 155 deletions

View file

@ -111,14 +111,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
} }
this.$getTransformedPoint = function (delta, point) { this.$getTransformedPoint = function (delta, point) {
// Get delta info. // Get delta info.
var moveIfEqual = this.$insertRight; var moveIfEqual = this.$insertRight;
var deltaIsInsert = (delta.action == 'insert') var deltaIsInsert = (delta.action == "insert")
var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.column - delta.range.start.column); var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
var deltaStart = delta.range.start; var deltaStart = delta.start;
var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. var deltaEnd = (deltaIsInsert ? deltaStart : delta.end); // Collapse insert range.
// DELTA AFTER POINT: No change needed. // DELTA AFTER POINT: No change needed.
if ($pointsInOrder(point, deltaStart, moveIfEqual)) { if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
@ -137,8 +136,8 @@ var Anchor = exports.Anchor = function(doc, row, column) {
} }
// DELTA ENVELOPS POINT (delete only): Move point to delta start. // DELTA ENVELOPS POINT (delete only): Move point to delta start.
if (delta.action != 'remove') if (delta.action != "remove")
throw 'Delete action expected.'; throw "Delete action expected.";
return { return {
row: deltaStart.row, row: deltaStart.row,
@ -181,7 +180,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
}; };
/** /**
* When called, the `'change'` event listener is removed. * When called, the `"change"` event listener is removed.
* *
**/ **/
this.detach = function() { this.detach = function() {

View file

@ -41,12 +41,12 @@ function splitLine (docLines, position) {
function joinLineWithNext(docLines, row) { function joinLineWithNext(docLines, row) {
docLines[row] += docLines[row + 1]; docLines[row] += docLines[row + 1];
docLines.splice(row + 1, 1); docLines.splice(row + 1, 1);
} }
function throwDeltaError(delta, errorText){ function throwDeltaError(delta, errorText){
console.log('Invalid Delta:', delta); console.log("Invalid Delta:", delta);
throw 'Invalid Delta: ' + errorText; throw "Invalid Delta: " + errorText;
} }
function positionInDocument(docLines, position) { function positionInDocument(docLines, position) {
@ -57,32 +57,32 @@ function positionInDocument(docLines, position) {
function validateDelta(docLines, delta) { function validateDelta(docLines, delta) {
// Validate action string. // Validate action string.
if (delta.action != 'insert' && delta.action != 'remove') if (delta.action != "insert" && delta.action != "remove")
throwDeltaError(delta, 'delta.action must be "insert" or "remove"'); throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
// Validate lines type. // Validate lines type.
if (!(delta.lines instanceof Array)) if (!(delta.lines instanceof Array))
throwDeltaError(delta, 'delta.lines must be an Array'); throwDeltaError(delta, "delta.lines must be an Array");
// Validate range type. // Validate range type.
if (!(delta.range instanceof Range)) if (!delta.start || !delta.end)
throwDeltaError(delta, 'delta.range must be an instance of the Range class'); throwDeltaError(delta, "delta.start/end must be an present");
// Validate that the start point is contained in the document. // Validate that the start point is contained in the document.
var start = delta.range.start; var start = delta.start;
if (!positionInDocument(docLines, delta.range.start)) if (!positionInDocument(docLines, delta.start))
throwDeltaError(delta, 'delta.range.start must be contained in document'); throwDeltaError(delta, "delta.start must be contained in document");
// Validate that the end point is contained in the document (remove deltas only). // Validate that the end point is contained in the document (remove deltas only).
var end = delta.range.end; var end = delta.end;
if (delta.action == 'remove' && !positionInDocument(docLines, end)) if (delta.action == "remove" && !positionInDocument(docLines, end))
throwDeltaError(delta, 'delta.range.end must contained in document for "remove" actions'); throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
// Validate that the .range size matches the .lines size. // Validate that the .range size matches the .lines size.
var numRangeRows = end.row - start.row; var numRangeRows = end.row - start.row;
var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
throwDeltaError(delta, 'delta.range must match delta lines'); throwDeltaError(delta, "delta.range must match delta lines");
} }
exports.applyDelta = function(docLines, delta, doNotValidate) { exports.applyDelta = function(docLines, delta, doNotValidate) {
@ -92,21 +92,21 @@ exports.applyDelta = function(docLines, delta, doNotValidate) {
validateDelta(docLines, delta); validateDelta(docLines, delta);
// Apply delta. // Apply delta.
if (delta.range.start.row == delta.range.end.row) { if (delta.start.row == delta.end.row) {
// Apply single-line delta. // Apply single-line delta.
// Note: The multi-line code below correctly handle single-line // Note: The multi-line code below correctly handle single-line
// deltas too, but we need to short-circuit for speed. // deltas too, but we need to short-circuit for speed.
var row = delta.range.start.row; var row = delta.start.row;
var startColumn = delta.range.start.column; var startColumn = delta.start.column;
var endColumn = delta.range.end.column; var endColumn = delta.end.column;
var line = docLines[row]; var line = docLines[row];
switch (delta.action) { switch (delta.action) {
case 'insert': case "insert":
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
break; break;
case 'remove': case "remove":
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
break; break;
} }
@ -114,22 +114,21 @@ exports.applyDelta = function(docLines, delta, doNotValidate) {
// Apply multi-line delta. // Apply multi-line delta.
switch (delta.action) { switch (delta.action) {
case "insert":
case 'insert': splitLine(docLines, delta.start);
splitLine(docLines, delta.range.start); docLines.splice.apply(docLines, [delta.start.row + 1, 0].concat(delta.lines));
docLines.splice.apply(docLines, [delta.range.start.row + 1, 0].concat(delta.lines)); joinLineWithNext(docLines, delta.start.row);
joinLineWithNext(docLines, delta.range.start.row); joinLineWithNext(docLines, delta.end.row);
joinLineWithNext(docLines, delta.range.end.row);
break; break;
case 'remove': case "remove":
splitLine(docLines, delta.range.end); splitLine(docLines, delta.end);
splitLine(docLines, delta.range.start); splitLine(docLines, delta.start);
docLines.splice( docLines.splice(
delta.range.start.row + 1, // Where to start deleting delta.start.row + 1, // Where to start deleting
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. delta.end.row - delta.start.row + 1 // Num lines to delete.
); );
joinLineWithNext(docLines, delta.range.start.row); joinLineWithNext(docLines, delta.start.row);
break; break;
} }
} }

View file

@ -177,13 +177,12 @@ var BackgroundTokenizer = function(tokenizer, editor) {
} }
this.$updateOnChange = function(delta) { this.$updateOnChange = function(delta) {
var range = delta.range; var startRow = delta.start.row;
var startRow = range.start.row; var len = delta.end.row - startRow;
var len = range.end.row - startRow;
if (len === 0) { if (len === 0) {
this.lines[startRow] = null; this.lines[startRow] = null;
} else if (delta.action == 'remove') { } else if (delta.action == "remove") {
this.lines.splice(startRow, len + 1, null); this.lines.splice(startRow, len + 1, null);
this.states.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null);
} else { } else {

View file

@ -13,7 +13,7 @@ var EventEmitter = require("../lib/event_emitter").EventEmitter;
/** /**
* new CommandManager(platform, commands) * new CommandManager(platform, commands)
* @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'` * @param {String} platform Identifier for the platform; must be either `"mac"` or `"win"`
* @param {Array} commands A list of commands * @param {Array} commands A list of commands
* *
**/ **/
@ -33,7 +33,7 @@ oop.inherits(CommandManager, HashHandler);
oop.implement(this, EventEmitter); oop.implement(this, EventEmitter);
this.exec = function(command, editor, args) { this.exec = function(command, editor, args) {
if (typeof command === 'string') if (typeof command === "string")
command = this.commands[command]; command = this.commands[command];
if (!command) if (!command)

View file

@ -53,7 +53,7 @@ var Anchor = require("./anchor").Anchor;
**/ **/
var Document = function(textOrLines) { var Document = function(textOrLines) {
this.$lines = ['']; this.$lines = [""];
// There has to be one line at least in the document. If you pass an empty // There has to be one line at least in the document. If you pass an empty
// string to the insert function, nothing will happen. Workaround. // string to the insert function, nothing will happen. Workaround.
@ -99,7 +99,7 @@ var Document = function(textOrLines) {
}; };
/** /**
* Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters. * Splits a string of text on any newline (`\n`) or carriage-return (`\r`) characters.
* *
* @method $split * @method $split
* @param {String} text The text to work with * @param {String} text The text to work with
@ -225,12 +225,9 @@ var Document = function(textOrLines) {
this.getLinesForRange = function(range) { this.getLinesForRange = function(range) {
var lines; var lines;
if (range.start.row == range.end.row) { if (range.start.row == range.end.row) {
// Handle a single-line range. // Handle a single-line range.
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
} else { } else {
// Handle a multi-line range. // Handle a multi-line range.
lines = this.getLines(range.start.row, range.end.row); lines = this.getLines(range.start.row, range.end.row);
lines[0] = (lines[0] || "").substring(range.start.column); lines[0] = (lines[0] || "").substring(range.start.column);
@ -254,7 +251,6 @@ var Document = function(textOrLines) {
}; };
this.$getClippedRange = function(range) { this.$getClippedRange = function(range) {
// Get Range object. // Get Range object.
if (!range instanceof Range) if (!range instanceof Range)
range = Range.fromPoints(range.start, range.end); range = Range.fromPoints(range.start, range.end);
@ -267,16 +263,16 @@ var Document = function(textOrLines) {
// Deprecated methods retained for backwards compatibility. // Deprecated methods retained for backwards compatibility.
this.insertLines = function(row, lines) { this.insertLines = function(row, lines) {
console.warn('Use of document.insertLines is deprecated. Use the insertFullLines method instead.'); console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
return this.insertFullLines(row, lines); return this.insertFullLines(row, lines);
}; };
this.removeLines = function(firstRow, lastRow) { this.removeLines = function(firstRow, lastRow) {
console.warn('Use of document.removeLines is deprecated. Use the removeFullLines method instead.'); console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
return this.removeFullLines(firstRow, lastRow); return this.removeFullLines(firstRow, lastRow);
}; };
this.insertNewLine = function(position) { this.insertNewLine = function(position) {
console.warn('Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.");
return this.insertMergedLines(position, ['', '']); return this.insertMergedLines(position, ["", ""]);
}; };
/** /**
@ -287,7 +283,6 @@ var Document = function(textOrLines) {
* *
**/ **/
this.insert = function(position, text) { this.insert = function(position, text) {
// Only detect new lines if the document has no line break yet. // Only detect new lines if the document has no line break yet.
if (this.getLength() <= 1) if (this.getLength() <= 1)
this.$detectNewLine(text); this.$detectNewLine(text);
@ -296,7 +291,7 @@ var Document = function(textOrLines) {
}; };
/** /**
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event. * Inserts `text` into the `position` at the current row. This method also triggers the `"change"` event.
* *
* This differs from the `insert` method in two ways: * This differs from the `insert` method in two ways:
* 1. This does NOT handle newline characters (single-line text only). * 1. This does NOT handle newline characters (single-line text only).
@ -310,7 +305,6 @@ var Document = function(textOrLines) {
* ``` * ```
**/ **/
this.insertInLine = function(position, text) { this.insertInLine = function(position, text) {
// Calculate insertion range end point. // Calculate insertion range end point.
this.$clipPosition(position); this.$clipPosition(position);
var endPoint = { var endPoint = {
@ -318,10 +312,12 @@ var Document = function(textOrLines) {
column : position.column + text.length column : position.column + text.length
}; };
var range = Range.fromPoints(position, endPoint);
// Apply delta (emits change). // Apply delta (emits change).
this.applyDelta({ this.applyDelta({
action: "insert", action: "insert",
range: Range.fromPoints(position, endPoint), start: range.start,
end: range.end,
lines: [text] lines: [text]
}, true /*doNotValidate*/); }, true /*doNotValidate*/);
@ -346,7 +342,7 @@ var Document = function(textOrLines) {
**/ **/
/** /**
* Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `'change'` event. * Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `"change"` event.
* @param {Number} row The index of the row to insert at * @param {Number} row The index of the row to insert at
* @param {Array} lines An array of strings * @param {Array} lines An array of strings
* @returns {Object} Contains the final row and column, like this: * @returns {Object} Contains the final row and column, like this:
@ -368,11 +364,11 @@ var Document = function(textOrLines) {
var column = 0; var column = 0;
if (row < this.getLength()) { if (row < this.getLength()) {
// Insert before the specified row. // Insert before the specified row.
lines = lines.concat(['']); lines = lines.concat([""]);
column = 0; column = 0;
} else { } else {
// Insert after the last row in the document. // Insert after the last row in the document.
lines = [''].concat(lines); lines = [""].concat(lines);
row--; row--;
column = this.$lines[row].length; column = this.$lines[row].length;
} }
@ -382,7 +378,7 @@ var Document = function(textOrLines) {
}; };
/** /**
* Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `'change'` event. * Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `"change"` event.
* @param {Number} row The index of the row to insert at * @param {Number} row The index of the row to insert at
* @param {Array} lines An array of strings * @param {Array} lines An array of strings
* @returns {Object} Contains the final row and column, like this: * @returns {Object} Contains the final row and column, like this:
@ -396,7 +392,6 @@ var Document = function(textOrLines) {
* *
**/ **/
this.insertMergedLines = function(position, lines) { this.insertMergedLines = function(position, lines) {
// Calculate insertion range end point. // Calculate insertion range end point.
this.$clipPosition(position); this.$clipPosition(position);
var endPoint = { var endPoint = {
@ -407,7 +402,8 @@ var Document = function(textOrLines) {
// Apply delta (emits change). // Apply delta (emits change).
this.applyDelta({ this.applyDelta({
action: "insert", action: "insert",
range: Range.fromPoints(position, endPoint), start: position,
end: endPoint,
lines: lines lines: lines
}); });
@ -421,19 +417,19 @@ var Document = function(textOrLines) {
* *
**/ **/
this.remove = function(range) { this.remove = function(range) {
// Apply delta (emits change). // Apply delta (emits change).
range = this.$getClippedRange(range); range = this.$getClippedRange(range);
this.applyDelta({ this.applyDelta({
action: 'remove', action: "remove",
range: range, start: range.start,
end: range.end,
lines: this.getLinesForRange(range), lines: this.getLinesForRange(range),
}); });
return range.start; return range.start;
}; };
/** /**
* Removes the specified columns from the `row`. This method also triggers the `'change'` event. * Removes the specified columns from the `row`. This method also triggers the `"change"` event.
* @param {Number} row The row to remove from * @param {Number} row The row to remove from
* @param {Number} startColumn The column to start removing at * @param {Number} startColumn The column to start removing at
* @param {Number} endColumn The column to stop removing at * @param {Number} endColumn The column to stop removing at
@ -441,15 +437,15 @@ var Document = function(textOrLines) {
* *
**/ **/
this.removeInLine = function(row, startColumn, endColumn) { this.removeInLine = function(row, startColumn, endColumn) {
// Calculate deleteion range. // Calculate deleteion range.
var range = new Range(row, startColumn, row, endColumn); var range = new Range(row, startColumn, row, endColumn);
range = this.$getClippedRange(range); range = this.$getClippedRange(range);
// Apply delta (emits change). // Apply delta (emits change).
this.applyDelta({ this.applyDelta({
action: 'remove', action: "remove",
range: range, start: range.start,
end: range.end,
lines: this.getLinesForRange(range), lines: this.getLinesForRange(range),
}, true /*doNotValidate*/); }, true /*doNotValidate*/);
@ -457,14 +453,13 @@ var Document = function(textOrLines) {
}; };
/** /**
* Removes a range of full lines. This method also triggers the `'change'` event. * Removes a range of full lines. This method also triggers the `"change"` event.
* @param {Number} firstRow The first row to be removed * @param {Number} firstRow The first row to be removed
* @param {Number} lastRow The last row to be removed * @param {Number} lastRow The last row to be removed
* @returns {[String]} Returns all the removed lines. * @returns {[String]} Returns all the removed lines.
* *
**/ **/
this.removeFullLines = function(firstRow, lastRow) { this.removeFullLines = function(firstRow, lastRow) {
// Clip to document. // Clip to document.
firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
@ -485,8 +480,9 @@ var Document = function(textOrLines) {
// Apply delta (emits change). // Apply delta (emits change).
this.applyDelta({ this.applyDelta({
action: 'remove', action: "remove",
range: range, start: range.start,
end: range.end,
lines: this.getLinesForRange(range) lines: this.getLinesForRange(range)
}); });
@ -495,18 +491,19 @@ var Document = function(textOrLines) {
}; };
/** /**
* Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event. * Removes the new line between `row` and the row immediately following it. This method also triggers the `"change"` event.
* @param {Number} row The row to check * @param {Number} row The row to check
* *
**/ **/
this.removeNewLine = function(row) { this.removeNewLine = function(row) {
if (row < this.getLength() - 1 && row >= 0) { if (row < this.getLength() - 1 && row >= 0) {
var range = new Range(row, this.getLine(row).length, row + 1, 0);
// Apply delta (emits change). // Apply delta (emits change).
this.applyDelta({ this.applyDelta({
action: 'remove', action: "remove",
range: new Range(row, this.getLine(row).length, row + 1, 0), start: range.start,
lines: ['', ''] end: range.end,
lines: ["", ""]
}); });
} }
}; };
@ -546,7 +543,7 @@ var Document = function(textOrLines) {
/** /**
* Applies all changes in `deltas` to the document. * Applies all changes in `deltas` to the document.
* @param {Array} deltas An array of delta objects (can include 'insert' and 'remove' actions) * @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
**/ **/
this.applyDeltas = function(deltas) { this.applyDeltas = function(deltas) {
for (var i=0; i<deltas.length; i++) { for (var i=0; i<deltas.length; i++) {
@ -556,7 +553,7 @@ var Document = function(textOrLines) {
/** /**
* Reverts all changes in `deltas` from the document. * Reverts all changes in `deltas` from the document.
* @param {Array} deltas An array of delta objects (can include 'insert' and 'remove' actions) * @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
**/ **/
this.revertDeltas = function(deltas) { this.revertDeltas = function(deltas) {
for (var i=deltas.length-1; i>=0; i--) { for (var i=deltas.length-1; i>=0; i--) {
@ -566,12 +563,11 @@ var Document = function(textOrLines) {
/** /**
* Applies `delta` to the document. * Applies `delta` to the document.
* @param {Object} delta A delta object (can include 'insert' and 'remove' actions) * @param {Object} delta A delta object (can include "insert" and "remove" actions)
**/ **/
this.applyDelta = function(delta, doNotValidate) { this.applyDelta = function(delta, doNotValidate) {
// An empty range is a NOOP. // An empty range is a NOOP.
if (delta.range.isEmpty()) if (!Range.comparePoints(delta.start, delta.end))
return; return;
// Split large insert deltas. This is necessary because: // Split large insert deltas. This is necessary because:
@ -582,37 +578,40 @@ var Document = function(textOrLines) {
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas // delta handling is too slow. If we make delete delta handling faster we can split all large deltas
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
// If we do this, update validateDelta() to limit the number of lines in a delete delta. // If we do this, update validateDelta() to limit the number of lines in a delete delta.
var bIsInsert = delta.action == 'insert'; var bIsInsert = delta.action == "insert";
while (bIsInsert && delta.lines.length > 65001) { while (bIsInsert && delta.lines.length > 65001) {
// Get split deltas. // Get split deltas.
var lines = delta.lines.splice(0, 65000); var lines = delta.lines.splice(0, 65000);
lines.push(''); lines.push("");
var range = new Range(delta.start.row, delta.start.column,
delta.start.row + 65000, 0)
this.applyDelta({ this.applyDelta({
action: delta.action, action: delta.action,
lines: lines, lines: lines,
range: new Range(delta.range.start.row, delta.range.start.column, start: range.start,
delta.range.start.row + 65000, 0) end: range.end,
}); });
// Update remaining delta. // Update remaining delta.
delta.range.start.row += 65000; delta.start.row += 65000;
delta.range.start.column = 0; delta.start.column = 0;
} }
// Apply. // Apply.
applyDelta(this.$lines, delta, doNotValidate); applyDelta(this.$lines, delta, doNotValidate);
this._emit("change", { data: delta }); this._emit("change", { data: delta });
}; };
/** /**
* Reverts `delta` from the document. * Reverts `delta` from the document.
* @param {Object} delta A delta object (can include 'insert' and 'remove' actions) * @param {Object} delta A delta object (can include "insert" and "remove" actions)
**/ **/
this.revertDelta = function(delta) { this.revertDelta = function(delta) {
var range = Range.fromPoints(delta.start, delta.end);
this.applyDelta({ this.applyDelta({
action: (delta.action == 'insert' ? 'remove' : 'insert'), action: (delta.action == "insert" ? "remove" : "insert"),
range: delta.range.clone(), start: range.start,
end: range.end,
lines: delta.lines.slice() lines: delta.lines.slice()
}); });
}; };

View file

@ -253,7 +253,7 @@ var EditSession = function(text, mode) {
var delta = e.data; var delta = e.data;
this.$modified = true; this.$modified = true;
this.$resetRowCache(delta.range.start.row); this.$resetRowCache(delta.start.row);
var removedFolds = this.$updateInternalDataOnChange(e); var removedFolds = this.$updateInternalDataOnChange(e);
if (!this.$fromUndo && this.$undoManager && !delta.ignore) { if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
@ -1247,30 +1247,29 @@ var EditSession = function(text, mode) {
var range, point; var range, point;
var lastDeltaIsInsert = false; var lastDeltaIsInsert = false;
if (isInsert(delta)) { if (isInsert(delta)) {
range = Range.fromPoints(delta.range.start, delta.range.end); range = Range.fromPoints(delta.start, delta.end);
lastDeltaIsInsert = true; lastDeltaIsInsert = true;
} else { } else {
range = Range.fromPoints(delta.range.start, delta.range.start); range = Range.fromPoints(delta.start, delta.start);
lastDeltaIsInsert = false; lastDeltaIsInsert = false;
} }
for (var i = 1; i < deltas.length; i++) { for (var i = 1; i < deltas.length; i++) {
delta = deltas[i]; delta = deltas[i];
if (isInsert(delta)) { if (isInsert(delta)) {
point = delta.range.start; point = delta.start;
if (range.compare(point.row, point.column) == -1) { if (range.compare(point.row, point.column) == -1) {
range.setStart(delta.range.start); range.setStart(point);
} }
point = delta.range.end; point = delta.end;
if (range.compare(point.row, point.column) == 1) { if (range.compare(point.row, point.column) == 1) {
range.setEnd(delta.range.end); range.setEnd(point);
} }
lastDeltaIsInsert = true; lastDeltaIsInsert = true;
} else { } else {
point = delta.range.start; point = delta.start;
if (range.compare(point.row, point.column) == -1) { if (range.compare(point.row, point.column) == -1) {
range = range = Range.fromPoints(delta.start, delta.start);
Range.fromPoints(delta.range.start, delta.range.start);
} }
lastDeltaIsInsert = false; lastDeltaIsInsert = false;
} }
@ -1676,8 +1675,8 @@ var EditSession = function(text, mode) {
this.$updateInternalDataOnChange = function(e) { this.$updateInternalDataOnChange = function(e) {
var useWrapMode = this.$useWrapMode; var useWrapMode = this.$useWrapMode;
var action = e.data.action; var action = e.data.action;
var start = e.data.range.start; var start = e.data.start;
var end = e.data.range.end; var end = e.data.end;
var firstRow = start.row; var firstRow = start.row;
var lastRow = end.row; var lastRow = end.row;
var len = lastRow - firstRow; var len = lastRow - firstRow;
@ -1685,11 +1684,11 @@ var EditSession = function(text, mode) {
this.$updating = true; this.$updating = true;
if (len != 0) { if (len != 0) {
if (action == 'remove') { if (action == "remove") {
this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
var foldLines = this.$foldData; var foldLines = this.$foldData;
removedFolds = this.getFoldsInRange(e.data.range); removedFolds = this.getFoldsInRange(e.data);
this.removeFolds(removedFolds); this.removeFolds(removedFolds);
var foldLine = this.getFoldLine(end.row); var foldLine = this.getFoldLine(end.row);
@ -1759,10 +1758,10 @@ var EditSession = function(text, mode) {
} else { } else {
// Realign folds. E.g. if you add some new chars before a fold, the // Realign folds. E.g. if you add some new chars before a fold, the
// fold should "move" to the right. // fold should "move" to the right.
len = Math.abs(e.data.range.start.column - e.data.range.end.column); len = Math.abs(e.data.start.column - e.data.end.column);
if (action == 'remove') { if (action == "remove") {
// Get all the folds in the change range and remove them. // Get all the folds in the change range and remove them.
removedFolds = this.getFoldsInRange(e.data.range); removedFolds = this.getFoldsInRange(e.data);
this.removeFolds(removedFolds); this.removeFolds(removedFolds);
len = -len; len = -len;

View file

@ -830,9 +830,8 @@ function Folding() {
this.updateFoldWidgets = function(e) { this.updateFoldWidgets = function(e) {
var delta = e.data; var delta = e.data;
var range = delta.range; var firstRow = delta.start.row;
var firstRow = range.start.row; var len = delta.end.row - firstRow;
var len = range.end.row - firstRow;
if (len === 0) { if (len === 0) {
this.foldWidgets[firstRow] = null; this.foldWidgets[firstRow] = null;

View file

@ -607,11 +607,10 @@ var Editor = function(renderer, session) {
* *
**/ **/
this.onDocumentChange = function(e) { this.onDocumentChange = function(e) {
// Rerender and emit "change" event. // Rerender and emit "change" event.
var range = e.data.range; var delta = e.data;
var lastRow = (range.start.row == range.end.row ? range.end.row : Infinity); var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
this.renderer.updateLines(range.start.row, lastRow); this.renderer.updateLines(delta.start.row, lastRow);
this._signal("change", e); this._signal("change", e);
// Update cursor because tab characters can influence the cursor position. // Update cursor because tab characters can influence the cursor position.

View file

@ -45,7 +45,7 @@ var ElasticTabstopsLite = function(editor) {
recordChanges = true; recordChanges = true;
}; };
this.onChange = function(e) { this.onChange = function(e) {
var range = e.data.range var range = e.data;
if (recordChanges) { if (recordChanges) {
if (changedRows.indexOf(range.start.row) == -1) if (changedRows.indexOf(range.start.row) == -1)
changedRows.push(range.start.row); changedRows.push(range.start.row);

View file

@ -94,11 +94,9 @@ module.exports = {
editor.removeLines(); editor.removeLines();
util.insertMode(editor); util.insertMode(editor);
} }
break; break;
default: default:
if (range) { if (range) {
// range.end.column ++; // range.end.column ++;
editor.session.remove(range); editor.session.remove(range);
util.insertMode(editor); util.insertMode(editor);

View file

@ -103,9 +103,8 @@ var Gutter = function(parentEl) {
if (!this.$annotations.length) if (!this.$annotations.length)
return; return;
var delta = e.data; var delta = e.data;
var range = delta.range; var firstRow = delta.start.row;
var firstRow = range.start.row; var len = delta.end.row - firstRow;
var len = range.end.row - firstRow;
if (len === 0) { if (len === 0) {
// do nothing // do nothing
} else if (delta.action == 'remove') { } else if (delta.action == 'remove') {

View file

@ -150,7 +150,6 @@ exports.getMatchOffsets = function(string, regExp) {
/* deprecated */ /* deprecated */
exports.deferredCall = function(fcn) { exports.deferredCall = function(fcn) {
var timer = null; var timer = null;
var callback = function() { var callback = function() {
timer = null; timer = null;

View file

@ -119,9 +119,8 @@ function LineWidgets(session) {
if (!lineWidgets) return; if (!lineWidgets) return;
var delta = e.data; var delta = e.data;
var range = delta.range; var startRow = delta.start.row;
var startRow = range.start.row; var len = delta.end.row - startRow;
var len = range.end.row - startRow;
if (len === 0) { if (len === 0) {
// return // return

View file

@ -178,29 +178,31 @@ var UndoManager = function() {
function $serializeDelta(delta){ function $serializeDelta(delta){
return { return {
action: delta.action, action: delta.action,
range: delta.range, start: delta.start,
lines: (delta.lines.length == 1 ? null : delta.lines), end: delta.end,
text: (delta.lines.length == 1 ? delta.lines[0] : null ), lines: delta.lines.length == 1 ? null : delta.lines,
text: delta.lines.length == 1 ? delta.lines[0] : null,
}; };
} }
function $deserializeDelta(delta) { function $deserializeDelta(delta) {
return { return {
action: delta.action, action: delta.action,
range: delta.range, start: delta.start,
lines: (delta.text === null ? delta.lines : [delta.text]) end: delta.end,
lines: delta.lines || [delta.text]
}; };
} }
function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) {
var deltaSets_new = new Array(deltaSets_old.length); var deltaSets_new = new Array(deltaSets_old.length);
for (var i in deltaSets_old) { for (var i = 0; i < deltaSets_old.length; i++) {
var deltaSet_old = deltaSets_old[i]; var deltaSet_old = deltaSets_old[i];
var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};
for (var i_ in deltaSet_old.deltas) { for (var j = 0; j < deltaSet_old.deltas.length; j++) {
var delta_old = deltaSet_old.deltas[i_]; var delta_old = deltaSet_old.deltas[j];
deltaSet_new.deltas[i_] = fnGetModifiedDelta(delta_old); deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old);
} }
deltaSets_new[i] = deltaSet_new; deltaSets_new[i] = deltaSet_new;

View file

@ -13,16 +13,7 @@ var Mirror = exports.Mirror = function(sender) {
var _self = this; var _self = this;
sender.on("change", function(e) { sender.on("change", function(e) {
doc.applyDeltas(e.data);
// Convert delta.range back into a Range instance since
// window.onMessage loses non-primitive data. See http://jsfiddle.net/nqJfw/1/.
var deltas = e.data;
for (var i in deltas) {
var delta = deltas[i];
delta.range = Range.fromPoints(delta.range.start, delta.range.end);
}
doc.applyDeltas(deltas);
if (_self.$timeout) if (_self.$timeout)
return deferredUpdate.schedule(_self.$timeout); return deferredUpdate.schedule(_self.$timeout);
_self.onUpdate(); _self.onUpdate();