Checkpointing fold-wrap-data work. Mostly done
This commit is contained in:
parent
ff72467c10
commit
46a877e563
2 changed files with 193 additions and 67 deletions
|
|
@ -477,7 +477,7 @@ var EditSession = function(text, mode) {
|
||||||
line = lines[i];
|
line = lines[i];
|
||||||
if (foldLine) {
|
if (foldLine) {
|
||||||
var end = foldLine.range.end;
|
var end = foldLine.range.end;
|
||||||
line = this.getFoldDisplayLine(foldLine, end.row, line.length);
|
line = this.getFoldDisplayLine(foldLine);
|
||||||
// Continue after the foldLine.end.row. All the lines in
|
// Continue after the foldLine.end.row. All the lines in
|
||||||
// between are folded.
|
// between are folded.
|
||||||
i = end.row;
|
i = end.row;
|
||||||
|
|
@ -1003,9 +1003,30 @@ var EditSession = function(text, mode) {
|
||||||
var wrapData = this.$wrapData;
|
var wrapData = this.$wrapData;
|
||||||
var wrapLimit = this.$wrapLimit;
|
var wrapLimit = this.$wrapLimit;
|
||||||
var tokens;
|
var tokens;
|
||||||
|
var foldLine;
|
||||||
|
|
||||||
for (var row = firstRow; row <= lastRow; row++) {
|
for (var row = firstRow; row <= lastRow; row++) {
|
||||||
tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[row]));
|
foldLine = this.getFoldLine(row);
|
||||||
|
if (!foldLine) {
|
||||||
|
tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[row]));
|
||||||
|
} else {
|
||||||
|
tokens = [];
|
||||||
|
foldLine.walk(function(placeholder, row, column, lastColumn) {
|
||||||
|
var walkTokens;
|
||||||
|
if (placeholder) {
|
||||||
|
walkTokens = this.$getDisplayTokens(placeholder, tokens.length);
|
||||||
|
walkTokens[0] = PLACEHOLDER_START;
|
||||||
|
for (var i = 1; i < walkTokens.length; i++) {
|
||||||
|
walkTokens[i] = PLACEHOLDER_BODY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
walkTokens = this.$getDisplayTokens(
|
||||||
|
lines[row].substring(lastColumn, column),
|
||||||
|
tokens.length);
|
||||||
|
}
|
||||||
|
tokens = tokens.concat(walkTokens);
|
||||||
|
}.bind(this), row, lines[row].length);
|
||||||
|
}
|
||||||
wrapData[row] =
|
wrapData[row] =
|
||||||
this.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
this.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
||||||
}
|
}
|
||||||
|
|
@ -1251,14 +1272,16 @@ var EditSession = function(text, mode) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.screen2Doc = function(screenRow, screenColumn) {
|
this.screen2Doc = function(screenRow, screenColumn) {
|
||||||
var line,
|
var line;
|
||||||
docRow = 0,
|
var docRow = 0;
|
||||||
docColumn = 0, column,
|
var docColumn = 0;
|
||||||
foldLine,
|
var column;
|
||||||
foldLineRowLength;
|
var foldLine;
|
||||||
|
var foldLineRowLength;
|
||||||
var row = 0,
|
var row = 0;
|
||||||
rowLength = 0;
|
var rowLength = 0;
|
||||||
|
var splits = null;
|
||||||
|
var split = 0;
|
||||||
|
|
||||||
while (row <= screenRow) {
|
while (row <= screenRow) {
|
||||||
rowLength = this.getRowLength(docRow);
|
rowLength = this.getRowLength(docRow);
|
||||||
|
|
@ -1270,58 +1293,37 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var splits = null;
|
|
||||||
splits = this.$wrapData[docRow] || [];
|
splits = this.$wrapData[docRow] || [];
|
||||||
foldLine = this.getFoldLine(docRow);
|
foldLine = this.getFoldLine(docRow);
|
||||||
if (foldLine) {
|
line = foldLine
|
||||||
docColumn = splits[screenRow - row] || 0;
|
? this.getFoldDisplayLine(foldLine)
|
||||||
walkScreenColumn = 0;
|
: this.getLine(docRow);
|
||||||
|
|
||||||
foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
|
if (this.$useWrapMode) {
|
||||||
var data, str;
|
docColumn = split = splits[screenRow - row - 1] || 0;
|
||||||
if (placeholder) {
|
line = line.substring(split);
|
||||||
data = this.$getStringScreenWidth(placeholder, null, walkScreenColumn);
|
|
||||||
if (data[0] > screenColumn || data[1] == 0) {
|
|
||||||
return true; // Stop walk.
|
|
||||||
}
|
|
||||||
docColumn += data[1];
|
|
||||||
} else {
|
|
||||||
docColumn = lastColumn;
|
|
||||||
if (isNewRow) {
|
|
||||||
docRow = row;
|
|
||||||
line = this.getLine(row);
|
|
||||||
}
|
|
||||||
str = line.substring(lastColumn, column);
|
|
||||||
data = this.$getStringScreenWidth(str, screenColumn, walkScreenColumn);
|
|
||||||
docColumn += data[1];
|
|
||||||
if (data[0] == screenColumn) {
|
|
||||||
return true; // Stop walk.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
walkScreenColumn = data[0];
|
|
||||||
}.bind(this), foldLine.end.row, this.getLine(foldLine.end.row).length);
|
|
||||||
} else {
|
|
||||||
line = this.getLine(docRow);
|
|
||||||
if (this.$useWrapMode && splits) {
|
|
||||||
docColumn = splits[screenRow - row - 1] || 0;
|
|
||||||
line = line.substring(docColumn);
|
|
||||||
}
|
|
||||||
|
|
||||||
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
|
|
||||||
|
|
||||||
// Need to do some clamping action here.
|
|
||||||
if (this.$useWrapMode) {
|
|
||||||
column = this.$wrapData[docRow][screenRow - row]
|
|
||||||
if (docColumn >= column) {
|
|
||||||
// We remove one character at the end such that the docColumn
|
|
||||||
// position returned is not associated to the next row on the
|
|
||||||
// screen.
|
|
||||||
docColumn = column - 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
docColumn = Math.min(docColumn, line.length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
|
||||||
|
|
||||||
|
if (foldLine) {
|
||||||
|
var position = foldLine.idxToPosition(docColumn);
|
||||||
|
return [position.row, position.column];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to do some clamping action here.
|
||||||
|
if (this.$useWrapMode) {
|
||||||
|
column = splits[screenRow - row]
|
||||||
|
if (docColumn >= column) {
|
||||||
|
// We remove one character at the end such that the docColumn
|
||||||
|
// position returned is not associated to the next row on the
|
||||||
|
// screen.
|
||||||
|
docColumn = column - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
docColumn = Math.min(docColumn, line.length);
|
||||||
|
}
|
||||||
|
|
||||||
return [docRow, docColumn, screenRow, row]
|
return [docRow, docColumn, screenRow, row]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1388,13 +1390,14 @@ var EditSession = function(text, mode) {
|
||||||
foldStartRow = docRow;
|
foldStartRow = docRow;
|
||||||
} else {
|
} else {
|
||||||
textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
|
textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
|
||||||
|
foldStartRow = foldLine.start.row;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp textLine if in wrapMode.
|
// Clamp textLine if in wrapMode.
|
||||||
if (this.$useWrapMode) {
|
if (this.$useWrapMode) {
|
||||||
var wrapRow = wrapData[foldStartRow];
|
var wrapRow = wrapData[foldStartRow];
|
||||||
var screenRowOffset = 0;
|
var screenRowOffset = 0;
|
||||||
while (docColumn >= wrapRow[screenRowOffset]) {
|
while (textLine.length >= wrapRow[screenRowOffset]) {
|
||||||
screenRow ++;
|
screenRow ++;
|
||||||
screenRowOffset++;
|
screenRowOffset++;
|
||||||
}
|
}
|
||||||
|
|
@ -1532,6 +1535,9 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
/**
|
||||||
|
* Note: This doesn't update wrapData!
|
||||||
|
*/
|
||||||
this.shiftRow = function(shift) {
|
this.shiftRow = function(shift) {
|
||||||
this.start.row += shift;
|
this.start.row += shift;
|
||||||
this.end.row += shift;
|
this.end.row += shift;
|
||||||
|
|
@ -1602,7 +1608,7 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
stop = stop || callback(fold.placeholder, null, null, lastEnd);
|
||||||
|
|
||||||
if (stop) {
|
if (stop) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1645,8 +1651,7 @@ var EditSession = function(text, mode) {
|
||||||
&& fold.start.column != column
|
&& fold.start.column != column
|
||||||
&& fold.start.row != row)
|
&& fold.start.row != row)
|
||||||
{
|
{
|
||||||
// TODO: Implement adding new characters inside of an
|
throw "Moving characters inside of a fold should never be reached";
|
||||||
// fold. This should extend/remove the fold etc.
|
|
||||||
} else if (fold.start.row == row) {
|
} else if (fold.start.row == row) {
|
||||||
folds = this.folds;
|
folds = this.folds;
|
||||||
var i = folds.indexOf(fold);
|
var i = folds.indexOf(fold);
|
||||||
|
|
@ -1683,8 +1688,6 @@ var EditSession = function(text, mode) {
|
||||||
// containing these removed folds.
|
// containing these removed folds.
|
||||||
folds = folds.splice(i, folds.length - i);
|
folds = folds.splice(i, folds.length - i);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var newFoldLine = new FoldLine(foldData, folds);
|
var newFoldLine = new FoldLine(foldData, folds);
|
||||||
foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
|
foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
|
||||||
return newFoldLine;
|
return newFoldLine;
|
||||||
|
|
@ -1710,6 +1713,35 @@ var EditSession = function(text, mode) {
|
||||||
ret.push("]")
|
ret.push("]")
|
||||||
return ret.join("\n");
|
return ret.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.idxToPosition = function(idx) {
|
||||||
|
var lastFoldEndColumn = 0;
|
||||||
|
var fold;
|
||||||
|
|
||||||
|
for (var i = 0; i < this.folds.length; i++) {
|
||||||
|
var fold = this.folds[i];
|
||||||
|
|
||||||
|
idx -= fold.start.column - lastFoldEndColumn;
|
||||||
|
if (idx < 0) {
|
||||||
|
return {
|
||||||
|
row: fold.start.row,
|
||||||
|
column: fold.start.column + idx
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
idx -= fold.placeholder.length;
|
||||||
|
if (idx < 0) {
|
||||||
|
return fold.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFoldEndColumn = fold.end.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
row: this.end.row,
|
||||||
|
column: this.end.column + idx
|
||||||
|
};
|
||||||
|
}
|
||||||
}).call(FoldLine.prototype);
|
}).call(FoldLine.prototype);
|
||||||
|
|
||||||
FoldLine.prototype.__defineGetter__("rangeDBG", function() {
|
FoldLine.prototype.__defineGetter__("rangeDBG", function() {
|
||||||
|
|
@ -1864,6 +1896,7 @@ var EditSession = function(text, mode) {
|
||||||
this.$foldData.sort(function(a, b) {
|
this.$foldData.sort(function(a, b) {
|
||||||
return a.start.row - b.start.row;
|
return a.start.row - b.start.row;
|
||||||
});
|
});
|
||||||
|
return foldLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1874,13 +1907,14 @@ var EditSession = function(text, mode) {
|
||||||
endRow = range.end.row,
|
endRow = range.end.row,
|
||||||
foldData = this.$foldData,
|
foldData = this.$foldData,
|
||||||
foldRow = null;
|
foldRow = null;
|
||||||
|
var foldLine;
|
||||||
|
|
||||||
var fold = new Fold(range, placeholder);
|
var fold = new Fold(range, placeholder);
|
||||||
var added = false;
|
var added = false;
|
||||||
|
|
||||||
// For now we assume that no two folds are created for the same range!
|
// For now we assume that no two folds are created for the same range!
|
||||||
for (var i = 0; i < foldData.length; i++) {
|
for (var i = 0; i < foldData.length; i++) {
|
||||||
var foldLine = foldData[i];
|
foldLine = foldData[i];
|
||||||
if (endRow == foldLine.start.row) {
|
if (endRow == foldLine.start.row) {
|
||||||
foldLine.addFold(fold);
|
foldLine.addFold(fold);
|
||||||
added = true;
|
added = true;
|
||||||
|
|
@ -1904,10 +1938,13 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!added) {
|
if (!added) {
|
||||||
this.$addFoldLine(new FoldLine(this.$foldData, fold));
|
foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Recalculate wrapData
|
// TODO: Recalculate wrapData
|
||||||
|
if (this.$useWrapMode) {
|
||||||
|
this.$updateWrapData(foldLine.start.row, foldLine.start.row);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify that fold data has changed.
|
// Notify that fold data has changed.
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
|
|
@ -1916,6 +1953,8 @@ var EditSession = function(text, mode) {
|
||||||
|
|
||||||
this.removeFold = function(fold) {
|
this.removeFold = function(fold) {
|
||||||
var foldLine = fold.foldLine;
|
var foldLine = fold.foldLine;
|
||||||
|
var startRow = foldLine.start.row;
|
||||||
|
var endRow = foldLine.end.row;
|
||||||
|
|
||||||
var foldLines = this.$foldData,
|
var foldLines = this.$foldData,
|
||||||
folds = foldLine.folds;
|
folds = foldLine.folds;
|
||||||
|
|
@ -1953,7 +1992,9 @@ var EditSession = function(text, mode) {
|
||||||
this.$addFoldLine(newFoldLine);
|
this.$addFoldLine(newFoldLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Update wrapData.
|
if (this.$useWrapMode) {
|
||||||
|
this.$updateWrapData(startRow, endRow);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify that fold data has changed.
|
// Notify that fold data has changed.
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
|
|
@ -1991,6 +2032,11 @@ var EditSession = function(text, mode) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getFoldDisplayLine = function(foldLine, endRow, endColumn) {
|
this.getFoldDisplayLine = function(foldLine, endRow, endColumn) {
|
||||||
|
if (endRow == null) {
|
||||||
|
endRow = foldLine.end.row;
|
||||||
|
endColumn = this.getLine(endRow).length;
|
||||||
|
}
|
||||||
|
|
||||||
// Build the textline using the FoldLine walker.
|
// Build the textline using the FoldLine walker.
|
||||||
var line = "",
|
var line = "",
|
||||||
textLine = "";
|
textLine = "";
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ if (typeof process !== "undefined") {
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
var lang = require("pilot/lang");
|
||||||
var EditSession = require("ace/edit_session").EditSession;
|
var EditSession = require("ace/edit_session").EditSession;
|
||||||
var Editor = require("ace/editor").Editor;
|
var Editor = require("ace/editor").Editor;
|
||||||
var UndoManager = require("ace/undomanager").UndoManager;
|
var UndoManager = require("ace/undomanager").UndoManager;
|
||||||
|
|
@ -264,6 +265,7 @@ module.exports = {
|
||||||
function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
|
function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
|
||||||
wrapLimit = wrapLimit || 12;
|
wrapLimit = wrapLimit || 12;
|
||||||
tabSize = tabSize || 4;
|
tabSize = tabSize || 4;
|
||||||
|
line = lang.stringTrimRight(line);
|
||||||
var tokens = EditSession.prototype.$getDisplayTokens(line);
|
var tokens = EditSession.prototype.$getDisplayTokens(line);
|
||||||
var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
||||||
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
||||||
|
|
@ -373,6 +375,48 @@ module.exports = {
|
||||||
assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
|
assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"test fold getFoldDisplayLine": function() {
|
||||||
|
var session = createFoldTestSession();
|
||||||
|
function assertDisplayLine(foldLine, str) {
|
||||||
|
var line = session.getLine(foldLine.end.row);
|
||||||
|
var displayLine =
|
||||||
|
session.getFoldDisplayLine(foldLine, foldLine.end.row, line.length);
|
||||||
|
assert.equal(displayLine, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertDisplayLine(session.$foldData[0], "function foo(args...) {")
|
||||||
|
assertDisplayLine(session.$foldData[1], " for (vfoo...ert(items[bar...\"juhu\");");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test foldLine idxToPosition": function() {
|
||||||
|
var session = createFoldTestSession();
|
||||||
|
|
||||||
|
function assertIdx2Pos(foldLineIdx, idx, row, column) {
|
||||||
|
var foldLine = session.$foldData[foldLineIdx];
|
||||||
|
assert.position(foldLine.idxToPosition(idx), row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// "function foo(items) {",
|
||||||
|
// " for (var i=0; i<items.length; i++) {",
|
||||||
|
// " alert(items[i] + \"juhu\");",
|
||||||
|
// " } // Real Tab.",
|
||||||
|
// "}"
|
||||||
|
|
||||||
|
assertIdx2Pos(0, 12, 0, 12);
|
||||||
|
assertIdx2Pos(0, 13, 0, 13);
|
||||||
|
assertIdx2Pos(0, 14, 0, 13);
|
||||||
|
assertIdx2Pos(0, 19, 0, 13);
|
||||||
|
assertIdx2Pos(0, 20, 0, 18);
|
||||||
|
|
||||||
|
assertIdx2Pos(1, 10, 1, 10);
|
||||||
|
assertIdx2Pos(1, 11, 1, 10);
|
||||||
|
assertIdx2Pos(1, 15, 1, 10);
|
||||||
|
assertIdx2Pos(1, 16, 2, 10);
|
||||||
|
assertIdx2Pos(1, 26, 2, 20);
|
||||||
|
assertIdx2Pos(1, 27, 2, 20);
|
||||||
|
assertIdx2Pos(1, 32, 2, 25);
|
||||||
|
},
|
||||||
|
|
||||||
"test fold documentToScreen": function() {
|
"test fold documentToScreen": function() {
|
||||||
var session = createFoldTestSession();
|
var session = createFoldTestSession();
|
||||||
function assertDoc2Screen(docRow, docCol, screenRow, screenCol) {
|
function assertDoc2Screen(docRow, docCol, screenRow, screenCol) {
|
||||||
|
|
@ -647,6 +691,42 @@ module.exports = {
|
||||||
assert.range(foldLines[0].range, 0, 13, 0, 18);
|
assert.range(foldLines[0].range, 0, 13, 0, 18);
|
||||||
assert.range(foldLines[1].range, 1, 10, 2, 25);
|
assert.range(foldLines[1].range, 1, 10, 2, 25);
|
||||||
// TODO: Add test for inseration inside of folds.
|
// TODO: Add test for inseration inside of folds.
|
||||||
|
},
|
||||||
|
|
||||||
|
"test fold wrap data compution": function() {
|
||||||
|
function assertArray(a, b) {
|
||||||
|
assert.ok(a.length == b.length);
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
assert.ok(a[i] == b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertWrap(line0, line1, line2) {
|
||||||
|
line0 && assertArray(wrapData[0], line0);
|
||||||
|
line1 && assertArray(wrapData[1], line1);
|
||||||
|
line2 && assertArray(wrapData[2], line2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines = [
|
||||||
|
"foo bar foo bar",
|
||||||
|
"foo bar foo bar",
|
||||||
|
"foo bar foo bar"
|
||||||
|
];
|
||||||
|
|
||||||
|
var session = new EditSession(lines.join("\n"));
|
||||||
|
var wrapData = session.$wrapData;
|
||||||
|
session.setUseWrapMode(true);
|
||||||
|
session.$wrapLimit = 7;
|
||||||
|
session.$updateWrapData(0, 2);
|
||||||
|
|
||||||
|
assertWrap([7], [7], [7]);
|
||||||
|
session.addFold(new Range(0, 13, 0, 18), "args...");
|
||||||
|
|
||||||
|
|
||||||
|
session.addFold(new Range(1, 10, 2, 10), "foo...");
|
||||||
|
session.addFold(new Range(2, 20, 2, 25), "bar...");
|
||||||
|
return session;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue