Final iteration of wrapMode + folding: Addind unit tests, fixing bugs.

This commit is contained in:
Julian Viereck 2011-04-28 15:53:50 +02:00
commit 825cf26478
6 changed files with 129 additions and 53 deletions

View file

@ -150,13 +150,13 @@ exports.launch = function(env) {
// BEGING TESTING // BEGING TESTING
var Range = require("ace/range").Range; var Range = require("ace/range").Range;
docs.js.addFold(new Range(0, 13, 0, 18), "args..."); docs.js.addFold("args...", new Range(0, 13, 0, 18));
docs.js.addFold(new Range(2, 20, 2, 25), "bar..."); docs.js.addFold("bar...", new Range(2, 20, 2, 25));
docs.js.addFold(new Range(1, 10, 2, 10), "foo..."); docs.js.addFold("foo...", new Range(1, 10, 2, 10));
docs.svg.addFold(new Range(1, 0, 7, 0), "fold..."); docs.svg.addFold("fold...", new Range(1, 0, 7, 0));
docs.plain.addFold(new Range(0, 90, 2, 30), "fold"); docs.plain.addFold("fold", new Range(0, 90, 2, 30));
window.s = docs.plain; window.s = docs.plain;
window.e = env.editor; window.e = env.editor;
setTimeout(function() { setTimeout(function() {
@ -481,7 +481,7 @@ exports.launch = function(env) {
range = env.editor.selection.getRange(), range = env.editor.selection.getRange(),
placeHolder = session.getTextRange(range).substring(0, 3) + "..."; placeHolder = session.getTextRange(range).substring(0, 3) + "...";
session.addFold(range, placeHolder); session.addFold(placeHolder, range);
} }
}); });

View file

