From e9f3ba7b56a7e0a7b6959f08e74c9cd38c20daff Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Mon, 25 Apr 2011 13:29:23 +0200 Subject: [PATCH] Add support for multi line insertion + unit tests --- lib/ace/edit_session.js | 84 +++++++++++++++++++++++++++++------- lib/ace/edit_session_test.js | 39 +++++++++++++++++ lib/ace/range.js | 10 +++++ 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index b4d93ca0..b263d1d2 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -905,15 +905,32 @@ var EditSession = function(text, mode) { // If some new line is added inside of a foldLine, then split // the fold line up. + var foldLines = this.$foldData; var foldLine = this.getFoldLine(firstRow); - if (foldLine && foldLine.range.inside(start.row, start.column)) { - var foldLine = foldLine.split(start.row, start.column); + var idx = 0; + if (foldLine) { + var cmp = foldLine.range.compareInside(start.row, start.column) + // Inside of the foldLine range. Need to split stuff up. + if (cmp == 0) { + // TODO: Handle case where inseration is inside of fold! + foldLine = foldLine.split(start.row, start.column); + foldLine.shiftRow(len); + foldLine.addRemoveChars( + lastRow, 0, end.column - start.column); + this.$addFoldLine(foldLine); + } else + // Infront of the foldLine but same row. Need to shift column. + if (cmp == -1) { + foldLine.addRemoveChars(firstRow, 0, end.column - start.column); + foldLine.shiftRow(len); + } + // Nothing to do if the insert is after the foldLine. + idx = foldLines.indexOf(foldLine) + 1; } - var foldLines = this.$foldData; - for (var i = 0; i < foldLines.length; i++) { - var foldLine = foldLines[i]; + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; if (foldLine.start.row >= firstRow) { foldLine.shiftRow(len); } @@ -1418,11 +1435,24 @@ var EditSession = function(text, mode) { this.sameRow = range.start.row == range.end.row; } - function FoldLine(fold) { - this.folds = [fold]; - this.range = fold.range.clone(); - this.start = this.range.start; - this.end = this.range.end; + /** + * Creates a new FoldLine. If the an array is passed in, the folds are + * expected to be sorted already. + */ + function FoldLine(folds) { + if (Array.isArray(folds)) { + var last = folds[folds.length - 1] + this.folds = folds; + this.range = new Range(folds[0].start.row, folds[0].start.column, + last.end.row, last.end.column); + this.start = this.range.start; + this.end = this.range.end; + } else { + this.folds = [folds]; + this.range = folds.range.clone(); + this.start = this.range.start; + this.end = this.range.end; + } } (function() { @@ -1599,8 +1629,29 @@ var EditSession = function(text, mode) { } } } + + this.split = function(row, column) { + var fold = this.getNextFoldTo(row, column).fold, + folds = this.folds; + if (!fold) { + return null; + } + var i = folds.indexOf(fold); + var foldBefore = folds[i - 1]; + this.end.row = foldBefore.end.row; + this.end.column = foldBefore.end.column; + + // Remove the folds after row/column and create a new FoldLine + // containing these removed folds. + var folds = folds.splice(i, folds.length - i); + return new FoldLine(folds); + } }).call(FoldLine.prototype); + FoldLine.prototype.__defineGetter__("rangeDBG", function() { + return this.range + ""; + }) + this.getFoldAt = function(row, column, side) { var foldLine = this.getFoldLine(row); if (foldLine) { @@ -1663,6 +1714,13 @@ var EditSession = function(text, mode) { return null; } + this.$addFoldLine = function(foldLine) { + this.$foldData.push(foldLine); + this.$foldData.sort(function(a, b) { + return a.start.row - b.start.row; + }); + } + /** * Adds a new fold. */ @@ -1707,11 +1765,7 @@ var EditSession = function(text, mode) { } if (!added) { - foldLine = new FoldLine(fold); - foldData.push(foldLine); - foldData.sort(function(a, b) { - return a.start.row - b.start.row; - }); + this.$addFoldLine(new FoldLine(fold)); } // TODO: Recalculate wrapData diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index cc36b6aa..d065a36b 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -502,6 +502,45 @@ module.exports = { assert.range(foldLine.range, 1, 12, 2, 27); assert.range(folds[0].range, 1, 12, 2, 10); assert.range(folds[1].range, 2, 22, 2, 27); + }, + + "test fold multi-line insert": function() { + var session = createFoldTestSession(), + foldLines = session.$foldData; + function insert(row, column, text) { + session.insert({row: row, column: column}, text); + } + + var foldLines = session.$foldData, foldLine, fold, folds; + + insert(0, 0, "\nfoo"); + assert.equal(foldLines.length, 2); + assert.range(foldLines[0].range, 1, 16, 1, 21); + assert.range(foldLines[1].range, 2, 10, 3, 25); + + insert(2, 0, "\nbar"); + assert.equal(foldLines.length, 2); + assert.range(foldLines[0].range, 1, 16, 1, 21); + assert.range(foldLines[1].range, 3, 13, 4, 25); + + insert(3, 10, "\nfoo"); + assert.equal(foldLines.length, 2); + assert.range(foldLines[0].range, 1, 16, 1, 21); + assert.range(foldLines[1].range, 4, 6, 5, 25); + + insert(5, 10, "\nbar"); + assert.equal(foldLines.length, 3); + assert.range(foldLines[0].range, 1, 16, 1, 21); + assert.range(foldLines[1].range, 4, 6, 5, 10); + assert.range(foldLines[2].range, 6, 13, 6, 18); + + insert(6, 18, "\nfoo"); + assert.equal(foldLines.length, 3); + assert.range(foldLines[0].range, 1, 16, 1, 21); + assert.range(foldLines[1].range, 4, 6, 5, 10); + assert.range(foldLines[2].range, 6, 13, 6, 18); + + // TODO: Add test for inseration inside of folds. } }; diff --git a/lib/ace/range.js b/lib/ace/range.js index 4c51067f..b1987534 100644 --- a/lib/ace/range.js +++ b/lib/ace/range.js @@ -145,6 +145,16 @@ var Range = function(startRow, startColumn, endRow, endColumn) { } } + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + this.clipRows = function(firstRow, lastRow) { if (this.end.row > lastRow) { var end = {