Skip to content

Commit

Permalink
continue refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
nightwing committed Feb 14, 2014
1 parent 46f3d77 commit 6b60bcb
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 134 deletions.
45 changes: 17 additions & 28 deletions lib/ace/apply_delta.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function positionInDocument(docLines, position) {
}

function validateDelta(docLines, delta) {

// Validate action string.
if (delta.action != "insert" && delta.action != "remove")
throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
Expand Down Expand Up @@ -73,47 +72,37 @@ function validateDelta(docLines, delta) {
}

exports.applyDelta = function(docLines, delta, doNotValidate) {

// Validate delta.
if (!doNotValidate)
validateDelta(docLines, delta);

var row = delta.start.row;
var startColumn = delta.start.column;
var line = docLines[row];
// Apply delta.
if (row == delta.end.row) {
// Apply single-line delta.
// Note: The multi-line code below correctly handle single-line
// deltas too, but we need to short-circuit for speed.
var endColumn = delta.end.column;
switch (delta.action) {
case "insert":
switch (delta.action) {
case "insert":
var lines = delta.lines;
if (lines.length === 1) {
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
break;
case "remove":
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
break;
}
} else {
// Apply multi-line delta.
switch (delta.action) {
case "insert":
} else {
var line = docLines[row];
var args = [row, 1].concat(delta.lines);
docLines.splice.apply(docLines, args);
docLines[row] = line.substring(0, startColumn) + docLines[row];
docLines[row + delta.lines.length - 1] += line.substring(startColumn);
break;
case "remove":
var endRow
}
break;
case "remove":
var endColumn = delta.end.column;
var endRow = delta.end.row;
if (row === endRow) {
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
} else {
docLines.splice(
row, // Where to start deleting
delta.end.row - delta.start.row + 1, // Num lines to delete.
line.substring(0, startColumn) + docLines[delta.end.row].substring(delta.end.column)
row, endRow - row + 1,
line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
);
break;
}
}
break;
}
}
});
155 changes: 76 additions & 79 deletions lib/ace/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@ var Anchor = require("./anchor").Anchor;

/**
* Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s.
*
* At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
*
* @class Document
**/

/**
/**
*
* Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty.
* @param {String | Array} text The starting text
Expand Down Expand Up @@ -76,9 +75,9 @@ var Document = function(textOrLines) {
* @param {String} text The text to use
**/
this.setValue = function(text) {
var len = this.getLength();
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
this.insert({row: 0, column:0}, text);
var len = this.getLength() - 1;
this.remove(new Range(0, 0, len, this.getLine(len).length));
this.insert({row: 0, column: 0}, text);
};

/**
Expand Down Expand Up @@ -224,7 +223,7 @@ var Document = function(textOrLines) {
**/
this.getLinesForRange = function(range) {
var lines;
if (range.start.row == range.end.row) {
if (range.start.row === range.end.row) {
// Handle a single-line range.
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
} else {
Expand All @@ -238,29 +237,6 @@ var Document = function(textOrLines) {
return lines;
};

this.$clipPosition = function(position) {
var length = this.getLength();
if (position.row >= length) {
position.row = Math.max(0, length - 1);
position.column = this.getLine(length - 1).length;
} else {
position.row = Math.max(0, position.row);
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
}
return position;
};

this.$getClippedRange = function(range) {
// Get Range object.
if (!range instanceof Range)
range = Range.fromPoints(range.start, range.end);

// Return clipped range.
this.$clipPosition(range.start);
this.$clipPosition(range.end);
return range;
};

// Deprecated methods retained for backwards compatibility.
this.insertLines = function(row, lines) {
console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
Expand Down Expand Up @@ -305,25 +281,54 @@ var Document = function(textOrLines) {
* ```
**/
this.insertInLine = function(position, text) {
// Calculate insertion range end point.
this.$clipPosition(position);
var endPoint = {
row : position.row,
column : position.column + text.length
};
var start = this.clippedPos(position.row, position.column);
var end = this.pos(position.row, position.column + text.length);

var range = Range.fromPoints(position, endPoint);
// Apply delta (emits change).
this.applyDelta({
action: "insert",
start: range.start,
end: range.end,
start: start,
end: end,
lines: [text]
}, true /*doNotValidate*/);
}, true);

return endPoint;
return this.clonePos(end);
};

this.clippedPos = function(row, column) {
var length = this.getLength();
if (row === undefined) {
row = length;
} else if (row < 0) {
row = 0;
} else if (row >= length) {
row = length - 1;
column = undefined
}
var line = this.getLine(row);
column = Math.min(Math.max(column, 0), line.length);
return {row: row, column: column};
};

this.clonePos = function(pos) {
return {row: pos.row, column: pos.column};
};

this.pos = function(row, column) {
return {row: row, column: column};
};

this.$clipPosition = function(position) {
var length = this.getLength();
if (position.row >= length) {
position.row = Math.max(0, length - 1);
position.column = this.getLine(length - 1).length;
} else {
position.row = Math.max(0, position.row);
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
}
return position;
};

/**
* Fires whenever the document changes.
*
Expand Down Expand Up @@ -392,14 +397,12 @@ var Document = function(textOrLines) {
*
**/
this.insertMergedLines = function(position, lines) {
// Calculate insertion range end point.
this.$clipPosition(position);
var endPoint = {
row : position.row + lines.length - 1,
column : (lines.length == 1 ? position.column : 0) + lines[lines.length - 1].length
};

// Apply delta (emits change).
this.applyDelta({
action: "insert",
start: position,
Expand All @@ -417,15 +420,14 @@ var Document = function(textOrLines) {
*
**/
this.remove = function(range) {
// Apply delta (emits change).
range = this.$getClippedRange(range);
var start = this.clippedPos(range.start.row, range.start.column);
this.applyDelta({
action: "remove",
start: range.start,
end: range.end,
start: start,
end: this.clippedPos(range.end.row, range.end.column),
lines: this.getLinesForRange(range),
});
return range.start;
return this.clonePos(start);
};

/**
Expand All @@ -437,19 +439,16 @@ var Document = function(textOrLines) {
*
**/
this.removeInLine = function(row, startColumn, endColumn) {
// Calculate deleteion range.
var range = new Range(row, startColumn, row, endColumn);
range = this.$getClippedRange(range);
var start = this.clippedPos(row, startColumn);

// Apply delta (emits change).
this.applyDelta({
action: "remove",
start: range.start,
end: range.end,
start: start,
end: this.clippedPos(row, endColumn),
lines: this.getLinesForRange(range),
}, true /*doNotValidate*/);
}, true);

return range.start;
return this.clonePos(start);
};

/**
Expand Down Expand Up @@ -478,7 +477,6 @@ var Document = function(textOrLines) {
// Store delelted lines with bounding newlines ommitted (maintains previous behavior).
var deletedLines = this.$lines.slice(firstRow, lastRow + 1);

// Apply delta (emits change).
this.applyDelta({
action: "remove",
start: range.start,
Expand All @@ -496,13 +494,11 @@ var Document = function(textOrLines) {
*
**/
this.removeNewLine = function(row) {
if (row < this.getLength() - 1 && row >= 0) {
var range = new Range(row, this.getLine(row).length, row + 1, 0);
// Apply delta (emits change).
if (row < this.getLength() - 1 && row >= 0) {
this.applyDelta({
action: "remove",
start: range.start,
end: range.end,
start: this.pos(row, this.getLine(row).length),
end: this.pos(row + 1, 0),
lines: ["", ""]
});
}
Expand Down Expand Up @@ -566,10 +562,21 @@ var Document = function(textOrLines) {
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
**/
this.applyDelta = function(delta, doNotValidate) {
var isInsert = delta.action == "insert";
// An empty range is a NOOP.
if (!Range.comparePoints(delta.start, delta.end))
if (isInsert ? !delta.lines.length
: !Range.comparePoints(delta.start, delta.end))
return;

if (isInsert && delta.lines.length > 0xFFFF)
this.$splitAndapplyLargeDelta(delta);

// Apply.
applyDelta(this.$lines, delta, doNotValidate);
this._signal("change", {data: delta});
};

this.$splitAndapplyLargeDelta = function(delta) {
// Split large insert deltas. This is necessary because:
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
// 2. fn.apply() doesn't work for a large number of params. The mallest threshold is on safari 0xFFFF.
Expand All @@ -578,28 +585,18 @@ var Document = function(textOrLines) {
// 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
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
var bIsInsert = delta.action == "insert";
while (bIsInsert && delta.lines.length > 65001) {
while (delta.lines.length > 0xFFFF) {
// Get split deltas.
var lines = delta.lines.splice(0, 65000);
var lines = delta.lines.splice(0, 0xFFFF);
lines.push("");
var range = new Range(delta.start.row, delta.start.column,
delta.start.row + 65000, 0)
var start = delta.start;
this.applyDelta({
action: delta.action,
lines: lines,
start: range.start,
end: range.end,
});

// Update remaining delta.
delta.start.row += 65000;
delta.start.column = 0;
start: this.pos(start.row, start.column),
end: this.pos(start.row += 0xFFFF, start.column = 0) // Updates remaining delta.
}, true);
}

// Apply.
applyDelta(this.$lines, delta, doNotValidate);
this._emit("change", { data: delta });
};

/**
Expand Down
Loading

0 comments on commit 6b60bcb

Please sign in to comment.