@ -1006,6 +1006,7 @@ var EditSession = function(text, mode) {
var foldLine; var foldLine;
var row = firstRow; var row = firstRow;
lastRow = Math.min(lastRow, lines.length - 1);
while (row <= lastRow) { while (row <= lastRow) {
foldLine = this.getFoldLine(row); foldLine = this.getFoldLine(row);
if (!foldLine) { if (!foldLine) {
@ -1030,8 +1031,14 @@ var EditSession = function(text, mode) {
tokens = tokens.concat(walkTokens); tokens = tokens.concat(walkTokens);
}.bind(this), }.bind(this),
foldLine.end.row, foldLine.end.row,
lines[foldLine.end.row].length lines[foldLine.end.row].length + 1
); );
// Remove spaces/tabs from the back of the token array.
while (tokens.length != 0
&& tokens[tokens.length - 1] >= SPACE)
{
tokens.pop();
}
} }
wrapData[row] = wrapData[row] =
this.$computeWrapSplits(tokens, wrapLimit, tabSize); this.$computeWrapSplits(tokens, wrapLimit, tabSize);
@ -1096,24 +1103,9 @@ var EditSession = function(text, mode) {
} }
// === ELSE === // === ELSE ===
// Search for the first non space/tab token backwards. // Check if split is inside of a placeholder. Placeholder are
for (split; split != lastSplit - 1; split--) { // not splitable. Therefore, seek the beginning of the placeholder
if (tokens[split] >= SPACE) { // and try to place the split beofre the placeholder's start.
split++;
break;
}
}
// If we found one, then add the split.
if (split > lastSplit) {
addSplit(split);
continue;
}
// === ELSE ===
split = lastSplit + wrapLimit;
// No space or tab around? Well, force a split then.
// Check if the split position is inside of a placeholder.
// Placeholder are not splitable!
if (tokens[split] == PLACEHOLDER_START if (tokens[split] == PLACEHOLDER_START
|| tokens[split] == PLACEHOLDER_BODY) || tokens[split] == PLACEHOLDER_BODY)
{ {
@ -1140,8 +1132,7 @@ var EditSession = function(text, mode) {
// placeholder. So, let's seek for the end of the placeholder. // placeholder. So, let's seek for the end of the placeholder.
split = lastSplit + wrapLimit; split = lastSplit + wrapLimit;
for (split; split < tokens.length; split++) { for (split; split < tokens.length; split++) {
if (tokens[split] != PLACEHOLDER_START && if (tokens[split] != PLACEHOLDER_BODY)
tokens[split] != PLACEHOLDER_BODY)
{ {
break; break;
} }
@ -1159,8 +1150,23 @@ var EditSession = function(text, mode) {
} }
// === ELSE === // === ELSE ===
// The split is inside of a CHAR or CHAR_EXT token. Forcing // Search for the first non space/tab/placeholder token backwards.
// a split here is all right. for (split; split != lastSplit - 1; split--) {
if (tokens[split] >= PLACEHOLDER_START) {
split++;
break;
}
}
// If we found one, then add the split.
if (split > lastSplit) {
addSplit(split);
continue;
}
// === ELSE ===
split = lastSplit + wrapLimit;
// The split is inside of a CHAR or CHAR_EXT token and no space
// around -> force a split.
addSplit(lastSplit + wrapLimit); addSplit(lastSplit + wrapLimit);
} }
return splits; return splits;

View file

@ -123,22 +123,19 @@ function FoldLine(foldData, folds) {
for (var i = 0; i < folds.length; i++) { for (var i = 0; i < folds.length; i++) {
fold = folds[i]; fold = folds[i];
comp = fold.range.compareEnd(endRow, endColumn); comp = fold.range.compareStart(endRow, endColumn);
// This fold is after the endRow/Column. // This fold is after the endRow/Column.
if (comp == -1) { if (comp == -1) {
callback(null, endRow, endColumn, lastEnd, isNewRow); callback(null, endRow, endColumn, lastEnd, isNewRow);
return; return;
} }
// The endRow/Column is inside of the current fold.
else if (comp == 0) {
callback(null, endRow, fold.start.column, lastEnd, isNewRow);
return;
}
stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
stop = stop || callback(fold.placeholder, null, null, lastEnd); stop = !stop && callback(fold.placeholder, null, null, lastEnd);
if (stop) { // If the user requested to stop the walk or endRow/endColumn is
// inside of this fold (comp == 0), then end here.
if (stop || comp == 0) {
return; return;
} }

View file

@ -38,6 +38,7 @@
define(function(require, exports, module) { define(function(require, exports, module) {
var Range = require("ace/range").Range;
var FoldLine = require("ace/edit_session/fold_line").FoldLine; var FoldLine = require("ace/edit_session/fold_line").FoldLine;
/** /**
@ -212,11 +213,19 @@ function Folding() {
/** /**
* Adds a new fold. * Adds a new fold.
*/ */
this.addFold = function(range, placeholder) { this.addFold = function(placeholder, startRow, startColumn, endRow, endColumn) {
var startRow = range.start.row, var range;
endRow = range.end.row, // Normalize parameters.
foldData = this.$foldData, if (!(startRow instanceof Range)) {
foldRow = null; range = new Range(startRow, startColumn, endRow, endColumn);
} else {
range = startRow;
startRow = range.start.row;
endRow = range.end.row;
}
var foldData = this.$foldData;
var foldRow = null;
var foldLine; var foldLine;
var fold = new Fold(range, placeholder); var fold = new Fold(range, placeholder);

View file

@ -61,9 +61,9 @@ function createFoldTestSession() {
]; ];
var session = new EditSession(lines.join("\n")); var session = new EditSession(lines.join("\n"));
session.setUndoManager(new UndoManager()); session.setUndoManager(new UndoManager());
session.addFold(new Range(0, 13, 0, 18), "args..."); session.addFold("args...", new Range(0, 13, 0, 18));
session.addFold(new Range(1, 10, 2, 10), "foo..."); session.addFold("foo...", new Range(1, 10, 2, 10));
session.addFold(new Range(2, 20, 2, 25), "bar..."); session.addFold("bar...", new Range(2, 20, 2, 25));
return session; return session;
} }
@ -697,7 +697,7 @@ module.exports = {
function assertArray(a, b) { function assertArray(a, b) {
assert.ok(a.length == b.length); assert.ok(a.length == b.length);
for (var i = 0; i < a.length; i++) { for (var i = 0; i < a.length; i++) {
assert.ok(a[i] == b[i]); assert.equal(a[i], b[i]);
} }
} }
@ -707,6 +707,11 @@ module.exports = {
line2 && assertArray(wrapData[2], line2); line2 && assertArray(wrapData[2], line2);
} }
function removeFoldAssertWrap(docRow, docColumn, line0, line1, line2) {
session.removeFold(session.getFoldAt(docRow, docColumn));
assertWrap(line0, line1, line2);
}
var lines = [ var lines = [
"foo bar foo bar", "foo bar foo bar",
"foo bar foo bar", "foo bar foo bar",
@ -714,19 +719,78 @@ module.exports = {
]; ];
var session = new EditSession(lines.join("\n")); var session = new EditSession(lines.join("\n"));
var wrapData = session.$wrapData;
session.setUseWrapMode(true); session.setUseWrapMode(true);
session.$wrapLimit = 7; session.$wrapLimit = 7;
session.$updateWrapData(0, 2); session.$updateWrapData(0, 2);
var wrapData = session.$wrapData;
assertWrap([7], [7], [7]); // Do a simple assertion without folds to check basic functionallity.
session.addFold(new Range(0, 13, 0, 18), "args..."); assertWrap([8], [8], [8]);
// --- Do in line folding ---
// Adding a fold. The split position is inside of the fold. As placeholder
// are not splitable, the split should be before the split.
session.addFold("woot", 0, 4, 0, 16);
assertWrap([4], [8], [8]);
// Remove the fold again which should reset the wrapData.
removeFoldAssertWrap(0, 4, [8], [8], [8]);
session.addFold("woot", 0, 6, 0, 9);
assertWrap([6, 13], [8], [8]);
removeFoldAssertWrap(0, 6, [8], [8], [8]);
// The fold fits into the wrap limit - no split expected.
session.addFold("woot", 0, 3, 0, 16);
assertWrap([], [8], [8]);
removeFoldAssertWrap(0, 4, [8], [8], [8]);
// Fold after split position should be all fine.
session.addFold("woot", 0, 8, 0, 16);
assertWrap([8], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]);
// Fold's placeholder is far too long for wrapSplit.
session.addFold("woot0123456789", 0, 8, 0, 16);
assertWrap([8], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]);
// Fold's placeholder is far too long for wrapSplit
// + content at the end of the line
session.addFold("woot0123456789", 0, 7, 0, 8);
assertWrap([7, 21], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot0123456789", 0, 7, 0, 8);
session.addFold("woot0123456789", 0, 8, 0, 9);
assertWrap([7, 21, 35], [8], [8]);
session.removeFold(session.getFoldAt(0, 7));
removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot0123456789", 0, 7, 0, 8);
session.addFold("woot0123456789", 0, 14, 0, 16);
assertWrap([7, 21, 27], [8], [8]);
session.removeFold(session.getFoldAt(0, 7));
removeFoldAssertWrap(0, 14, [8], [8], [8]);
// --- Do some multiline folding ---
// Add a fold over two lines. Note, that the wrapData[1] stays the
// same. This is an implementation detail and expected behavior.
session.addFold("woot", 0, 8, 1, 16);
assertWrap([8], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot", 0, 9, 1, 11);
assertWrap([8, 14], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 9, [8], [8], [8]);
session.addFold("woot", 0, 9, 1, 16);
assertWrap([8], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 9, [8], [8], [8]);
session.addFold(new Range(1, 10, 2, 10), "foo...");
session.addFold(new Range(2, 20, 2, 25), "bar...");
return session; return session;
} }
}; };

View file

@ -66,7 +66,7 @@ var UndoManager = function() {
this.$undoStack.push(deltas); this.$undoStack.push(deltas);
} }
}; };
this.reset = function() { this.reset = function() {
this.$undoStack = []; this.$undoStack = [];
this.$redoStack = []; this.$redoStack = [];