remove delta.range
This commit is contained in:
parent
b5af2c898c
commit
4299db01bd
15 changed files with 136 additions and 155 deletions
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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') {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue