From ebac43d3295460aa1f5cfff0ecd42b9fa6056e93 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 18 Jan 2011 11:39:48 +0100 Subject: [PATCH 01/36] fix node search paths for unit tests --- support/paths.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/paths.js b/support/paths.js index e5b06350..09568933 100644 --- a/support/paths.js +++ b/support/paths.js @@ -1,7 +1,7 @@ require("./requireJS-node"); require.paths.unshift(__dirname + "/../lib"); require.paths.unshift(__dirname + "/cockpit/lib"); -require.paths.unshift(__dirname + "/cockpit/support/pilot/lib"); +require.paths.unshift(__dirname + "/pilot/lib"); require.paths.unshift(__dirname + "/async/lib"); require.paths.unshift(__dirname + "/node-htmlparser/lib"); require.paths.unshift(__dirname + "/jsdom/lib"); From c2f7944a753f599d14097adfa33ef5d86f324b82 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 18 Jan 2011 11:40:24 +0100 Subject: [PATCH 02/36] split off the document from the edit session --- lib/ace/document.js | 796 +++++----------------------- lib/ace/edit_session.js | 845 ++++++++++++++++++++++++++++++ lib/ace/test/document_test.js | 217 +------- lib/ace/test/edit_session_test.js | 295 +++++++++++ 4 files changed, 1284 insertions(+), 869 deletions(-) create mode 100644 lib/ace/edit_session.js create mode 100644 lib/ace/test/edit_session_test.js diff --git a/lib/ace/document.js b/lib/ace/document.js index dd8ad7d9..99a76fc4 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -40,38 +40,31 @@ define(function(require, exports, module) { var oop = require("pilot/oop"); var lang = require("pilot/lang"); var EventEmitter = require("pilot/event_emitter").EventEmitter; -var Selection = require("ace/selection").Selection; -var TextMode = require("ace/mode/text").Mode; var Range = require("ace/range").Range; -var NO_CHANGE_DELTAS = {}; - -var Document = function(text, mode) { - - this.modified = true; +var Document = function(text) { this.$lines = []; - this.selection = new Selection(this); - this.$breakpoints = []; - this.listeners = []; - if (mode) { - this.setMode(mode); - } - if (Array.isArray(text)) { - this.$insertLines(0, text); + this.insertLines(0, text); } else { - this.$insert({row: 0, column: 0}, text); + this.insert({row: 0, column:0}, text); } }; - (function() { oop.implement(this, EventEmitter); - this.$undoManager = null; - + this.setValue = function(text) { + this.remove(new Range(0, 0, this.$lines.length, this.$lines[this.$lines.length-1].length)); + this.insertLines(0, this.$split(text)); + }; + + this.getValue = function() { + return this.$lines.join(this.getNewLineCharacter()); + }; + // check for IE split bug if ("aaa".split(/a/).length == 0) this.$split = function(text) { @@ -82,125 +75,7 @@ var Document = function(text, mode) { return text.split(/\r\n|\r|\n/); }; - this.setValue = function(text) { - var args = [0, this.$lines.length]; - args.push.apply(args, this.$split(text)); - this.$lines.splice.apply(this.$lines, args); - this.modified = true; - this.fireChangeEvent(0); - }; - - this.toString = function() { - return this.$lines.join(this.$getNewLineCharacter()); - }; - this.getValue = this.toString; - - this.getSelection = function() { - return this.selection; - }; - - this.fireChangeEvent = function(firstRow, lastRow) { - var data = { - firstRow: firstRow, - lastRow: lastRow - }; - this._dispatchEvent("change", { data: data}); - }; - - this.setUndoManager = function(undoManager) { - this.$undoManager = undoManager; - this.$deltas = []; - - if (this.$informUndoManager) { - this.$informUndoManager.cancel(); - } - - if (undoManager) { - var self = this; - this.$informUndoManager = lang.deferredCall(function() { - if (self.$deltas.length > 0) - undoManager.execute({ - action : "aceupdate", - args : [self.$deltas, self] - }); - self.$deltas = []; - }); - } - }; - - this.$defaultUndoManager = { - undo: function() {}, - redo: function() {} - }; - - this.getUndoManager = function() { - return this.$undoManager || this.$defaultUndoManager; - }, - - this.getTabString = function() { - if (this.getUseSoftTabs()) { - return lang.stringRepeat(" ", this.getTabSize()); - } else { - return "\t"; - } - }; - - this.$useSoftTabs = true; - this.setUseSoftTabs = function(useSoftTabs) { - if (this.$useSoftTabs === useSoftTabs) return; - - this.$useSoftTabs = useSoftTabs; - }; - - this.getUseSoftTabs = function() { - return this.$useSoftTabs; - }; - - this.$tabSize = 4; - this.setTabSize = function(tabSize) { - if (isNaN(tabSize) || this.$tabSize === tabSize) return; - - this.modified = true; - this.$tabSize = tabSize; - this._dispatchEvent("changeTabSize"); - }; - - this.getTabSize = function() { - return this.$tabSize; - }; - - this.isTabStop = function(position) { - return this.$useSoftTabs && (position.column % this.$tabSize == 0); - }; - - this.getBreakpoints = function() { - return this.$breakpoints; - }; - - this.setBreakpoints = function(rows) { - this.$breakpoints = []; - for (var i=0; i 0) { - inToken = !!line.charAt(column - 1).match(this.tokenRe); - } - - if (!inToken) { - inToken = !!line.charAt(column).match(this.tokenRe); - } - - var re = inToken ? this.tokenRe : this.nonTokenRe; - - var start = column; - if (start > 0) { - do { - start--; - } - while (start >= 0 && line.charAt(start).match(re)); - start++; - } - - var end = column; - while (end < line.length && line.charAt(end).match(re)) { - end++; - } - - return new Range(row, start, row, end); - }; - - this.$getNewLineCharacter = function() { + this.getNewLineCharacter = function() { switch (this.$newLineMode) { case "windows": return "\r\n"; @@ -268,66 +109,9 @@ var Document = function(text, mode) { this.getNewLineMode = function() { return this.$newLineMode; }; - - this.$mode = null; - this.setMode = function(mode) { - if (this.$mode === mode) return; - - this.$mode = mode; - this._dispatchEvent("changeMode"); - }; - - this.getMode = function() { - if (!this.$mode) { - this.$mode = new TextMode(); - } - return this.$mode; - }; - - this.$scrollTop = 0; - this.setScrollTopRow = function(scrollTopRow) { - if (this.$scrollTop === scrollTopRow) return; - - this.$scrollTop = scrollTopRow; - this._dispatchEvent("changeScrollTop"); - }; - - this.getScrollTopRow = function() { - return this.$scrollTop; - }; - - this.getWidth = function() { - this.$computeWidth(); - return this.width; - }; - - this.getScreenWidth = function() { - this.$computeWidth(); - return this.screenWidth; - }; - - this.$computeWidth = function() { - if (this.modified) { - this.modified = false; - - var lines = this.$lines; - var longestLine = 0; - var longestScreenLine = 0; - var tabSize = this.getTabSize(); - - for ( var i = 0; i < lines.length; i++) { - var len = lines[i].length; - longestLine = Math.max(longestLine, len); - - lines[i].replace("\t", function(m) { - len += tabSize-1; - return m; - }); - longestScreenLine = Math.max(longestScreenLine, len); - } - this.width = longestLine; - this.screenWidth = longestScreenLine; - } + + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); }; /** @@ -337,14 +121,6 @@ var Document = function(text, mode) { return this.$lines[row] || ""; }; - /** - * Get a line as it is displayed on screen. Tabs are replaced by spaces. - */ - this.getDisplayLine = function(row) { - var tab = new Array(this.getTabSize()+1).join(" "); - return this.$lines[row].replace(/\t/g, tab); - }; - this.getLines = function(firstRow, lastRow) { return this.$lines.slice(firstRow, lastRow+1); }; @@ -363,482 +139,184 @@ var Document = function(text, mode) { lines.push(this.$lines[range.start.row].substring(range.start.column)); lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1)); lines.push(this.$lines[range.end.row].substring(0, range.end.column)); - return lines.join(this.$getNewLineCharacter()); + return lines.join(this.getNewLineCharacter()); } }; - this.findMatchingBracket = function(position) { - if (position.column == 0) return null; - - var charBeforeCursor = this.getLine(position.row).charAt(position.column-1); - if (charBeforeCursor == "") return null; - - var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); - if (!match) { - return null; - } - - if (match[1]) { - return this.$findClosingBracket(match[1], position); - } else { - return this.$findOpeningBracket(match[2], position); - } - }; - - this.$brackets = { - ")": "(", - "(": ")", - "]": "[", - "[": "]", - "{": "}", - "}": "{" - }; - - this.$findOpeningBracket = function(bracket, position) { - var openBracket = this.$brackets[bracket]; - - var column = position.column - 2; - var row = position.row; - var depth = 1; - - var line = this.getLine(row); - - while (true) { - while(column >= 0) { - var ch = line.charAt(column); - if (ch == openBracket) { - depth -= 1; - if (depth == 0) { - return {row: row, column: column}; - } - } - else if (ch == bracket) { - depth +=1; - } - column -= 1; - } - row -=1; - if (row < 0) break; - - var line = this.getLine(row); - var column = line.length-1; - } - return null; - }; - - this.$findClosingBracket = function(bracket, position) { - var closingBracket = this.$brackets[bracket]; - - var column = position.column; - var row = position.row; - var depth = 1; - - var line = this.getLine(row); - var lineCount = this.getLength(); - - while (true) { - while(column < line.length) { - var ch = line.charAt(column); - if (ch == closingBracket) { - depth -= 1; - if (depth == 0) { - return {row: row, column: column}; - } - } - else if (ch == bracket) { - depth +=1; - } - column += 1; - } - row +=1; - if (row >= lineCount) break; - - var line = this.getLine(row); - var column = 0; - } - return null; - }; - - this.insert = function(position, text, fromUndo) { - var end = this.$insert(position, text, fromUndo); - this.fireChangeEvent(position.row, position.row == end.row ? position.row - : undefined); - return end; - }; - - /** - * @param rows Array[Integer] sorted list of rows - */ - this.multiRowInsert = function(rows, column, text) { - var lines = this.$lines; - - for (var i=rows.length-1; i>=0; i--) { - var row = rows[i]; - if (row >= lines.length) - continue; - - var diff = column - lines[row].length; - if ( diff > 0) { - var padded = lang.stringRepeat(" ", diff) + text; - var offset = -diff; - } - else { - padded = text; - offset = 0; - } - - var end = this.$insert({row: row, column: column+offset}, padded, false); - } - - if (end) { - this.fireChangeEvent(rows[0], rows[rows.length-1] + end.row - rows[0]); - return { - rows: end.row - rows[0], - columns: end.column - column - } - } - else { - return { - rows: 0, - columns: 0 - } - } - }; - - this.$insertLines = function(row, lines, fromUndo) { - if (lines.length == 0) - return; - - var args = [row, 0]; - args.push.apply(args, lines); - this.$lines.splice.apply(this.$lines, args); - - var nl = this.$getNewLineCharacter(); - var delta = { - action: "insertText", - range: new Range(row, 0, row + lines.length, 0), - text: lines.join(nl) + nl - }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } - - if (fromUndo !== NO_CHANGE_DELTAS) { - this._dispatchEvent("changeDelta", { data: delta }); - } - }, - - this.$insert = function(position, text, fromUndo) { + this.insert = function(position, text) { if (text.length == 0) return position; - this.modified = true; if (this.$lines.length <= 1) { this.$detectNewLine(text); } var newLines = this.$split(text); - if (this.$isNewLine(text)) { - var line = this.$lines[position.row] || ""; - this.$lines[position.row] = line.substring(0, position.column); - this.$lines.splice(position.row + 1, 0, line.substring(position.column)); - - var end = { - row : position.row + 1, - column : 0 - }; + if (this.isNewLine(text)) { + var end = this.insertNewLine(position); } else if (newLines.length == 1) { - var line = this.$lines[position.row] || ""; - this.$lines[position.row] = line.substring(0, position.column) + text - + line.substring(position.column); - - var end = { - row : position.row, - column : position.column + text.length - }; + var end = this.insertInLine(position, text); } else { - var line = this.$lines[position.row] || ""; - var firstLine = line.substring(0, position.column) + newLines[0]; - var lastLine = newLines[newLines.length - 1] + line.substring(position.column); - - this.$lines[position.row] = firstLine; - this.$insertLines(position.row + 1, [lastLine], NO_CHANGE_DELTAS); - - if (newLines.length > 2) { - this.$insertLines(position.row + 1, newLines.slice(1, -1), NO_CHANGE_DELTAS); - } - - var end = { - row : position.row + newLines.length - 1, - column : newLines[newLines.length - 1].length - }; + this.insertInLine(position, newLines[0]); + if (newLines.length > 2) + this.insertLines(position.row+1, newLines.slice(1, newLines.length-1)); + + var end = this.insertInLine({row: position.row + newLines.length - 1, column: 0}, newLines[newLines.length-1]); } + return end; + }; + + this.insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + nl: this.getNewLineCharacter(), + range: range, + lines: lines + }; + this._dispatchEvent("changeDelta", { data: delta }); + return range.end; + }, + + this.insertNewLine = function(position) { + console.log(position) + var line = this.$lines[position.row] || ""; + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._dispatchEvent("changeDelta", { data: delta }); + + return end; + }; + + this.insertInLine = function(position, text) { + var line = this.$lines[position.row] || ""; + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + var delta = { action: "insertText", range: Range.fromPoints(position, end), text: text }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } this._dispatchEvent("changeDelta", { data: delta }); - + return end; }; - this.$isNewLine = function(text) { - return (text == "\r\n" || text == "\r" || text == "\n"); - }; - - this.remove = function(range, fromUndo) { + this.remove = function(range) { if (range.isEmpty()) return range.start; - this.$remove(range, fromUndo); - - this.fireChangeEvent(range.start.row, range.isMultiLine() ? undefined : range.start.row); - - return range.start; - }; - - this.multiRowRemove = function(rows, range) { - if (range.start.row !== rows[0]) - throw new TypeError("range must start in the first row!"); + if (range.isMultiLine()) { + var firstRow = range.start.row; + var lastRow = range.end.row; - var height = range.end.row - rows[0]; - for (var i=rows.length-1; i>=0; i--) { - var row = rows[i]; - if (row >= this.$lines.length) - continue; - - var end = this.$remove(new Range(row, range.start.column, row+height, range.end.column), false); + // TODO removeInLine can be optimized away! + this.removeInLine(lastRow, 0, range.end.column); + if (lastRow - firstRow >= 2) + this.removeLines(firstRow + 1, lastRow - 1); + this.removeInLine(firstRow, range.start.column, this.$lines[firstRow].length); + this.removeNewLine(range.start.row); } - - if (end) { - if (height < 0) - this.fireChangeEvent(rows[0]+height, undefined); - else - this.fireChangeEvent(rows[0], height == 0 ? rows[rows.length-1] : undefined); + else { + this.removeInLine(range) } }; - this.$remove = function(range, fromUndo) { - if (range.isEmpty()) - return; - + this.removeInLine = function(row, startColumn, endColumn) { + var range = new Range(row, startColumn, row, endColumn); + var line = this.$lines[row]; + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + var delta = { action: "removeText", - range: range.clone(), - text: this.getTextRange(range) + range: range, + text: removed }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } - - this.modified = true; - - var firstRow = range.start.row; - var lastRow = range.end.row; - - var row = this.getLine(firstRow).substring(0, range.start.column) - + this.getLine(lastRow).substring(range.end.column); - - if (row != "") - this.$lines.splice(firstRow, lastRow - firstRow + 1, row); - else - this.$lines.splice(firstRow, lastRow - firstRow + 1, ""); - - this._dispatchEvent("changeDelta", { data: delta }); return range.start; }; - this.undoChanges = function(deltas) { - this.selection.clearSelection(); - for (var i=deltas.length-1; i>=0; i--) { - var delta = deltas[i]; - if (delta.action == "insertText") { - this.remove(delta.range, true); - this.selection.moveCursorToPosition(delta.range.start); - } else { - this.insert(delta.range.start, delta.text, true); - this.selection.clearSelection(); - } - } - }, - - this.redoChanges = function(deltas) { - this.selection.clearSelection(); - for (var i=0; i= this.$lines.length-1) return 0; - - var removed = this.$lines.slice(firstRow, lastRow + 1); - this.$remove(new Range(firstRow, 0, lastRow + 1, 0)); - this.$insertLines(firstRow+1, removed); - - this.fireChangeEvent(firstRow, lastRow + 1); - return 1; - }; - - this.duplicateLines = function(firstRow, lastRow) { - var firstRow = this.$clipRowToDocument(firstRow); - var lastRow = this.$clipRowToDocument(lastRow); - - var lines = this.getLines(firstRow, lastRow); - this.$insertLines(firstRow, lines); - - var addedRows = lastRow - firstRow + 1; - this.fireChangeEvent(firstRow); - - return addedRows; - }; - - this.$clipRowToDocument = function(row) { - return Math.max(0, Math.min(row, this.$lines.length-1)); - }; - - this.documentToScreenColumn = function(row, docColumn) { - var tabSize = this.getTabSize(); - - var screenColumn = 0; - var remaining = docColumn; - - var line = this.getLine(row).split("\t"); - for (var i=0; i len) { - remaining -= (len + 1); - screenColumn += len + tabSize; - } - else { - screenColumn += remaining; - break; - } - } - - return screenColumn; - }; - - this.screenToDocumentColumn = function(row, screenColumn) { - var tabSize = this.getTabSize(); - - var docColumn = 0; - var remaining = screenColumn; - - var line = this.getLine(row).split("\t"); - for (var i=0; i= len + tabSize) { - remaining -= (len + tabSize); - docColumn += (len + 1); - } - else if (remaining > len){ - docColumn += len; - break; - } - else { - docColumn += remaining; - break; - } - } - return docColumn; - }; - }).call(Document.prototype); exports.Document = Document; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js new file mode 100644 index 00000000..1a5dd67c --- /dev/null +++ b/lib/ace/edit_session.js @@ -0,0 +1,845 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var lang = require("pilot/lang"); +var EventEmitter = require("pilot/event_emitter").EventEmitter; +var Selection = require("ace/selection").Selection; +var TextMode = require("ace/mode/text").Mode; +var Range = require("ace/range").Range; + +var NO_CHANGE_DELTAS = {}; + +var EditSession = function(text, mode) { + + this.modified = true; + this.$lines = []; + this.selection = new Selection(this); + this.$breakpoints = []; + + this.listeners = []; + if (mode) { + this.setMode(mode); + } + + if (Array.isArray(text)) { + this.$insertLines(0, text); + } else { + this.$insert({row: 0, column: 0}, text); + } +}; + + +(function() { + + oop.implement(this, EventEmitter); + + this.$undoManager = null; + + // check for IE split bug + if ("aaa".split(/a/).length == 0) + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + } + else + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + + this.setValue = function(text) { + var args = [0, this.$lines.length]; + args.push.apply(args, this.$split(text)); + this.$lines.splice.apply(this.$lines, args); + this.modified = true; + this.fireChangeEvent(0); + }; + + this.toString = function() { + return this.$lines.join(this.$getNewLineCharacter()); + }; + + this.getValue = this.toString; + + this.getSelection = function() { + return this.selection; + }; + + this.fireChangeEvent = function(firstRow, lastRow) { + var data = { + firstRow: firstRow, + lastRow: lastRow + }; + this._dispatchEvent("change", { data: data}); + }; + + this.setUndoManager = function(undoManager) { + this.$undoManager = undoManager; + this.$deltas = []; + + if (this.$informUndoManager) { + this.$informUndoManager.cancel(); + } + + if (undoManager) { + var self = this; + this.$informUndoManager = lang.deferredCall(function() { + if (self.$deltas.length > 0) + undoManager.execute({ + action : "aceupdate", + args : [self.$deltas, self] + }); + self.$deltas = []; + }); + } + }; + + this.$defaultUndoManager = { + undo: function() {}, + redo: function() {} + }; + + this.getUndoManager = function() { + return this.$undoManager || this.$defaultUndoManager; + }, + + this.getTabString = function() { + if (this.getUseSoftTabs()) { + return lang.stringRepeat(" ", this.getTabSize()); + } else { + return "\t"; + } + }; + + this.$useSoftTabs = true; + this.setUseSoftTabs = function(useSoftTabs) { + if (this.$useSoftTabs === useSoftTabs) return; + + this.$useSoftTabs = useSoftTabs; + }; + + this.getUseSoftTabs = function() { + return this.$useSoftTabs; + }; + + this.$tabSize = 4; + this.setTabSize = function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.modified = true; + this.$tabSize = tabSize; + this._dispatchEvent("changeTabSize"); + }; + + this.getTabSize = function() { + return this.$tabSize; + }; + + this.isTabStop = function(position) { + return this.$useSoftTabs && (position.column % this.$tabSize == 0); + }; + + this.getBreakpoints = function() { + return this.$breakpoints; + }; + + this.setBreakpoints = function(rows) { + this.$breakpoints = []; + for (var i=0; i 0) { + inToken = !!line.charAt(column - 1).match(this.tokenRe); + } + + if (!inToken) { + inToken = !!line.charAt(column).match(this.tokenRe); + } + + var re = inToken ? this.tokenRe : this.nonTokenRe; + + var start = column; + if (start > 0) { + do { + start--; + } + while (start >= 0 && line.charAt(start).match(re)); + start++; + } + + var end = column; + while (end < line.length && line.charAt(end).match(re)) { + end++; + } + + return new Range(row, start, row, end); + }; + + this.$getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + + case "unix": + return "\n"; + + case "auto": + return this.$autoNewLine; + } + }, + + this.$autoNewLine = "\n"; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) return; + + this.$newLineMode = newLineMode; + }; + + this.getNewLineMode = function() { + return this.$newLineMode; + }; + + this.$mode = null; + this.setMode = function(mode) { + if (this.$mode === mode) return; + + this.$mode = mode; + this._dispatchEvent("changeMode"); + }; + + this.getMode = function() { + if (!this.$mode) { + this.$mode = new TextMode(); + } + return this.$mode; + }; + + this.$scrollTop = 0; + this.setScrollTopRow = function(scrollTopRow) { + if (this.$scrollTop === scrollTopRow) return; + + this.$scrollTop = scrollTopRow; + this._dispatchEvent("changeScrollTop"); + }; + + this.getScrollTopRow = function() { + return this.$scrollTop; + }; + + this.getWidth = function() { + this.$computeWidth(); + return this.width; + }; + + this.getScreenWidth = function() { + this.$computeWidth(); + return this.screenWidth; + }; + + this.$computeWidth = function() { + if (this.modified) { + this.modified = false; + + var lines = this.$lines; + var longestLine = 0; + var longestScreenLine = 0; + var tabSize = this.getTabSize(); + + for ( var i = 0; i < lines.length; i++) { + var len = lines[i].length; + longestLine = Math.max(longestLine, len); + + lines[i].replace("\t", function(m) { + len += tabSize-1; + return m; + }); + longestScreenLine = Math.max(longestScreenLine, len); + } + this.width = longestLine; + this.screenWidth = longestScreenLine; + } + }; + + /** + * Get a verbatim copy of the given line as it is in the document + */ + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + + /** + * Get a line as it is displayed on screen. Tabs are replaced by spaces. + */ + this.getDisplayLine = function(row) { + var tab = new Array(this.getTabSize()+1).join(" "); + return this.$lines[row].replace(/\t/g, tab); + }; + + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow+1); + }; + + this.getLength = function() { + return this.$lines.length; + }; + + this.getTextRange = function(range) { + if (range.start.row == range.end.row) { + return this.$lines[range.start.row].substring(range.start.column, + range.end.column); + } + else { + var lines = []; + lines.push(this.$lines[range.start.row].substring(range.start.column)); + lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1)); + lines.push(this.$lines[range.end.row].substring(0, range.end.column)); + return lines.join(this.$getNewLineCharacter()); + } + }; + + this.findMatchingBracket = function(position) { + if (position.column == 0) return null; + + var charBeforeCursor = this.getLine(position.row).charAt(position.column-1); + if (charBeforeCursor == "") return null; + + var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); + if (!match) { + return null; + } + + if (match[1]) { + return this.$findClosingBracket(match[1], position); + } else { + return this.$findOpeningBracket(match[2], position); + } + }; + + this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{" + }; + + this.$findOpeningBracket = function(bracket, position) { + var openBracket = this.$brackets[bracket]; + + var column = position.column - 2; + var row = position.row; + var depth = 1; + + var line = this.getLine(row); + + while (true) { + while(column >= 0) { + var ch = line.charAt(column); + if (ch == openBracket) { + depth -= 1; + if (depth == 0) { + return {row: row, column: column}; + } + } + else if (ch == bracket) { + depth +=1; + } + column -= 1; + } + row -=1; + if (row < 0) break; + + var line = this.getLine(row); + var column = line.length-1; + } + return null; + }; + + this.$findClosingBracket = function(bracket, position) { + var closingBracket = this.$brackets[bracket]; + + var column = position.column; + var row = position.row; + var depth = 1; + + var line = this.getLine(row); + var lineCount = this.getLength(); + + while (true) { + while(column < line.length) { + var ch = line.charAt(column); + if (ch == closingBracket) { + depth -= 1; + if (depth == 0) { + return {row: row, column: column}; + } + } + else if (ch == bracket) { + depth +=1; + } + column += 1; + } + row +=1; + if (row >= lineCount) break; + + var line = this.getLine(row); + var column = 0; + } + return null; + }; + + this.insert = function(position, text, fromUndo) { + var end = this.$insert(position, text, fromUndo); + this.fireChangeEvent(position.row, position.row == end.row ? position.row + : undefined); + return end; + }; + + /** + * @param rows Array[Integer] sorted list of rows + */ + this.multiRowInsert = function(rows, column, text) { + var lines = this.$lines; + + for (var i=rows.length-1; i>=0; i--) { + var row = rows[i]; + if (row >= lines.length) + continue; + + var diff = column - lines[row].length; + if ( diff > 0) { + var padded = lang.stringRepeat(" ", diff) + text; + var offset = -diff; + } + else { + padded = text; + offset = 0; + } + + var end = this.$insert({row: row, column: column+offset}, padded, false); + } + + if (end) { + this.fireChangeEvent(rows[0], rows[rows.length-1] + end.row - rows[0]); + return { + rows: end.row - rows[0], + columns: end.column - column + } + } + else { + return { + rows: 0, + columns: 0 + } + } + }; + + this.$insertLines = function(row, lines, fromUndo) { + if (lines.length == 0) + return; + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var nl = this.$getNewLineCharacter(); + var delta = { + action: "insertText", + range: new Range(row, 0, row + lines.length, 0), + text: lines.join(nl) + nl + }; + if (!fromUndo && this.$undoManager) { + this.$deltas.push(delta); + this.$informUndoManager.schedule(); + } + + if (fromUndo !== NO_CHANGE_DELTAS) { + this._dispatchEvent("changeDelta", { data: delta }); + } + }, + + this.$insert = function(position, text, fromUndo) { + if (text.length == 0) + return position; + + this.modified = true; + if (this.$lines.length <= 1) { + this.$detectNewLine(text); + } + + var newLines = this.$split(text); + + if (this.$isNewLine(text)) { + var line = this.$lines[position.row] || ""; + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column)); + + var end = { + row : position.row + 1, + column : 0 + }; + } + else if (newLines.length == 1) { + var line = this.$lines[position.row] || ""; + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + } + else { + var line = this.$lines[position.row] || ""; + var firstLine = line.substring(0, position.column) + newLines[0]; + var lastLine = newLines[newLines.length - 1] + line.substring(position.column); + + this.$lines[position.row] = firstLine; + this.$insertLines(position.row + 1, [lastLine], NO_CHANGE_DELTAS); + + if (newLines.length > 2) { + this.$insertLines(position.row + 1, newLines.slice(1, -1), NO_CHANGE_DELTAS); + } + + var end = { + row : position.row + newLines.length - 1, + column : newLines[newLines.length - 1].length + }; + } + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + if (!fromUndo && this.$undoManager) { + this.$deltas.push(delta); + this.$informUndoManager.schedule(); + } + this._dispatchEvent("changeDelta", { data: delta }); + + return end; + }; + + this.$isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + + this.remove = function(range, fromUndo) { + if (range.isEmpty()) + return range.start; + + this.$remove(range, fromUndo); + + this.fireChangeEvent(range.start.row, range.isMultiLine() ? undefined : range.start.row); + + return range.start; + }; + + this.multiRowRemove = function(rows, range) { + if (range.start.row !== rows[0]) + throw new TypeError("range must start in the first row!"); + + var height = range.end.row - rows[0]; + for (var i=rows.length-1; i>=0; i--) { + var row = rows[i]; + if (row >= this.$lines.length) + continue; + + var end = this.$remove(new Range(row, range.start.column, row+height, range.end.column), false); + } + + if (end) { + if (height < 0) + this.fireChangeEvent(rows[0]+height, undefined); + else + this.fireChangeEvent(rows[0], height == 0 ? rows[rows.length-1] : undefined); + } + }; + + this.$remove = function(range, fromUndo) { + if (range.isEmpty()) + return; + + var delta = { + action: "removeText", + range: range.clone(), + text: this.getTextRange(range) + }; + if (!fromUndo && this.$undoManager) { + this.$deltas.push(delta); + this.$informUndoManager.schedule(); + } + + this.modified = true; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + var row = this.getLine(firstRow).substring(0, range.start.column) + + this.getLine(lastRow).substring(range.end.column); + + if (row != "") + this.$lines.splice(firstRow, lastRow - firstRow + 1, row); + else + this.$lines.splice(firstRow, lastRow - firstRow + 1, ""); + + this._dispatchEvent("changeDelta", { data: delta }); + return range.start; + }; + + this.undoChanges = function(deltas) { + this.selection.clearSelection(); + for (var i=deltas.length-1; i>=0; i--) { + var delta = deltas[i]; + if (delta.action == "insertText") { + this.remove(delta.range, true); + this.selection.moveCursorToPosition(delta.range.start); + } else { + this.insert(delta.range.start, delta.text, true); + this.selection.clearSelection(); + } + } + }, + + this.redoChanges = function(deltas) { + this.selection.clearSelection(); + for (var i=0; i= this.$lines.length-1) return 0; + + var removed = this.$lines.slice(firstRow, lastRow + 1); + this.$remove(new Range(firstRow, 0, lastRow + 1, 0)); + this.$insertLines(firstRow+1, removed); + + this.fireChangeEvent(firstRow, lastRow + 1); + return 1; + }; + + this.duplicateLines = function(firstRow, lastRow) { + var firstRow = this.$clipRowToDocument(firstRow); + var lastRow = this.$clipRowToDocument(lastRow); + + var lines = this.getLines(firstRow, lastRow); + this.$insertLines(firstRow, lines); + + var addedRows = lastRow - firstRow + 1; + this.fireChangeEvent(firstRow); + + return addedRows; + }; + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.$lines.length-1)); + }; + + this.documentToScreenColumn = function(row, docColumn) { + var tabSize = this.getTabSize(); + + var screenColumn = 0; + var remaining = docColumn; + + var line = this.getLine(row).split("\t"); + for (var i=0; i len) { + remaining -= (len + 1); + screenColumn += len + tabSize; + } + else { + screenColumn += remaining; + break; + } + } + + return screenColumn; + }; + + this.screenToDocumentColumn = function(row, screenColumn) { + var tabSize = this.getTabSize(); + + var docColumn = 0; + var remaining = screenColumn; + + var line = this.getLine(row).split("\t"); + for (var i=0; i= len + tabSize) { + remaining -= (len + tabSize); + docColumn += (len + 1); + } + else if (remaining > len){ + docColumn += len; + break; + } + else { + docColumn += remaining; + break; + } + } + return docColumn; + }; + +}).call(EditSession.prototype); + +exports.EditSession = EditSession; +}); diff --git a/lib/ace/test/document_test.js b/lib/ace/test/document_test.js index 1df5f511..9076a7fd 100644 --- a/lib/ace/test/document_test.js +++ b/lib/ace/test/document_test.js @@ -35,259 +35,56 @@ * * ***** END LICENSE BLOCK ***** */ -define(function(require, exports, module) { - var Document = require("../document").Document, - UndoManager = require("../undomanager").UndoManager, - MockRenderer = require("./mockrenderer"), Range = require("../range").Range, assert = require("./assertions"), async = require("async"); var Test = { - "test: find matching opening bracket" : function() { - var doc = new Document(["(()(", "())))"]); - - assert.position(doc.findMatchingBracket({row: 0, column: 3}), 0, 1); - assert.position(doc.findMatchingBracket({row: 1, column: 2}), 1, 0); - assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 3); - assert.position(doc.findMatchingBracket({row: 1, column: 4}), 0, 0); - assert.equal(doc.findMatchingBracket({row: 1, column: 5}), null); - }, - - "test: find matching closing bracket" : function() { - var doc = new Document(["(()(", "())))"]); - - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); - assert.position(doc.findMatchingBracket({row: 0, column: 4}), 1, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 2}), 0, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 3); - assert.equal(doc.findMatchingBracket({row: 0, column: 0}), null); - }, - - "test: match different bracket types" : function() { - var doc = new Document(["({[", ")]}"]); - - assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 0); - assert.position(doc.findMatchingBracket({row: 0, column: 2}), 1, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 3}), 1, 1); - - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 0, 0); - assert.position(doc.findMatchingBracket({row: 1, column: 2}), 0, 2); - assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 1); - }, - - "test: move lines down" : function() { - var doc = new Document(["a1", "a2", "a3", "a4"]); - - doc.moveLinesDown(0, 1); - assert.equal(doc.toString(), ["a3", "a1", "a2", "a4"].join("\n")); - - doc.moveLinesDown(1, 2); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); - - doc.moveLinesDown(2, 3); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); - - doc.moveLinesDown(2, 2); - assert.equal(doc.toString(), ["a3", "a4", "a2", "a1"].join("\n")); - }, - - "test: move lines up" : function() { - var doc = new Document(["a1", "a2", "a3", "a4"]); - - doc.moveLinesUp(2, 3); - assert.equal(doc.toString(), ["a1", "a3", "a4", "a2"].join("\n")); - - doc.moveLinesUp(1, 2); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); - - doc.moveLinesUp(0, 1); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); - - doc.moveLinesUp(2, 2); - assert.equal(doc.toString(), ["a3", "a1", "a4", "a2"].join("\n")); - }, - - "test: duplicate lines" : function() { - var doc = new Document(["1", "2", "3", "4"]); - - doc.duplicateLines(1, 2); - assert.equal(doc.toString(), ["1", "2", "3", "2", "3", "4"].join("\n")); - }, - - "test: duplicate last line" : function() { - var doc = new Document(["1", "2", "3"]); - - doc.duplicateLines(2, 2); - assert.equal(doc.toString(), ["1", "2", "3", "3"].join("\n")); - }, - - "test: duplicate first line" : function() { - var doc = new Document(["1", "2", "3"]); - - doc.duplicateLines(0, 0); - assert.equal(doc.toString(), ["1", "1", "2", "3"].join("\n")); - }, - "test: should handle unix style new lines" : function() { var doc = new Document(["1", "2", "3"]); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); }, "test: should handle windows style new lines" : function() { var doc = new Document(["1", "2", "3"].join("\r\n")); doc.setNewLineMode("unix"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); }, "test: set new line mode to 'windows' should use '\r\n' as new lines": function() { var doc = new Document(["1", "2", "3"].join("\n")); doc.setNewLineMode("windows"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n")); }, "test: set new line mode to 'unix' should use '\n' as new lines": function() { var doc = new Document(["1", "2", "3"].join("\r\n")); doc.setNewLineMode("unix"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); }, "test: set new line mode to 'auto' should detect the incoming nl type": function() { var doc = new Document(["1", "2", "3"].join("\n")); doc.setNewLineMode("auto"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); var doc = new Document(["1", "2", "3"].join("\r\n")); doc.setNewLineMode("auto"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n")); doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n")); - assert.equal(["4", "5", "6"].join("\n"), doc.toString()); - }, - - "test: convert document to screen coordinates" : function() { - var doc = new Document("01234\t567890\t1234"); - doc.setTabSize(4); - - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 4), 4); - assert.equal(doc.documentToScreenColumn(0, 5), 5); - assert.equal(doc.documentToScreenColumn(0, 6), 9); - assert.equal(doc.documentToScreenColumn(0, 12), 15); - assert.equal(doc.documentToScreenColumn(0, 13), 19); - - doc.setTabSize(2); - - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 4), 4); - assert.equal(doc.documentToScreenColumn(0, 5), 5); - assert.equal(doc.documentToScreenColumn(0, 6), 7); - assert.equal(doc.documentToScreenColumn(0, 12), 13); - assert.equal(doc.documentToScreenColumn(0, 13), 15); - }, - - "test: convert document to scrren coordinates with leading tabs": function() { - var doc = new Document("\t\t123"); - doc.setTabSize(4); - - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 1), 4); - assert.equal(doc.documentToScreenColumn(0, 2), 8); - assert.equal(doc.documentToScreenColumn(0, 3), 9); - }, - - "test: convert screen to document coordinates" : function() { - var doc = new Document("01234\t567890\t1234"); - doc.setTabSize(4); - - assert.equal(doc.screenToDocumentColumn(0, 0), 0); - assert.equal(doc.screenToDocumentColumn(0, 4), 4); - assert.equal(doc.screenToDocumentColumn(0, 5), 5); - assert.equal(doc.screenToDocumentColumn(0, 6), 5); - assert.equal(doc.screenToDocumentColumn(0, 7), 5); - assert.equal(doc.screenToDocumentColumn(0, 8), 5); - assert.equal(doc.screenToDocumentColumn(0, 9), 6); - assert.equal(doc.screenToDocumentColumn(0, 15), 12); - assert.equal(doc.screenToDocumentColumn(0, 19), 13); - }, - - "test: insert text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); - - var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); - assert.equal(inserted.rows, 0); - assert.equal(inserted.columns, 6); - - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); - }, - - "test: undo insert text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); - - var undoManager = new UndoManager(); - doc.setUndoManager(undoManager); - - doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); - doc.$informUndoManager.call(); - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); - - undoManager.undo(); - assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); - - undoManager.redo(); - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); - }, - - "test: insert new line in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); - - var inserted = doc.multiRowInsert([0, 1, 2], 2, "\n"); - assert.equal(inserted.rows, 1); - assert.equal(doc.toString(), ["12\n", " \n", "ab\ncd"].join("\n")); - }, - - "test: insert multi line text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); - - var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu\n12"); - assert.equal(inserted.rows, 1); - assert.equal(doc.toString(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n")); - }, - - "test: remove right in multiple rows" : function() { - var doc = new Document(["12", "", "abcd"]); - - doc.multiRowRemove([0, 1, 2], new Range(0, 2, 0, 3)); - assert.equal(doc.toString(), ["12", "", "abd"].join("\n")); - }, - - "test: undo remove right in multiple rows" : function() { - var doc = new Document(["12", "", "abcd"]); - var undoManager = new UndoManager(); - doc.setUndoManager(undoManager); - - doc.multiRowRemove([0, 1, 2], new Range(0, 1, 0, 3)); - doc.$informUndoManager.call(); - assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); - - undoManager.undo(); - assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); - - undoManager.redo(); - assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); + assert.equal(["4", "5", "6"].join("\n"), doc.getValue()); } }; module.exports = require("async/test").testcase(Test); -}); if (module === require.main) { require("../../../support/paths"); diff --git a/lib/ace/test/edit_session_test.js b/lib/ace/test/edit_session_test.js new file mode 100644 index 00000000..1df5f511 --- /dev/null +++ b/lib/ace/test/edit_session_test.js @@ -0,0 +1,295 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var Document = require("../document").Document, + UndoManager = require("../undomanager").UndoManager, + MockRenderer = require("./mockrenderer"), + Range = require("../range").Range, + assert = require("./assertions"), + async = require("async"); + +var Test = { + + "test: find matching opening bracket" : function() { + var doc = new Document(["(()(", "())))"]); + + assert.position(doc.findMatchingBracket({row: 0, column: 3}), 0, 1); + assert.position(doc.findMatchingBracket({row: 1, column: 2}), 1, 0); + assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 3); + assert.position(doc.findMatchingBracket({row: 1, column: 4}), 0, 0); + assert.equal(doc.findMatchingBracket({row: 1, column: 5}), null); + }, + + "test: find matching closing bracket" : function() { + var doc = new Document(["(()(", "())))"]); + + assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); + assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); + assert.position(doc.findMatchingBracket({row: 0, column: 4}), 1, 2); + assert.position(doc.findMatchingBracket({row: 0, column: 2}), 0, 2); + assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 3); + assert.equal(doc.findMatchingBracket({row: 0, column: 0}), null); + }, + + "test: match different bracket types" : function() { + var doc = new Document(["({[", ")]}"]); + + assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 0); + assert.position(doc.findMatchingBracket({row: 0, column: 2}), 1, 2); + assert.position(doc.findMatchingBracket({row: 0, column: 3}), 1, 1); + + assert.position(doc.findMatchingBracket({row: 1, column: 1}), 0, 0); + assert.position(doc.findMatchingBracket({row: 1, column: 2}), 0, 2); + assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 1); + }, + + "test: move lines down" : function() { + var doc = new Document(["a1", "a2", "a3", "a4"]); + + doc.moveLinesDown(0, 1); + assert.equal(doc.toString(), ["a3", "a1", "a2", "a4"].join("\n")); + + doc.moveLinesDown(1, 2); + assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + + doc.moveLinesDown(2, 3); + assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + + doc.moveLinesDown(2, 2); + assert.equal(doc.toString(), ["a3", "a4", "a2", "a1"].join("\n")); + }, + + "test: move lines up" : function() { + var doc = new Document(["a1", "a2", "a3", "a4"]); + + doc.moveLinesUp(2, 3); + assert.equal(doc.toString(), ["a1", "a3", "a4", "a2"].join("\n")); + + doc.moveLinesUp(1, 2); + assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + + doc.moveLinesUp(0, 1); + assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + + doc.moveLinesUp(2, 2); + assert.equal(doc.toString(), ["a3", "a1", "a4", "a2"].join("\n")); + }, + + "test: duplicate lines" : function() { + var doc = new Document(["1", "2", "3", "4"]); + + doc.duplicateLines(1, 2); + assert.equal(doc.toString(), ["1", "2", "3", "2", "3", "4"].join("\n")); + }, + + "test: duplicate last line" : function() { + var doc = new Document(["1", "2", "3"]); + + doc.duplicateLines(2, 2); + assert.equal(doc.toString(), ["1", "2", "3", "3"].join("\n")); + }, + + "test: duplicate first line" : function() { + var doc = new Document(["1", "2", "3"]); + + doc.duplicateLines(0, 0); + assert.equal(doc.toString(), ["1", "1", "2", "3"].join("\n")); + }, + + "test: should handle unix style new lines" : function() { + var doc = new Document(["1", "2", "3"]); + + assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + }, + + "test: should handle windows style new lines" : function() { + var doc = new Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("unix"); + assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + }, + + "test: set new line mode to 'windows' should use '\r\n' as new lines": function() { + var doc = new Document(["1", "2", "3"].join("\n")); + doc.setNewLineMode("windows"); + assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); + }, + + "test: set new line mode to 'unix' should use '\n' as new lines": function() { + var doc = new Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("unix"); + assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + }, + + "test: set new line mode to 'auto' should detect the incoming nl type": function() { + var doc = new Document(["1", "2", "3"].join("\n")); + + doc.setNewLineMode("auto"); + assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); + + var doc = new Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("auto"); + assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); + + doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n")); + assert.equal(["4", "5", "6"].join("\n"), doc.toString()); + }, + + "test: convert document to screen coordinates" : function() { + var doc = new Document("01234\t567890\t1234"); + doc.setTabSize(4); + + assert.equal(doc.documentToScreenColumn(0, 0), 0); + assert.equal(doc.documentToScreenColumn(0, 4), 4); + assert.equal(doc.documentToScreenColumn(0, 5), 5); + assert.equal(doc.documentToScreenColumn(0, 6), 9); + assert.equal(doc.documentToScreenColumn(0, 12), 15); + assert.equal(doc.documentToScreenColumn(0, 13), 19); + + doc.setTabSize(2); + + assert.equal(doc.documentToScreenColumn(0, 0), 0); + assert.equal(doc.documentToScreenColumn(0, 4), 4); + assert.equal(doc.documentToScreenColumn(0, 5), 5); + assert.equal(doc.documentToScreenColumn(0, 6), 7); + assert.equal(doc.documentToScreenColumn(0, 12), 13); + assert.equal(doc.documentToScreenColumn(0, 13), 15); + }, + + "test: convert document to scrren coordinates with leading tabs": function() { + var doc = new Document("\t\t123"); + doc.setTabSize(4); + + assert.equal(doc.documentToScreenColumn(0, 0), 0); + assert.equal(doc.documentToScreenColumn(0, 1), 4); + assert.equal(doc.documentToScreenColumn(0, 2), 8); + assert.equal(doc.documentToScreenColumn(0, 3), 9); + }, + + "test: convert screen to document coordinates" : function() { + var doc = new Document("01234\t567890\t1234"); + doc.setTabSize(4); + + assert.equal(doc.screenToDocumentColumn(0, 0), 0); + assert.equal(doc.screenToDocumentColumn(0, 4), 4); + assert.equal(doc.screenToDocumentColumn(0, 5), 5); + assert.equal(doc.screenToDocumentColumn(0, 6), 5); + assert.equal(doc.screenToDocumentColumn(0, 7), 5); + assert.equal(doc.screenToDocumentColumn(0, 8), 5); + assert.equal(doc.screenToDocumentColumn(0, 9), 6); + assert.equal(doc.screenToDocumentColumn(0, 15), 12); + assert.equal(doc.screenToDocumentColumn(0, 19), 13); + }, + + "test: insert text in multiple rows": function() { + var doc = new Document(["12", "", "abcd"]); + + var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); + assert.equal(inserted.rows, 0); + assert.equal(inserted.columns, 6); + + assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + }, + + "test: undo insert text in multiple rows": function() { + var doc = new Document(["12", "", "abcd"]); + + var undoManager = new UndoManager(); + doc.setUndoManager(undoManager); + + doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); + doc.$informUndoManager.call(); + assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + + undoManager.undo(); + assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); + + undoManager.redo(); + assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + }, + + "test: insert new line in multiple rows": function() { + var doc = new Document(["12", "", "abcd"]); + + var inserted = doc.multiRowInsert([0, 1, 2], 2, "\n"); + assert.equal(inserted.rows, 1); + assert.equal(doc.toString(), ["12\n", " \n", "ab\ncd"].join("\n")); + }, + + "test: insert multi line text in multiple rows": function() { + var doc = new Document(["12", "", "abcd"]); + + var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu\n12"); + assert.equal(inserted.rows, 1); + assert.equal(doc.toString(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n")); + }, + + "test: remove right in multiple rows" : function() { + var doc = new Document(["12", "", "abcd"]); + + doc.multiRowRemove([0, 1, 2], new Range(0, 2, 0, 3)); + assert.equal(doc.toString(), ["12", "", "abd"].join("\n")); + }, + + "test: undo remove right in multiple rows" : function() { + var doc = new Document(["12", "", "abcd"]); + var undoManager = new UndoManager(); + doc.setUndoManager(undoManager); + + doc.multiRowRemove([0, 1, 2], new Range(0, 1, 0, 3)); + doc.$informUndoManager.call(); + assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); + + undoManager.undo(); + assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); + + undoManager.redo(); + assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); + } +}; + +module.exports = require("async/test").testcase(Test); +}); + +if (module === require.main) { + require("../../../support/paths"); + exports.exec() +} \ No newline at end of file From 6f6c6424e7959b999aa5f1c0d35c8beb3192d8a8 Mon Sep 17 00:00:00 2001 From: "Fabian Jakobs (c9)" Date: Tue, 18 Jan 2011 14:27:58 +0100 Subject: [PATCH 03/36] update pilot --- support/pilot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/pilot b/support/pilot index a7d30d94..250ffe66 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit a7d30d942c7b8f9e68bcb818a83faaa407404c56 +Subproject commit 250ffe66af17457c8d56660b57cdf7ae6cef73c3 From eece670fb09bb709f36118816d21469024d796fa Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 07:20:23 +0100 Subject: [PATCH 04/36] add undo/redo support to the new document and add unit tests --- lib/ace/document.js | 88 +++++++++++++--- lib/ace/test/document_test.js | 191 +++++++++++++++++++++++++++++++++- 2 files changed, 261 insertions(+), 18 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 99a76fc4..0e6258a4 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -38,7 +38,6 @@ define(function(require, exports, module) { var oop = require("pilot/oop"); -var lang = require("pilot/lang"); var EventEmitter = require("pilot/event_emitter").EventEmitter; var Range = require("ace/range").Range; @@ -143,10 +142,21 @@ var Document = function(text) { } }; + this.$clipPosition = function(position) { + var length = this.$lines.length; + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } + return position; + } + this.insert = function(position, text) { if (text.length == 0) return position; - + + position = this.$clipPosition(position); + if (this.$lines.length <= 1) { this.$detectNewLine(text); } @@ -160,7 +170,8 @@ var Document = function(text) { var end = this.insertInLine(position, text); } else { - this.insertInLine(position, newLines[0]); + var end = this.insertInLine(position, newLines[0]); + this.insertNewLine(end); if (newLines.length > 2) this.insertLines(position.row+1, newLines.slice(1, newLines.length-1)); @@ -173,24 +184,23 @@ var Document = function(text) { this.insertLines = function(row, lines) { if (lines.length == 0) return {row: row, column: 0}; - + var args = [row, 0]; args.push.apply(args, lines); this.$lines.splice.apply(this.$lines, args); - var range = new Range(row, 0, row + lines.length, 0); + var range = new Range(row, 0, row + lines.length - 1, 0); var delta = { action: "insertLines", - nl: this.getNewLineCharacter(), range: range, lines: lines }; - this._dispatchEvent("changeDelta", { data: delta }); + this._dispatchEvent("change", { data: delta }); return range.end; }, this.insertNewLine = function(position) { - console.log(position) + position = this.$clipPosition(position); var line = this.$lines[position.row] || ""; this.$lines[position.row] = line.substring(0, position.column); this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); @@ -205,12 +215,15 @@ var Document = function(text) { range: Range.fromPoints(position, end), text: this.getNewLineCharacter() }; - this._dispatchEvent("changeDelta", { data: delta }); + this._dispatchEvent("change", { data: delta }); return end; }; this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + var line = this.$lines[position.row] || ""; this.$lines[position.row] = line.substring(0, position.column) + text + line.substring(position.column); @@ -225,18 +238,23 @@ var Document = function(text) { range: Range.fromPoints(position, end), text: text }; - this._dispatchEvent("changeDelta", { data: delta }); + this._dispatchEvent("change", { data: delta }); return end; }; this.remove = function(range) { + // clip to document + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + if (range.isEmpty()) - return range.start; + return; + + var firstRow = range.start.row; + var lastRow = range.end.row; if (range.isMultiLine()) { - var firstRow = range.start.row; - var lastRow = range.end.row; // TODO removeInLine can be optimized away! this.removeInLine(lastRow, 0, range.end.column); @@ -246,13 +264,16 @@ var Document = function(text) { this.removeNewLine(range.start.row); } else { - this.removeInLine(range) + this.removeInLine(firstRow, range.start.column, range.end.column); } }; this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + var range = new Range(row, startColumn, row, endColumn); - var line = this.$lines[row]; + var line = this.getLine(row); var removed = line.substring(startColumn, endColumn); var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); this.$lines.splice(row, 1, newLine); @@ -262,6 +283,7 @@ var Document = function(text) { range: range, text: removed }; + this._dispatchEvent("change", { data: delta }); return range.start; }; @@ -275,7 +297,7 @@ var Document = function(text) { nl: this.getNewLineCharacter(), lines: removed }; - this._dispatchEvent("changeDelta", { data: delta }); + this._dispatchEvent("change", { data: delta }); }; this.removeNewLine = function(row) { @@ -292,7 +314,7 @@ var Document = function(text) { range: range, text: this.getNewLineCharacter() }; - this._dispatchEvent("changeDelta", { data: delta }); + this._dispatchEvent("change", { data: delta }); }; this.replace = function(range, text) { @@ -316,6 +338,38 @@ var Document = function(text) { return end; }; + + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + var range = delta.range; + + if (delta.action == "insertLines") + this.removeLines(range.start.row, range.end.row) + else if (delta.action == "insertText") + this.remove(range) + else if (delta.action == "removeLines") + this.insertLines(range.start.row, delta.lines) + else if (delta.action == "removeText") + this.insert(range.start, delta.text) + } + }; }).call(Document.prototype); diff --git a/lib/ace/test/document_test.js b/lib/ace/test/document_test.js index 9076a7fd..5fc27ec3 100644 --- a/lib/ace/test/document_test.js +++ b/lib/ace/test/document_test.js @@ -42,9 +42,198 @@ var Document = require("../document").Document, var Test = { + "test: insert text in line" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insert({row: 0, column: 1}, "juhu"); + assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); + }, + + "test: insert new line" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insertNewLine({row: 0, column: 1}); + assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); + }, + + "test: insert lines at the beginning" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insertLines(0, ["aa", "bb"]); + assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); + }, + + "test: insert lines at the end" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insertLines(2, ["aa", "bb"]); + assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n")); + }, + + "test: insert lines in the middle" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insertLines(1, ["aa", "bb"]); + assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); + }, + + "test: insert multi line string at the start" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insert({row: 0, column: 0}, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); + }, + + "test: insert multi line string at the end" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insert({row: 2, column: 0}, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); + }, + + "test: insert multi line string in the middle" : function() { + var doc = new Document(["12", "34"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.insert({row: 0, column: 1}, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); + }, + + "test: delete in line" : function() { + var doc = new Document(["1234", "5678"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.remove(new Range(0, 1, 0, 3)); + assert.equal(doc.getValue(), ["14", "5678"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["14", "5678"].join("\n")); + }, + + "test: delete new line" : function() { + var doc = new Document(["1234", "5678"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.remove(new Range(0, 4, 1, 0)); + assert.equal(doc.getValue(), ["12345678"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12345678"].join("\n")); + }, + + "test: delete multi line range line" : function() { + var doc = new Document(["1234", "5678", "abcd"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.remove(new Range(0, 2, 2, 2)); + assert.equal(doc.getValue(), ["12cd"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12cd"].join("\n")); + }, + + "test: delete full lines" : function() { + var doc = new Document(["1234", "5678", "abcd"]); + + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); + + doc.remove(new Range(1, 0, 3, 0)); + assert.equal(doc.getValue(), ["1234", ""].join("\n")); + }, + "test: should handle unix style new lines" : function() { var doc = new Document(["1", "2", "3"]); - assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); }, From 2db078554453981397be70d7562c161c5a0fbe89 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 08:14:28 +0100 Subject: [PATCH 05/36] remove lines returns the removed lines --- lib/ace/document.js | 16 ++++++++++++++++ lib/ace/test/document_test.js | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/lib/ace/document.js b/lib/ace/document.js index 0e6258a4..db6e4d54 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -123,6 +123,14 @@ var Document = function(text) { this.getLines = function(firstRow, lastRow) { return this.$lines.slice(firstRow, lastRow+1); }; + + /** + * Returns all lines in the document as string array. Warning: The caller + * should not modify this array! + */ + this.getAllLines = function() { + return this.$lines; + }; this.getLength = function() { return this.$lines.length; @@ -287,6 +295,13 @@ var Document = function(text) { return range.start; }; + /** + * Removes a range of full lines + * + * @param firstRow {Integer} The first row to be removed + * @param firstRow {Integer} The first row to be removed + * @return {String[]} The removed lines + */ this.removeLines = function(firstRow, lastRow) { var range = new Range(firstRow, 0, lastRow, this.$lines[lastRow].length); var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); @@ -298,6 +313,7 @@ var Document = function(text) { lines: removed }; this._dispatchEvent("change", { data: delta }); + return removed; }; this.removeNewLine = function(row) { diff --git a/lib/ace/test/document_test.js b/lib/ace/test/document_test.js index 5fc27ec3..2d8f9b33 100644 --- a/lib/ace/test/document_test.js +++ b/lib/ace/test/document_test.js @@ -231,6 +231,13 @@ var Test = { doc.remove(new Range(1, 0, 3, 0)); assert.equal(doc.getValue(), ["1234", ""].join("\n")); }, + + "test: remove lines should return the removed lines" : function() { + var doc = new Document(["1234", "5678", "abcd"]); + + var removed = doc.removeLines(1, 2); + assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n")); + }, "test: should handle unix style new lines" : function() { var doc = new Document(["1", "2", "3"]); From 8a8cf3265e16e651669e8c843c9e9b76547fc0f2 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 08:15:03 +0100 Subject: [PATCH 06/36] strip document handling from the edit session --- lib/ace/edit_session.js | 349 ++++++------------------------ lib/ace/test/edit_session_test.js | 253 +++++++++------------- 2 files changed, 174 insertions(+), 428 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 1a5dd67c..36de153c 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -43,13 +43,12 @@ var EventEmitter = require("pilot/event_emitter").EventEmitter; var Selection = require("ace/selection").Selection; var TextMode = require("ace/mode/text").Mode; var Range = require("ace/range").Range; +var Document = require("ace/document").Document; var NO_CHANGE_DELTAS = {}; var EditSession = function(text, mode) { - this.modified = true; - this.$lines = []; this.selection = new Selection(this); this.$breakpoints = []; @@ -58,10 +57,10 @@ var EditSession = function(text, mode) { this.setMode(mode); } - if (Array.isArray(text)) { - this.$insertLines(0, text); + if (text instanceof Document) { + this.setDocument(text) } else { - this.$insert({row: 0, column: 0}, text); + this.setDocument(new Document(text)); } }; @@ -70,42 +69,35 @@ var EditSession = function(text, mode) { oop.implement(this, EventEmitter); - this.$undoManager = null; - - // check for IE split bug - if ("aaa".split(/a/).length == 0) - this.$split = function(text) { - return text.replace(/\r\n|\r/g, "\n").split("\n"); - } - else - this.$split = function(text) { - return text.split(/\r\n|\r|\n/); - }; - - this.setValue = function(text) { - var args = [0, this.$lines.length]; - args.push.apply(args, this.$split(text)); - this.$lines.splice.apply(this.$lines, args); - this.modified = true; - this.fireChangeEvent(0); - }; - - this.toString = function() { - return this.$lines.join(this.$getNewLineCharacter()); + this.setDocument = function(doc) { + if (this.doc) + throw new Error("Document is already set"); + + this.doc = doc; + doc.on("change", this.onChange.bind(this)); }; - this.getValue = this.toString; - - this.getSelection = function() { - return this.selection; + this.onChange = function(e) { + var delta = e.data; + this.$modified = true; + if (!this.$fromUndo && this.$undoManager) { + this.$deltas.push(delta); + this.$informUndoManager.schedule(); + } + this._dispatchEvent("change", e); }; - this.fireChangeEvent = function(firstRow, lastRow) { - var data = { - firstRow: firstRow, - lastRow: lastRow - }; - this._dispatchEvent("change", { data: data}); + this.setValue = function(text) { + this.doc.setValue(text); + }; + + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + + this.getSelection = function() { + return this.selection; }; this.setUndoManager = function(undoManager) { @@ -161,7 +153,7 @@ var EditSession = function(text, mode) { this.setTabSize = function(tabSize) { if (isNaN(tabSize) || this.$tabSize === tabSize) return; - this.modified = true; + this.$modified = true; this.$tabSize = tabSize; this._dispatchEvent("changeTabSize"); }; @@ -244,29 +236,12 @@ var EditSession = function(text, mode) { return new Range(row, start, row, end); }; - this.$getNewLineCharacter = function() { - switch (this.$newLineMode) { - case "windows": - return "\r\n"; - - case "unix": - return "\n"; - - case "auto": - return this.$autoNewLine; - } - }, - - this.$autoNewLine = "\n"; - this.$newLineMode = "auto"; this.setNewLineMode = function(newLineMode) { - if (this.$newLineMode === newLineMode) return; - - this.$newLineMode = newLineMode; + this.doc.setNewLineMode(newLineMode); }; this.getNewLineMode = function() { - return this.$newLineMode; + return this.doc.getNewLineMode(); }; this.$mode = null; @@ -307,10 +282,10 @@ var EditSession = function(text, mode) { }; this.$computeWidth = function() { - if (this.modified) { - this.modified = false; + if (this.$modified) { + this.$modified = false; - var lines = this.$lines; + var lines = this.doc.getAllLines(); var longestLine = 0; var longestScreenLine = 0; var tabSize = this.getTabSize(); @@ -334,7 +309,7 @@ var EditSession = function(text, mode) { * Get a verbatim copy of the given line as it is in the document */ this.getLine = function(row) { - return this.$lines[row] || ""; + return this.doc.getLine(row); }; /** @@ -342,29 +317,19 @@ var EditSession = function(text, mode) { */ this.getDisplayLine = function(row) { var tab = new Array(this.getTabSize()+1).join(" "); - return this.$lines[row].replace(/\t/g, tab); + return this.doc.getLine(row).replace(/\t/g, tab); }; this.getLines = function(firstRow, lastRow) { - return this.$lines.slice(firstRow, lastRow+1); + return this.doc.getLines(firstRow, lastRow); }; this.getLength = function() { - return this.$lines.length; + return this.doc.getLength(); }; this.getTextRange = function(range) { - if (range.start.row == range.end.row) { - return this.$lines[range.start.row].substring(range.start.column, - range.end.column); - } - else { - var lines = []; - lines.push(this.$lines[range.start.row].substring(range.start.column)); - lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1)); - lines.push(this.$lines[range.end.row].substring(0, range.end.column)); - return lines.join(this.$getNewLineCharacter()); - } + return this.doc.getTextRange(range); }; this.findMatchingBracket = function(position) { @@ -459,25 +424,20 @@ var EditSession = function(text, mode) { return null; }; - this.insert = function(position, text, fromUndo) { - var end = this.$insert(position, text, fromUndo); - this.fireChangeEvent(position.row, position.row == end.row ? position.row - : undefined); - return end; + this.insert = function(position, text) { + return this.doc.insert(position, text); }; /** * @param rows Array[Integer] sorted list of rows */ - this.multiRowInsert = function(rows, column, text) { - var lines = this.$lines; - + this.multiRowInsert = function(rows, column, text) { for (var i=rows.length-1; i>=0; i--) { var row = rows[i]; - if (row >= lines.length) + if (row >= this.doc.getLength()) continue; - var diff = column - lines[row].length; + var diff = column - this.doc.getLine(row).length; if ( diff > 0) { var padded = lang.stringRepeat(" ", diff) + text; var offset = -diff; @@ -487,124 +447,17 @@ var EditSession = function(text, mode) { offset = 0; } - var end = this.$insert({row: row, column: column+offset}, padded, false); + var end = this.insert({row: row, column: column+offset}, padded); } - if (end) { - this.fireChangeEvent(rows[0], rows[rows.length-1] + end.row - rows[0]); - return { - rows: end.row - rows[0], - columns: end.column - column - } - } - else { - return { - rows: 0, - columns: 0 - } + return { + rows: end ? end.row - rows[0] : 0, + columns: end ? end.column - column : 0 } }; - this.$insertLines = function(row, lines, fromUndo) { - if (lines.length == 0) - return; - - var args = [row, 0]; - args.push.apply(args, lines); - this.$lines.splice.apply(this.$lines, args); - - var nl = this.$getNewLineCharacter(); - var delta = { - action: "insertText", - range: new Range(row, 0, row + lines.length, 0), - text: lines.join(nl) + nl - }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } - - if (fromUndo !== NO_CHANGE_DELTAS) { - this._dispatchEvent("changeDelta", { data: delta }); - } - }, - - this.$insert = function(position, text, fromUndo) { - if (text.length == 0) - return position; - - this.modified = true; - if (this.$lines.length <= 1) { - this.$detectNewLine(text); - } - - var newLines = this.$split(text); - - if (this.$isNewLine(text)) { - var line = this.$lines[position.row] || ""; - this.$lines[position.row] = line.substring(0, position.column); - this.$lines.splice(position.row + 1, 0, line.substring(position.column)); - - var end = { - row : position.row + 1, - column : 0 - }; - } - else if (newLines.length == 1) { - var line = this.$lines[position.row] || ""; - this.$lines[position.row] = line.substring(0, position.column) + text - + line.substring(position.column); - - var end = { - row : position.row, - column : position.column + text.length - }; - } - else { - var line = this.$lines[position.row] || ""; - var firstLine = line.substring(0, position.column) + newLines[0]; - var lastLine = newLines[newLines.length - 1] + line.substring(position.column); - - this.$lines[position.row] = firstLine; - this.$insertLines(position.row + 1, [lastLine], NO_CHANGE_DELTAS); - - if (newLines.length > 2) { - this.$insertLines(position.row + 1, newLines.slice(1, -1), NO_CHANGE_DELTAS); - } - - var end = { - row : position.row + newLines.length - 1, - column : newLines[newLines.length - 1].length - }; - } - - var delta = { - action: "insertText", - range: Range.fromPoints(position, end), - text: text - }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } - this._dispatchEvent("changeDelta", { data: delta }); - - return end; - }; - - this.$isNewLine = function(text) { - return (text == "\r\n" || text == "\r" || text == "\n"); - }; - - this.remove = function(range, fromUndo) { - if (range.isEmpty()) - return range.start; - - this.$remove(range, fromUndo); - - this.fireChangeEvent(range.start.row, range.isMultiLine() ? undefined : range.start.row); - - return range.start; + this.remove = function(range) { + return this.doc.remove(range); }; this.multiRowRemove = function(rows, range) { @@ -614,53 +467,16 @@ var EditSession = function(text, mode) { var height = range.end.row - rows[0]; for (var i=rows.length-1; i>=0; i--) { var row = rows[i]; - if (row >= this.$lines.length) + if (row >= this.doc.getLength()) continue; - var end = this.$remove(new Range(row, range.start.column, row+height, range.end.column), false); + var end = this.remove(new Range(row, range.start.column, row+height, range.end.column)); } - - if (end) { - if (height < 0) - this.fireChangeEvent(rows[0]+height, undefined); - else - this.fireChangeEvent(rows[0], height == 0 ? rows[rows.length-1] : undefined); - } - }; - - this.$remove = function(range, fromUndo) { - if (range.isEmpty()) - return; - - var delta = { - action: "removeText", - range: range.clone(), - text: this.getTextRange(range) - }; - if (!fromUndo && this.$undoManager) { - this.$deltas.push(delta); - this.$informUndoManager.schedule(); - } - - this.modified = true; - - var firstRow = range.start.row; - var lastRow = range.end.row; - - var row = this.getLine(firstRow).substring(0, range.start.column) - + this.getLine(lastRow).substring(range.end.column); - - if (row != "") - this.$lines.splice(firstRow, lastRow - firstRow + 1, row); - else - this.$lines.splice(firstRow, lastRow - firstRow + 1, ""); - - this._dispatchEvent("changeDelta", { data: delta }); - return range.start; }; this.undoChanges = function(deltas) { this.selection.clearSelection(); + this.$fromUndo = true; for (var i=deltas.length-1; i>=0; i--) { var delta = deltas[i]; if (delta.action == "insertText") { @@ -671,10 +487,13 @@ var EditSession = function(text, mode) { this.selection.clearSelection(); } } + this.$fromUndo = false; }, this.redoChanges = function(deltas) { this.selection.clearSelection(); + + this.$fromUndo = true; for (var i=0; i= this.$lines.length-1) return 0; + if (lastRow >= this.doc.getLength()-1) return 0; - var removed = this.$lines.slice(firstRow, lastRow + 1); - this.$remove(new Range(firstRow, 0, lastRow + 1, 0)); - this.$insertLines(firstRow+1, removed); - - this.fireChangeEvent(firstRow, lastRow + 1); + var removed = this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow+1, removed); return 1; }; @@ -780,16 +569,14 @@ var EditSession = function(text, mode) { var lastRow = this.$clipRowToDocument(lastRow); var lines = this.getLines(firstRow, lastRow); - this.$insertLines(firstRow, lines); + this.doc.insertLines(firstRow, lines); var addedRows = lastRow - firstRow + 1; - this.fireChangeEvent(firstRow); - return addedRows; }; this.$clipRowToDocument = function(row) { - return Math.max(0, Math.min(row, this.$lines.length-1)); + return Math.max(0, Math.min(row, this.doc.getLength()-1)); }; this.documentToScreenColumn = function(row, docColumn) { diff --git a/lib/ace/test/edit_session_test.js b/lib/ace/test/edit_session_test.js index 1df5f511..d4a13367 100644 --- a/lib/ace/test/edit_session_test.js +++ b/lib/ace/test/edit_session_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("../document").Document, +var EditSession = require("../edit_session").EditSession, UndoManager = require("../undomanager").UndoManager, MockRenderer = require("./mockrenderer"), Range = require("../range").Range, @@ -47,242 +47,201 @@ var Document = require("../document").Document, var Test = { "test: find matching opening bracket" : function() { - var doc = new Document(["(()(", "())))"]); + var session = new EditSession(["(()(", "())))"]); - assert.position(doc.findMatchingBracket({row: 0, column: 3}), 0, 1); - assert.position(doc.findMatchingBracket({row: 1, column: 2}), 1, 0); - assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 3); - assert.position(doc.findMatchingBracket({row: 1, column: 4}), 0, 0); - assert.equal(doc.findMatchingBracket({row: 1, column: 5}), null); + assert.position(session.findMatchingBracket({row: 0, column: 3}), 0, 1); + assert.position(session.findMatchingBracket({row: 1, column: 2}), 1, 0); + assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 3); + assert.position(session.findMatchingBracket({row: 1, column: 4}), 0, 0); + assert.equal(session.findMatchingBracket({row: 1, column: 5}), null); }, "test: find matching closing bracket" : function() { - var doc = new Document(["(()(", "())))"]); + var session = new EditSession(["(()(", "())))"]); - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1); - assert.position(doc.findMatchingBracket({row: 0, column: 4}), 1, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 2}), 0, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 3); - assert.equal(doc.findMatchingBracket({row: 0, column: 0}), null); + assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1); + assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1); + assert.position(session.findMatchingBracket({row: 0, column: 4}), 1, 2); + assert.position(session.findMatchingBracket({row: 0, column: 2}), 0, 2); + assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 3); + assert.equal(session.findMatchingBracket({row: 0, column: 0}), null); }, "test: match different bracket types" : function() { - var doc = new Document(["({[", ")]}"]); + var session = new EditSession(["({[", ")]}"]); - assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 0); - assert.position(doc.findMatchingBracket({row: 0, column: 2}), 1, 2); - assert.position(doc.findMatchingBracket({row: 0, column: 3}), 1, 1); + assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 0); + assert.position(session.findMatchingBracket({row: 0, column: 2}), 1, 2); + assert.position(session.findMatchingBracket({row: 0, column: 3}), 1, 1); - assert.position(doc.findMatchingBracket({row: 1, column: 1}), 0, 0); - assert.position(doc.findMatchingBracket({row: 1, column: 2}), 0, 2); - assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 1); + assert.position(session.findMatchingBracket({row: 1, column: 1}), 0, 0); + assert.position(session.findMatchingBracket({row: 1, column: 2}), 0, 2); + assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 1); }, "test: move lines down" : function() { - var doc = new Document(["a1", "a2", "a3", "a4"]); + var session = new EditSession(["a1", "a2", "a3", "a4"]); - doc.moveLinesDown(0, 1); - assert.equal(doc.toString(), ["a3", "a1", "a2", "a4"].join("\n")); + session.moveLinesDown(0, 1); + assert.equal(session.getValue(), ["a3", "a1", "a2", "a4"].join("\n")); - doc.moveLinesDown(1, 2); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + session.moveLinesDown(1, 2); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); - doc.moveLinesDown(2, 3); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + session.moveLinesDown(2, 3); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); - doc.moveLinesDown(2, 2); - assert.equal(doc.toString(), ["a3", "a4", "a2", "a1"].join("\n")); + session.moveLinesDown(2, 2); + assert.equal(session.getValue(), ["a3", "a4", "a2", "a1"].join("\n")); }, "test: move lines up" : function() { - var doc = new Document(["a1", "a2", "a3", "a4"]); + var session = new EditSession(["a1", "a2", "a3", "a4"]); - doc.moveLinesUp(2, 3); - assert.equal(doc.toString(), ["a1", "a3", "a4", "a2"].join("\n")); + session.moveLinesUp(2, 3); + assert.equal(session.getValue(), ["a1", "a3", "a4", "a2"].join("\n")); - doc.moveLinesUp(1, 2); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + session.moveLinesUp(1, 2); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); - doc.moveLinesUp(0, 1); - assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n")); + session.moveLinesUp(0, 1); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); - doc.moveLinesUp(2, 2); - assert.equal(doc.toString(), ["a3", "a1", "a4", "a2"].join("\n")); + session.moveLinesUp(2, 2); + assert.equal(session.getValue(), ["a3", "a1", "a4", "a2"].join("\n")); }, "test: duplicate lines" : function() { - var doc = new Document(["1", "2", "3", "4"]); + var session = new EditSession(["1", "2", "3", "4"]); - doc.duplicateLines(1, 2); - assert.equal(doc.toString(), ["1", "2", "3", "2", "3", "4"].join("\n")); + session.duplicateLines(1, 2); + assert.equal(session.getValue(), ["1", "2", "3", "2", "3", "4"].join("\n")); }, "test: duplicate last line" : function() { - var doc = new Document(["1", "2", "3"]); + var session = new EditSession(["1", "2", "3"]); - doc.duplicateLines(2, 2); - assert.equal(doc.toString(), ["1", "2", "3", "3"].join("\n")); + session.duplicateLines(2, 2); + assert.equal(session.getValue(), ["1", "2", "3", "3"].join("\n")); }, "test: duplicate first line" : function() { - var doc = new Document(["1", "2", "3"]); + var session = new EditSession(["1", "2", "3"]); - doc.duplicateLines(0, 0); - assert.equal(doc.toString(), ["1", "1", "2", "3"].join("\n")); - }, - - "test: should handle unix style new lines" : function() { - var doc = new Document(["1", "2", "3"]); - - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); - }, - - "test: should handle windows style new lines" : function() { - var doc = new Document(["1", "2", "3"].join("\r\n")); - - doc.setNewLineMode("unix"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); - }, - - "test: set new line mode to 'windows' should use '\r\n' as new lines": function() { - var doc = new Document(["1", "2", "3"].join("\n")); - doc.setNewLineMode("windows"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); - }, - - "test: set new line mode to 'unix' should use '\n' as new lines": function() { - var doc = new Document(["1", "2", "3"].join("\r\n")); - - doc.setNewLineMode("unix"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); - }, - - "test: set new line mode to 'auto' should detect the incoming nl type": function() { - var doc = new Document(["1", "2", "3"].join("\n")); - - doc.setNewLineMode("auto"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\n")); - - var doc = new Document(["1", "2", "3"].join("\r\n")); - - doc.setNewLineMode("auto"); - assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n")); - - doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n")); - assert.equal(["4", "5", "6"].join("\n"), doc.toString()); + session.duplicateLines(0, 0); + assert.equal(session.getValue(), ["1", "1", "2", "3"].join("\n")); }, "test: convert document to screen coordinates" : function() { - var doc = new Document("01234\t567890\t1234"); - doc.setTabSize(4); + var session = new EditSession("01234\t567890\t1234"); + session.setTabSize(4); - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 4), 4); - assert.equal(doc.documentToScreenColumn(0, 5), 5); - assert.equal(doc.documentToScreenColumn(0, 6), 9); - assert.equal(doc.documentToScreenColumn(0, 12), 15); - assert.equal(doc.documentToScreenColumn(0, 13), 19); + assert.equal(session.documentToScreenColumn(0, 0), 0); + assert.equal(session.documentToScreenColumn(0, 4), 4); + assert.equal(session.documentToScreenColumn(0, 5), 5); + assert.equal(session.documentToScreenColumn(0, 6), 9); + assert.equal(session.documentToScreenColumn(0, 12), 15); + assert.equal(session.documentToScreenColumn(0, 13), 19); - doc.setTabSize(2); + session.setTabSize(2); - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 4), 4); - assert.equal(doc.documentToScreenColumn(0, 5), 5); - assert.equal(doc.documentToScreenColumn(0, 6), 7); - assert.equal(doc.documentToScreenColumn(0, 12), 13); - assert.equal(doc.documentToScreenColumn(0, 13), 15); + assert.equal(session.documentToScreenColumn(0, 0), 0); + assert.equal(session.documentToScreenColumn(0, 4), 4); + assert.equal(session.documentToScreenColumn(0, 5), 5); + assert.equal(session.documentToScreenColumn(0, 6), 7); + assert.equal(session.documentToScreenColumn(0, 12), 13); + assert.equal(session.documentToScreenColumn(0, 13), 15); }, "test: convert document to scrren coordinates with leading tabs": function() { - var doc = new Document("\t\t123"); - doc.setTabSize(4); + var session = new EditSession("\t\t123"); + session.setTabSize(4); - assert.equal(doc.documentToScreenColumn(0, 0), 0); - assert.equal(doc.documentToScreenColumn(0, 1), 4); - assert.equal(doc.documentToScreenColumn(0, 2), 8); - assert.equal(doc.documentToScreenColumn(0, 3), 9); + assert.equal(session.documentToScreenColumn(0, 0), 0); + assert.equal(session.documentToScreenColumn(0, 1), 4); + assert.equal(session.documentToScreenColumn(0, 2), 8); + assert.equal(session.documentToScreenColumn(0, 3), 9); }, "test: convert screen to document coordinates" : function() { - var doc = new Document("01234\t567890\t1234"); - doc.setTabSize(4); + var session = new EditSession("01234\t567890\t1234"); + session.setTabSize(4); - assert.equal(doc.screenToDocumentColumn(0, 0), 0); - assert.equal(doc.screenToDocumentColumn(0, 4), 4); - assert.equal(doc.screenToDocumentColumn(0, 5), 5); - assert.equal(doc.screenToDocumentColumn(0, 6), 5); - assert.equal(doc.screenToDocumentColumn(0, 7), 5); - assert.equal(doc.screenToDocumentColumn(0, 8), 5); - assert.equal(doc.screenToDocumentColumn(0, 9), 6); - assert.equal(doc.screenToDocumentColumn(0, 15), 12); - assert.equal(doc.screenToDocumentColumn(0, 19), 13); + assert.equal(session.screenToDocumentColumn(0, 0), 0); + assert.equal(session.screenToDocumentColumn(0, 4), 4); + assert.equal(session.screenToDocumentColumn(0, 5), 5); + assert.equal(session.screenToDocumentColumn(0, 6), 5); + assert.equal(session.screenToDocumentColumn(0, 7), 5); + assert.equal(session.screenToDocumentColumn(0, 8), 5); + assert.equal(session.screenToDocumentColumn(0, 9), 6); + assert.equal(session.screenToDocumentColumn(0, 15), 12); + assert.equal(session.screenToDocumentColumn(0, 19), 13); }, "test: insert text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); - var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); + var inserted = session.multiRowInsert([0, 1, 2], 2, "juhu 1"); assert.equal(inserted.rows, 0); assert.equal(inserted.columns, 6); - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + assert.equal(session.getValue(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); }, "test: undo insert text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); var undoManager = new UndoManager(); - doc.setUndoManager(undoManager); + session.setUndoManager(undoManager); - doc.multiRowInsert([0, 1, 2], 2, "juhu 1"); - doc.$informUndoManager.call(); - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + session.multiRowInsert([0, 1, 2], 2, "juhu 1"); + session.$informUndoManager.call(); + assert.equal(session.getValue(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); undoManager.undo(); - assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); + assert.equal(session.getValue(), ["12", "", "abcd"].join("\n")); undoManager.redo(); - assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + assert.equal(session.getValue(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); }, "test: insert new line in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); - var inserted = doc.multiRowInsert([0, 1, 2], 2, "\n"); + var inserted = session.multiRowInsert([0, 1, 2], 2, "\n"); assert.equal(inserted.rows, 1); - assert.equal(doc.toString(), ["12\n", " \n", "ab\ncd"].join("\n")); + assert.equal(session.getValue(), ["12\n", " \n", "ab\ncd"].join("\n")); }, "test: insert multi line text in multiple rows": function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); - var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu\n12"); + var inserted = session.multiRowInsert([0, 1, 2], 2, "juhu\n12"); assert.equal(inserted.rows, 1); - assert.equal(doc.toString(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n")); + assert.equal(session.getValue(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n")); }, "test: remove right in multiple rows" : function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); - doc.multiRowRemove([0, 1, 2], new Range(0, 2, 0, 3)); - assert.equal(doc.toString(), ["12", "", "abd"].join("\n")); + session.multiRowRemove([0, 1, 2], new Range(0, 2, 0, 3)); + assert.equal(session.getValue(), ["12", "", "abd"].join("\n")); }, "test: undo remove right in multiple rows" : function() { - var doc = new Document(["12", "", "abcd"]); + var session = new EditSession(["12", "", "abcd"]); var undoManager = new UndoManager(); - doc.setUndoManager(undoManager); + session.setUndoManager(undoManager); - doc.multiRowRemove([0, 1, 2], new Range(0, 1, 0, 3)); - doc.$informUndoManager.call(); - assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); + session.multiRowRemove([0, 1, 2], new Range(0, 1, 0, 3)); + session.$informUndoManager.call(); + assert.equal(session.getValue(), ["1", "", "ad"].join("\n")); undoManager.undo(); - assert.equal(doc.toString(), ["12", "", "abcd"].join("\n")); + assert.equal(session.getValue(), ["12", "", "abcd"].join("\n")); undoManager.redo(); - assert.equal(doc.toString(), ["1", "", "ad"].join("\n")); + assert.equal(session.getValue(), ["1", "", "ad"].join("\n")); } }; From c7daceb51a7f55d8db0fc3abb98fefce136bb8f5 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 08:15:13 +0100 Subject: [PATCH 07/36] remove dead code --- lib/ace/undomanager.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index 33c76526..15b22e06 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -44,11 +44,6 @@ var UndoManager = function() { (function() { - /*this.$doc = null; - this.setDocument = function(doc) { - this.$doc = doc; - };*/ - this.execute = function(options) { var deltas = options.args[0]; this.$doc = options.args[1]; From 0fe4de2b62faa078cba16285ca19af7df043464b Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 08:41:04 +0100 Subject: [PATCH 08/36] all tests are green again --- lib/ace/document.js | 3 +- lib/ace/editor.js | 4 +- lib/ace/search.js | 40 ++--- lib/ace/test/all.js | 1 + lib/ace/test/change_document_test.js | 10 +- lib/ace/test/edit_session_test.js | 6 +- lib/ace/test/mode/css_test.js | 8 +- lib/ace/test/mode/html_test.js | 8 +- lib/ace/test/mode/javascript_test.js | 46 +++--- lib/ace/test/mode/text_test.js | 8 +- lib/ace/test/mode/xml_test.js | 8 +- lib/ace/test/navigation_test.js | 18 +-- lib/ace/test/search_test.js | 112 +++++++------- lib/ace/test/selection_test.js | 66 ++++---- lib/ace/test/text_edit_test.js | 222 +++++++++++++-------------- 15 files changed, 281 insertions(+), 279 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index db6e4d54..492c8050 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -257,7 +257,7 @@ var Document = function(text) { range.end = this.$clipPosition(range.end); if (range.isEmpty()) - return; + return range.start; var firstRow = range.start.row; var lastRow = range.end.row; @@ -274,6 +274,7 @@ var Document = function(text) { else { this.removeInLine(firstRow, range.start.column, range.end.column); } + return range.start; }; this.removeInLine = function(row, startColumn, endColumn) { diff --git a/lib/ace/editor.js b/lib/ace/editor.js index e6576dbf..927711ce 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -42,7 +42,7 @@ var event = require("pilot/event"); var lang = require("pilot/lang"); var TextInput = require("ace/keyboard/textinput").TextInput; var KeyBinding = require("ace/keyboard/keybinding").KeyBinding; -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var Search = require("ace/search").Search; var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenizer; var Range = require("ace/range").Range; @@ -78,7 +78,7 @@ var Editor =function(renderer, doc) { wrap: true }); - this.setDocument(doc || new Document("")); + this.setDocument(doc || new EditSession("")); this.focus(); }; diff --git a/lib/ace/search.js b/lib/ace/search.js index d800df76..aed0a8c5 100644 --- a/lib/ace/search.js +++ b/lib/ace/search.js @@ -67,14 +67,14 @@ Search.SELECTION = 2; return lang.copyObject(this.$options); }; - this.find = function(doc) { + this.find = function(session) { if (!this.$options.needle) return null; if (this.$options.backwards) { - var iterator = this.$backwardMatchIterator(doc); + var iterator = this.$backwardMatchIterator(session); } else { - iterator = this.$forwardMatchIterator(doc); + iterator = this.$forwardMatchIterator(session); } var firstRange = null; @@ -86,14 +86,14 @@ Search.SELECTION = 2; return firstRange; }; - this.findAll = function(doc) { + this.findAll = function(session) { if (!this.$options.needle) return []; if (this.$options.backwards) { - var iterator = this.$backwardMatchIterator(doc); + var iterator = this.$backwardMatchIterator(session); } else { - iterator = this.$forwardMatchIterator(doc); + iterator = this.$forwardMatchIterator(session); } var ranges = []; @@ -118,13 +118,13 @@ Search.SELECTION = 2; } }; - this.$forwardMatchIterator = function(doc) { + this.$forwardMatchIterator = function(session) { var re = this.$assembleRegExp(); var self = this; return { forEach: function(callback) { - self.$forwardLineIterator(doc).forEach(function(line, startIndex, row) { + self.$forwardLineIterator(session).forEach(function(line, startIndex, row) { if (startIndex) { line = line.substring(startIndex); } @@ -152,13 +152,13 @@ Search.SELECTION = 2; }; }; - this.$backwardMatchIterator = function(doc) { + this.$backwardMatchIterator = function(session) { var re = this.$assembleRegExp(); var self = this; return { forEach: function(callback) { - self.$backwardLineIterator(doc).forEach(function(line, startIndex, row) { + self.$backwardLineIterator(session).forEach(function(line, startIndex, row) { if (startIndex) { line = line.substring(startIndex); } @@ -208,20 +208,20 @@ Search.SELECTION = 2; return re; }; - this.$forwardLineIterator = function(doc) { + this.$forwardLineIterator = function(session) { var searchSelection = this.$options.scope == Search.SELECTION; - var range = doc.getSelection().getRange(); - var start = doc.getSelection().getCursor(); + var range = session.getSelection().getRange(); + var start = session.getSelection().getCursor(); var firstRow = searchSelection ? range.start.row : 0; var firstColumn = searchSelection ? range.start.column : 0; - var lastRow = searchSelection ? range.end.row : doc.getLength() - 1; + var lastRow = searchSelection ? range.end.row : session.getLength() - 1; var wrap = this.$options.wrap; function getLine(row) { - var line = doc.getLine(row); + var line = session.getLine(row); if (searchSelection && row == range.end.row) { line = line.substring(0, range.end.column); } @@ -264,15 +264,15 @@ Search.SELECTION = 2; }; }; - this.$backwardLineIterator = function(doc) { + this.$backwardLineIterator = function(session) { var searchSelection = this.$options.scope == Search.SELECTION; - var range = doc.getSelection().getRange(); + var range = session.getSelection().getRange(); var start = searchSelection ? range.end : range.start; var firstRow = searchSelection ? range.start.row : 0; var firstColumn = searchSelection ? range.start.column : 0; - var lastRow = searchSelection ? range.end.row : doc.getLength() - 1; + var lastRow = searchSelection ? range.end.row : session.getLength() - 1; var wrap = this.$options.wrap; @@ -280,7 +280,7 @@ Search.SELECTION = 2; forEach : function(callback) { var row = start.row; - var line = doc.getLine(row).substring(0, start.column); + var line = session.getLine(row).substring(0, start.column); var startIndex = 0; var stop = false; @@ -303,7 +303,7 @@ Search.SELECTION = 2; if (row == start.row) stop = true; - line = doc.getLine(row); + line = session.getLine(row); if (searchSelection) { if (row == firstRow) startIndex = firstColumn; diff --git a/lib/ace/test/all.js b/lib/ace/test/all.js index 449e6c17..5e4dc4e0 100644 --- a/lib/ace/test/all.js +++ b/lib/ace/test/all.js @@ -42,6 +42,7 @@ var async = require("async"); async.concat( require("./change_document_test"), require("./document_test"), + require("./edit_session_test"), require("./event_emitter_test"), require("./navigation_test"), require("./range_test"), diff --git a/lib/ace/test/change_document_test.js b/lib/ace/test/change_document_test.js index 5291eff9..77375781 100644 --- a/lib/ace/test/change_document_test.js +++ b/lib/ace/test/change_document_test.js @@ -39,7 +39,7 @@ define(function(require, exports, module) { require("./mockdom"); -var Document = require("../document").Document, +var EditSession = require("../edit_session").EditSession, Editor = require("../editor").Editor, Text = require("../mode/text").Mode, JavaScriptMode = require("../mode/javascript").Mode, @@ -47,10 +47,12 @@ var Document = require("../document").Document, assert = require("./assertions"); var Test = { - setUp : function() { - this.doc1 = new Document(["abc", "def"].join("\n")); - this.doc2 = new Document(["ghi", "jkl"].join("\n")); + + setUp : function(next) { + this.doc1 = new EditSession(["abc", "def"]); + this.doc2 = new EditSession(["ghi", "jkl"]); this.editor = new Editor(new MockRenderer()); + next(); }, "test: change document" : function() { diff --git a/lib/ace/test/edit_session_test.js b/lib/ace/test/edit_session_test.js index d4a13367..4298df3a 100644 --- a/lib/ace/test/edit_session_test.js +++ b/lib/ace/test/edit_session_test.js @@ -37,10 +37,10 @@ define(function(require, exports, module) { -var EditSession = require("../edit_session").EditSession, - UndoManager = require("../undomanager").UndoManager, +var EditSession = require("ace/edit_session").EditSession, + UndoManager = require("ace/undomanager").UndoManager, MockRenderer = require("./mockrenderer"), - Range = require("../range").Range, + Range = require("ace/range").Range, assert = require("./assertions"), async = require("async"); diff --git a/lib/ace/test/mode/css_test.js b/lib/ace/test/mode/css_test.js index 77573871..3b2932c0 100644 --- a/lib/ace/test/mode/css_test.js +++ b/lib/ace/test/mode/css_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var CssMode = require("ace/mode/css").Mode; var assert = require("../assertions"); @@ -47,10 +47,10 @@ var Test = { }, "test: toggle comment lines should not do anything" : function() { - var doc = new Document([" abc", "cde", "fg"].join("\n")); + var session = new EditSession([" abc", "cde", "fg"].join("\n")); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, diff --git a/lib/ace/test/mode/html_test.js b/lib/ace/test/mode/html_test.js index a9c7e4fd..d9cf64e4 100644 --- a/lib/ace/test/mode/html_test.js +++ b/lib/ace/test/mode/html_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var Range = require("ace/range").Range; var HtmlMode = require("ace/mode/html").Mode; var assert = require("../assertions"); @@ -48,11 +48,11 @@ var Test = { }, "test: toggle comment lines should not do anything" : function() { - var doc = new Document([" abc", "cde", "fg"]); + var session = new EditSession([" abc", "cde", "fg"]); var range = new Range(0, 3, 1, 1); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, "test: next line indent should be the same as the current line indent" : function() { diff --git a/lib/ace/test/mode/javascript_test.js b/lib/ace/test/mode/javascript_test.js index 0acf55b1..9fcb9c09 100644 --- a/lib/ace/test/mode/javascript_test.js +++ b/lib/ace/test/mode/javascript_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var Tokenizer = require("ace/tokenizer").Tokenizer; var JavaScriptMode = require("ace/mode/javascript").Mode; var assert = require("../assertions"); @@ -57,39 +57,39 @@ var Test = { }, "test: toggle comment lines should prepend '//' to each line" : function() { - var doc = new Document([" abc", "cde", "fg"]); + var session = new EditSession([" abc", "cde", "fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal(["// abc", "//cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal(["// abc", "//cde", "fg"].join("\n"), session.toString()); }, "test: toggle comment on commented lines should remove leading '//' chars" : function() { - var doc = new Document(["// abc", "//cde", "fg"]); + var session = new EditSession(["// abc", "//cde", "fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, "test: toggle comment lines twice should return the original text" : function() { - var doc = new Document([" abc", "cde", "fg"]); + var session = new EditSession([" abc", "cde", "fg"]); - this.mode.toggleCommentLines("start", doc, 0, 2); - this.mode.toggleCommentLines("start", doc, 0, 2); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + this.mode.toggleCommentLines("start", session, 0, 2); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, "test: toggle comment on multiple lines with one commented line prepend '//' to each line" : function() { - var doc = new Document(["// abc", "//cde", "fg"]); + var session = new EditSession(["// abc", "//cde", "fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 2); - assert.equal(["//// abc", "////cde", "//fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal(["//// abc", "////cde", "//fg"].join("\n"), session.toString()); }, "test: toggle comment on a comment line with leading white space": function() { - var doc = new Document(["//cde", " //fg"]); + var session = new EditSession(["//cde", " //fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal(["cde", " fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal(["cde", " fg"].join("\n"), session.toString()); }, "test: auto indent after opening brace" : function() { @@ -132,15 +132,15 @@ var Test = { }, "test: auto outdent should indent the line with the same indent as the line with the matching opening brace" : function() { - var doc = new Document([" function foo() {", " bla", " }"]); - this.mode.autoOutdent("start", doc, 2); - assert.equal(" }", doc.getLine(2)); + var session = new EditSession([" function foo() {", " bla", " }"]); + this.mode.autoOutdent("start", session, 2); + assert.equal(" }", session.getLine(2)); }, "test: no auto outdent if no matching brace is found" : function() { - var doc = new Document([" function foo()", " bla", " }"]); - this.mode.autoOutdent("start", doc, 2); - assert.equal(" }", doc.getLine(2)); + var session = new EditSession([" function foo()", " bla", " }"]); + this.mode.autoOutdent("start", session, 2); + assert.equal(" }", session.getLine(2)); } }; diff --git a/lib/ace/test/mode/text_test.js b/lib/ace/test/mode/text_test.js index 06c93f7b..a39f7d5b 100644 --- a/lib/ace/test/mode/text_test.js +++ b/lib/ace/test/mode/text_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var TextMode = require("ace/mode/text").Mode; var assert = require("../assertions"); @@ -47,10 +47,10 @@ var Test = { }, "test: toggle comment lines should not do anything" : function() { - var doc = new Document([" abc", "cde", "fg"]); + var session = new EditSession([" abc", "cde", "fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, diff --git a/lib/ace/test/mode/xml_test.js b/lib/ace/test/mode/xml_test.js index 01f86760..e2375afb 100644 --- a/lib/ace/test/mode/xml_test.js +++ b/lib/ace/test/mode/xml_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("ace/document").Document; +var EditSession = require("ace/edit_session").EditSession; var Tokenizer = require("ace/tokenizer").Tokenizer; var XmlMode = require("ace/mode/xml").Mode; var assert = require("../assertions"); @@ -57,10 +57,10 @@ var Test = { }, "test: toggle comment lines should not do anything" : function() { - var doc = new Document([" abc", "cde", "fg"]); + var session = new EditSession([" abc", "cde", "fg"]); - var comment = this.mode.toggleCommentLines("start", doc, 0, 1); - assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString()); + var comment = this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); }, "test: next line indent should be the same as the current line indent" : function() { diff --git a/lib/ace/test/navigation_test.js b/lib/ace/test/navigation_test.js index 30a1c144..44938b6f 100644 --- a/lib/ace/test/navigation_test.js +++ b/lib/ace/test/navigation_test.js @@ -39,20 +39,20 @@ define(function(require, exports, module) { require("./mockdom"); -var Document = require("../Document").Document, +var EditSession = require("ace/edit_session").EditSession, Editor = require("../Editor").Editor, MockRenderer = require("./mockrenderer"), assert = require("./assertions"); var Test = { - createTextDocument : function(rows, cols) { + createEditSession : function(rows, cols) { var line = new Array(cols + 1).join("a"); var text = new Array(rows).join(line + "\n") + line; - return new Document(text); + return new EditSession(text); }, "test: navigate to end of file should scroll the last line into view" : function() { - var doc = this.createTextDocument(200, 10); + var doc = this.createEditSession(200, 10); var editor = new Editor(new MockRenderer(), doc); editor.navigateFileEnd(); @@ -63,7 +63,7 @@ var Test = { }, "test: navigate to start of file should scroll the first row into view" : function() { - var doc = this.createTextDocument(200, 10); + var doc = this.createEditSession(200, 10); var editor = new Editor(new MockRenderer(), doc); editor.moveCursorTo(editor.getLastVisibleRow() + 20); @@ -73,7 +73,7 @@ var Test = { }, "test: goto hidden line should scroll the line into the middle of the viewport" : function() { - var editor = new Editor(new MockRenderer(), this.createTextDocument(200, 5)); + var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5)); editor.navigateTo(0, 0); editor.gotoLine(101); @@ -107,7 +107,7 @@ var Test = { }, "test: goto visible line should only move the cursor and not scroll": function() { - var editor = new Editor(new MockRenderer(), this.createTextDocument(200, 5)); + var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5)); editor.navigateTo(0, 0); editor.gotoLine(12); @@ -121,7 +121,7 @@ var Test = { }, "test: navigate from the end of a long line down to a short line and back should maintain the curser column": function() { - var editor = new Editor(new MockRenderer(), new Document(["123456", "1"])); + var editor = new Editor(new MockRenderer(), new EditSession(["123456", "1"])); editor.navigateTo(0, 6); assert.position(editor.getCursorPosition(), 0, 6); @@ -134,7 +134,7 @@ var Test = { }, "test: reset desired column on navigate left or right": function() { - var editor = new Editor(new MockRenderer(), new Document(["123456", "12"])); + var editor = new Editor(new MockRenderer(), new EditSession(["123456", "12"])); editor.navigateTo(0, 6); assert.position(editor.getCursorPosition(), 0, 6); diff --git a/lib/ace/test/search_test.js b/lib/ace/test/search_test.js index 00f35b2b..b33a0d0f 100644 --- a/lib/ace/test/search_test.js +++ b/lib/ace/test/search_test.js @@ -37,7 +37,7 @@ define(function(require, exports, module) { -var Document = require("../document").Document, +var EditSession = require("ace/edit_session").EditSession, Search = require("../search").Search, assert = require("./assertions"); @@ -51,128 +51,128 @@ var Test = { }, "test: find simple text in document" : function() { - var doc = new Document(["juhu kinners 123", "456"]); + var session = new EditSession(["juhu kinners 123", "456"]); var search = new Search().set({ needle: "kinners" }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 0, 5); assert.position(range.end, 0, 12); }, "test: find simple text in next line" : function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); var search = new Search().set({ needle: "kinners" }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 5); assert.position(range.end, 1, 12); }, "test: find text starting at cursor position" : function() { - var doc = new Document(["juhu kinners", "juhu kinners 123"]); - doc.getSelection().moveCursorTo(0, 6); + var session = new EditSession(["juhu kinners", "juhu kinners 123"]); + session.getSelection().moveCursorTo(0, 6); var search = new Search().set({ needle: "kinners" }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 5); assert.position(range.end, 1, 12); }, "test: wrap search is off by default" : function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); - doc.getSelection().moveCursorTo(2, 1); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); + session.getSelection().moveCursorTo(2, 1); var search = new Search().set({ needle: "kinners" }); - assert.equal(search.find(doc), null); + assert.equal(search.find(session), null); }, "test: wrap search should wrap at file end" : function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); - doc.getSelection().moveCursorTo(2, 1); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); + session.getSelection().moveCursorTo(2, 1); var search = new Search().set({ needle: "kinners", wrap: true }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 5); assert.position(range.end, 1, 12); }, "test: wrap search with no match should return 'null'": function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); - doc.getSelection().moveCursorTo(2, 1); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); + session.getSelection().moveCursorTo(2, 1); var search = new Search().set({ needle: "xyz", wrap: true }); - assert.equal(search.find(doc), null); + assert.equal(search.find(session), null); }, "test: case sensitive is by default off": function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); var search = new Search().set({ needle: "JUHU" }); - assert.range(search.find(doc), 1, 0, 1, 4); + assert.range(search.find(session), 1, 0, 1, 4); }, "test: case sensitive search": function() { - var doc = new Document(["abc", "juhu kinners 123", "456"]); + var session = new EditSession(["abc", "juhu kinners 123", "456"]); var search = new Search().set({ needle: "KINNERS", caseSensitive: true }); - var range = search.find(doc); + var range = search.find(session); assert.equal(range, null); }, "test: whole word search should not match inside of words": function() { - var doc = new Document(["juhukinners", "juhu kinners 123", "456"]); + var session = new EditSession(["juhukinners", "juhu kinners 123", "456"]); var search = new Search().set({ needle: "kinners", wholeWord: true }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 5); assert.position(range.end, 1, 12); }, "test: find backwards": function() { - var doc = new Document(["juhu juhu juhu juhu"]); - doc.getSelection().moveCursorTo(0, 10); + var session = new EditSession(["juhu juhu juhu juhu"]); + session.getSelection().moveCursorTo(0, 10); var search = new Search().set({ needle: "juhu", backwards: true }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 0, 5); assert.position(range.end, 0, 9); }, "test: find in selection": function() { - var doc = new Document(["juhu", "juhu", "juhu", "juhu"]); - doc.getSelection().setSelectionAnchor(1, 0); - doc.getSelection().selectTo(3, 5); + var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]); + session.getSelection().setSelectionAnchor(1, 0); + session.getSelection().selectTo(3, 5); var search = new Search().set({ needle: "juhu", @@ -180,20 +180,20 @@ var Test = { scope: Search.SELECTION }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 0); assert.position(range.end, 1, 4); - doc.getSelection().setSelectionAnchor(0, 2); - doc.getSelection().selectTo(3, 2); + session.getSelection().setSelectionAnchor(0, 2); + session.getSelection().selectTo(3, 2); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 1, 0); assert.position(range.end, 1, 4); }, "test: find backwards in selection": function() { - var doc = new Document(["juhu", "juhu", "juhu", "juhu"]); + var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]); var search = new Search().set({ needle: "juhu", @@ -202,36 +202,36 @@ var Test = { scope: Search.SELECTION }); - doc.getSelection().setSelectionAnchor(0, 2); - doc.getSelection().selectTo(3, 2); + session.getSelection().setSelectionAnchor(0, 2); + session.getSelection().selectTo(3, 2); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 2, 0); assert.position(range.end, 2, 4); - doc.getSelection().setSelectionAnchor(0, 2); - doc.getSelection().selectTo(1, 2); + session.getSelection().setSelectionAnchor(0, 2); + session.getSelection().selectTo(1, 2); - assert.equal(search.find(doc), null); + assert.equal(search.find(session), null); }, "test: edge case - match directly before the cursor" : function() { - var doc = new Document(["123", "123", "juhu"]); + var session = new EditSession(["123", "123", "juhu"]); var search = new Search().set({ needle: "juhu", wrap: true }); - doc.getSelection().moveCursorTo(2, 5); + session.getSelection().moveCursorTo(2, 5); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 2, 0); assert.position(range.end, 2, 4); }, "test: edge case - match backwards directly after the cursor" : function() { - var doc = new Document(["123", "123", "juhu"]); + var session = new EditSession(["123", "123", "juhu"]); var search = new Search().set({ needle: "juhu", @@ -239,28 +239,28 @@ var Test = { backwards: true }); - doc.getSelection().moveCursorTo(2, 0); + session.getSelection().moveCursorTo(2, 0); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 2, 0); assert.position(range.end, 2, 4); }, "test: find using a regular expression" : function() { - var doc = new Document(["abc123 123 cd", "abc"]); + var session = new EditSession(["abc123 123 cd", "abc"]); var search = new Search().set({ needle: "\\d+", regExp: true }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 0, 3); assert.position(range.end, 0, 6); }, "test: find using a regular expression and whole word" : function() { - var doc = new Document(["abc123 123 cd", "abc"]); + var session = new EditSession(["abc123 123 cd", "abc"]); var search = new Search().set({ needle: "\\d+\\b", @@ -268,26 +268,26 @@ var Test = { wholeWord: true }); - var range = search.find(doc); + var range = search.find(session); assert.position(range.start, 0, 7); assert.position(range.end, 0, 10); }, "test: use regular expressions with capture groups": function() { - var doc = new Document([" ab: 12px", "

Date: Wed, 19 Jan 2011 08:53:47 +0100 Subject: [PATCH 09/36] fix demo --- demo/startup.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/demo/startup.js b/demo/startup.js index b2e473a8..e3a9e1a3 100644 --- a/demo/startup.js +++ b/demo/startup.js @@ -44,8 +44,8 @@ exports.launch = function(env) { var event = require("pilot/event"); var Editor = require("ace/editor").Editor; var Renderer = require("ace/virtual_renderer").VirtualRenderer; - var theme = require("ace/theme/textmate"); - var Document = require("ace/document").Document; + var theme = require("ace/theme/textmate"); + var EditSession = require("ace/edit_session").EditSession; var JavaScriptMode = require("ace/mode/javascript").Mode; var CssMode = require("ace/mode/css").Mode; var HtmlMode = require("ace/mode/html").Mode; @@ -61,23 +61,23 @@ exports.launch = function(env) { var docs = {}; - docs.js = new Document(document.getElementById("jstext").innerHTML); + docs.js = new EditSession(document.getElementById("jstext").innerHTML); docs.js.setMode(new JavaScriptMode()); docs.js.setUndoManager(new UndoManager()); - docs.css = new Document(document.getElementById("csstext").innerHTML); + docs.css = new EditSession(document.getElementById("csstext").innerHTML); docs.css.setMode(new CssMode()); docs.css.setUndoManager(new UndoManager()); - docs.html = new Document(document.getElementById("htmltext").innerHTML); + docs.html = new EditSession(document.getElementById("htmltext").innerHTML); docs.html.setMode(new HtmlMode()); docs.html.setUndoManager(new UndoManager()); - docs.python = new Document(document.getElementById("pythontext").innerHTML); + docs.python = new EditSession(document.getElementById("pythontext").innerHTML); docs.python.setMode(new PythonMode()); docs.python.setUndoManager(new UndoManager()); - docs.php = new Document(document.getElementById("phptext").innerHTML); + docs.php = new EditSession(document.getElementById("phptext").innerHTML); docs.php.setMode(new PhpMode()); docs.php.setUndoManager(new UndoManager()); From a08f880b3c9b55aa69298cb7d15a7d1400fb9e4f Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 08:54:08 +0100 Subject: [PATCH 10/36] fix longest line computation --- lib/ace/edit_session.js | 6 +++--- lib/ace/test/edit_session_test.js | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 36de153c..c022dd04 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -48,7 +48,7 @@ var Document = require("ace/document").Document; var NO_CHANGE_DELTAS = {}; var EditSession = function(text, mode) { - this.modified = true; + this.$modified = true; this.selection = new Selection(this); this.$breakpoints = []; @@ -294,7 +294,7 @@ var EditSession = function(text, mode) { var len = lines[i].length; longestLine = Math.max(longestLine, len); - lines[i].replace("\t", function(m) { + lines[i].replace(/\t/g, function(m) { len += tabSize-1; return m; }); @@ -512,7 +512,7 @@ var EditSession = function(text, mode) { }; this.indentRows = function(startRow, endRow, indentString) { - indentString = indentString.replace("\t", this.getTabString()); + indentString = indentString.replace(/\t/g, this.getTabString()); for (var row=startRow; row<=endRow; row++) { this.insert({row: row, column:0}, indentString); } diff --git a/lib/ace/test/edit_session_test.js b/lib/ace/test/edit_session_test.js index 4298df3a..c5f76b9b 100644 --- a/lib/ace/test/edit_session_test.js +++ b/lib/ace/test/edit_session_test.js @@ -242,6 +242,27 @@ var Test = { undoManager.redo(); assert.equal(session.getValue(), ["1", "", "ad"].join("\n")); + }, + + "test get longest line" : function() { + var session = new EditSession(["12"]); + session.setTabSize(4); + assert.equal(session.getWidth(), 2); + assert.equal(session.getScreenWidth(), 2); + + session.doc.insertNewLine(0); + session.doc.insertLines(1, ["123"]); + assert.equal(session.getWidth(), 3); + assert.equal(session.getScreenWidth(), 3); + + session.doc.insertNewLine(0); + session.doc.insertLines(1, ["\t\t"]); + assert.equal(session.getWidth(), 3); + assert.equal(session.getScreenWidth(), 8); + + session.setTabSize(2); + assert.equal(session.getWidth(), 3); + assert.equal(session.getScreenWidth(), 4); } }; From d436d71c20c3ea1acf21aef6b85587fa28a0cc9f Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 09:10:05 +0100 Subject: [PATCH 11/36] rename document to session --- build_support/boot.js | 6 +- demo/startup.js | 6 +- lib/ace/edit_session.js | 4 + lib/ace/editor.js | 144 +++++++++++++------------- lib/ace/layer/cursor.js | 6 +- lib/ace/layer/marker.js | 12 +-- lib/ace/layer/text.js | 8 +- lib/ace/test/change_document_test.js | 60 +++++------ lib/ace/test/mockrenderer.js | 10 +- lib/ace/test/virtual_renderer_test.js | 4 +- lib/ace/virtual_renderer.js | 26 ++--- 11 files changed, 147 insertions(+), 139 deletions(-) diff --git a/build_support/boot.js b/build_support/boot.js index e311cebc..f61e91d6 100644 --- a/build_support/boot.js +++ b/build_support/boot.js @@ -51,20 +51,20 @@ var ace = { var env = require("pilot/environment").create(); var catalog = require("pilot/plugin_manager").catalog; catalog.startupPlugins({ env: env }).then(function() { - var Document = require("ace/document").Document; + var EditSession = require("ace/edit_session").EditSession; var JavaScriptMode = require("ace/mode/javascript").Mode; var UndoManager = require("ace/undomanager").UndoManager; var Editor = require("ace/editor").Editor; var Renderer = require("ace/virtual_renderer").VirtualRenderer; var theme = require("ace/theme/textmate"); - var doc = new Document(el.innerHTML); + var doc = new EditSession(el.innerHTML); el.innerHTML = ''; doc.setMode(new JavaScriptMode()); doc.setUndoManager(new UndoManager()); env.document = doc; env.editor = new Editor(new Renderer(el, theme)); - env.editor.setDocument(doc); + env.editor.setSession(doc); env.editor.resize(); window.addEventListener("resize", function() { env.editor.resize(); diff --git a/demo/startup.js b/demo/startup.js index e3a9e1a3..b62e79e3 100644 --- a/demo/startup.js +++ b/demo/startup.js @@ -102,7 +102,7 @@ exports.launch = function(env) { var modeEl = document.getElementById("mode"); function setMode() { - env.editor.getDocument().setMode(modes[modeEl.value] || modes.text); + env.editor.getSession().setMode(modes[modeEl.value] || modes.text); } modeEl.onchange = setMode; setMode(); @@ -120,7 +120,7 @@ exports.launch = function(env) { var docEl = document.getElementById("doc"); function onDocChange() { var doc = docs[docEl.value]; - env.editor.setDocument(doc); + env.editor.setSession(doc); var mode = doc.getMode(); if (mode instanceof JavaScriptMode) { @@ -240,7 +240,7 @@ exports.launch = function(env) { env.editor.onTextInput(reader.result); modeEl.value = mode; - env.editor.getDocument().setMode(modes[mode]); + env.editor.getSession().setMode(modes[mode]); }; reader.readAsText(file); } diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index c022dd04..ce959e57 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -77,6 +77,10 @@ var EditSession = function(text, mode) { doc.on("change", this.onChange.bind(this)); }; + this.getDocument = function() { + return this.doc; + }; + this.onChange = function(e) { var delta = e.data; this.$modified = true; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 927711ce..4055d2b2 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -48,7 +48,7 @@ var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenize var Range = require("ace/range").Range; var EventEmitter = require("pilot/event_emitter").EventEmitter; -var Editor =function(renderer, doc) { +var Editor =function(renderer, session) { var container = renderer.getContainerElement(); this.container = container; this.renderer = renderer; @@ -78,7 +78,7 @@ var Editor =function(renderer, doc) { wrap: true }); - this.setDocument(doc || new EditSession("")); + this.setSession(session || new EditSession("")); this.focus(); }; @@ -118,38 +118,38 @@ var Editor =function(renderer, doc) { return this.keyBinding.getKeyboardHandler(); } - this.setDocument = function(doc) { - if (this.doc == doc) return; + this.setSession = function(session) { + if (this.session == session) return; - if (this.doc) { - this.doc.removeEventListener("change", this.$onDocumentChange); - this.doc.removeEventListener("changeMode", this.$onDocumentModeChange); - this.doc.removeEventListener("changeTabSize", this.$onDocumentChangeTabSize); - this.doc.removeEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint); + if (this.session) { + this.session.removeEventListener("change", this.$onDocumentChange); + this.session.removeEventListener("changeMode", this.$onDocumentModeChange); + this.session.removeEventListener("changeTabSize", this.$onDocumentChangeTabSize); + this.session.removeEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint); - var selection = this.doc.getSelection(); + var selection = this.session.getSelection(); selection.removeEventListener("changeCursor", this.$onCursorChange); selection.removeEventListener("changeSelection", this.$onSelectionChange); - this.doc.setScrollTopRow(this.renderer.getScrollTopRow()); + this.session.setScrollTopRow(this.renderer.getScrollTopRow()); } - this.doc = doc; + this.session = session; this.$onDocumentChange = this.onDocumentChange.bind(this); - doc.addEventListener("change", this.$onDocumentChange); - this.renderer.setDocument(doc); + session.addEventListener("change", this.$onDocumentChange); + this.renderer.setSession(session); this.$onDocumentModeChange = this.onDocumentModeChange.bind(this); - doc.addEventListener("changeMode", this.$onDocumentModeChange); + session.addEventListener("changeMode", this.$onDocumentModeChange); this.$onDocumentChangeTabSize = this.renderer.updateText.bind(this.renderer); - doc.addEventListener("changeTabSize", this.$onDocumentChangeTabSize); + session.addEventListener("changeTabSize", this.$onDocumentChangeTabSize); this.$onDocumentChangeBreakpoint = this.onDocumentChangeBreakpoint.bind(this); - this.doc.addEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint); + this.session.addEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint); - this.selection = doc.getSelection(); + this.selection = session.getSelection(); this.$desiredColumn = 0; this.$onCursorChange = this.onCursorChange.bind(this); @@ -159,18 +159,18 @@ var Editor =function(renderer, doc) { this.selection.addEventListener("changeSelection", this.$onSelectionChange); this.onDocumentModeChange(); - this.bgTokenizer.setDocument(doc); + this.bgTokenizer.setDocument(session.getDocument()); this.bgTokenizer.start(0); this.onCursorChange(); this.onSelectionChange(); this.onDocumentChangeBreakpoint(); - this.renderer.scrollToRow(doc.getScrollTopRow()); + this.renderer.scrollToRow(session.getScrollTopRow()); this.renderer.updateFull(); }; - this.getDocument = function() { - return this.doc; + this.getSession = function() { + return this.session; }; this.getSelection = function() { @@ -201,7 +201,7 @@ var Editor =function(renderer, doc) { setTimeout(function() { self.$highlightPending = false; - var pos = self.doc.findMatchingBracket(self.getCursorPosition()); + var pos = self.session.findMatchingBracket(self.getCursorPosition()); if (pos) { var range = new Range(pos.row, pos.column, pos.row, pos.column+1); self.$bracketHighlight = self.renderer.addMarker(range, "ace_bracket"); @@ -280,11 +280,11 @@ var Editor =function(renderer, doc) { }; this.onDocumentChangeBreakpoint = function() { - this.renderer.setBreakpoints(this.doc.getBreakpoints()); + this.renderer.setBreakpoints(this.session.getBreakpoints()); }; this.onDocumentModeChange = function() { - var mode = this.doc.getMode(); + var mode = this.session.getMode(); if (this.mode == mode) return; @@ -308,7 +308,7 @@ var Editor =function(renderer, doc) { var pageY = event.getDocumentY(e); var pos = this.renderer.screenToTextCoordinates(pageX, pageY); - pos.row = Math.max(0, Math.min(pos.row, this.doc.getLength()-1)); + pos.row = Math.max(0, Math.min(pos.row, this.session.getLength()-1)); if (event.getButton(e) != 0) { if (this.selection.isEmpty()) { @@ -345,7 +345,7 @@ var Editor =function(renderer, doc) { return; var cursor = self.renderer.screenToTextCoordinates(mousePageX, mousePageY); - cursor.row = Math.max(0, Math.min(cursor.row, self.doc.getLength()-1)); + cursor.row = Math.max(0, Math.min(cursor.row, self.session.getLength()-1)); if (self.$clickSelection) { if (self.$clickSelection.contains(cursor.row, cursor.column)) { @@ -394,7 +394,7 @@ var Editor =function(renderer, doc) { this.getCopyText = function() { if (!this.selection.isEmpty()) { - return this.doc.getTextRange(this.getSelectionRange()); + return this.session.getTextRange(this.getSelectionRange()); } else { return ""; @@ -406,7 +406,7 @@ var Editor =function(renderer, doc) { return; if (!this.selection.isEmpty()) { - this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); this.clearSelection(); } }; @@ -416,28 +416,28 @@ var Editor =function(renderer, doc) { return; var cursor = this.getCursorPosition(); - text = text.replace("\t", this.doc.getTabString()); + text = text.replace("\t", this.session.getTabString()); // remove selected text if (!this.selection.isEmpty()) { - var cursor = this.doc.remove(this.getSelectionRange()); + var cursor = this.session.remove(this.getSelectionRange()); this.clearSelection(); } else if (this.$overwrite){ var range = new Range.fromPoints(cursor, cursor); range.end.column += text.length; - this.doc.remove(range); + this.session.remove(range); } this.clearSelection(); var lineState = this.bgTokenizer.getState(cursor.row); - var shouldOutdent = this.mode.checkOutdent(lineState, this.doc.getLine(cursor.row), text); - var line = this.doc.getLine(cursor.row); - var lineIndent = this.mode.getNextLineIndent(lineState, line.slice(0, cursor.column), this.doc.getTabString()); - var end = this.doc.insert(cursor, text); + var shouldOutdent = this.mode.checkOutdent(lineState, this.session.getLine(cursor.row), text); + var line = this.session.getLine(cursor.row); + var lineIndent = this.mode.getNextLineIndent(lineState, line.slice(0, cursor.column), this.session.getTabString()); + var end = this.session.insert(cursor, text); /* TODO: This shortcut is somehow broken - if (!shouldOutdent && line != this.doc.getLine(row) && text != "\n") { + if (!shouldOutdent && line != this.session.getLine(row) && text != "\n") { this.moveCursorToPosition(end); this.renderer.scrollCursorIntoView(); return; @@ -447,13 +447,13 @@ var Editor =function(renderer, doc) { var lineState = this.bgTokenizer.getState(cursor.row); // multi line insert if (cursor.row !== end.row) { - var size = this.doc.getTabSize(), + var size = this.session.getTabSize(), minIndent = Number.MAX_VALUE; for (var row = cursor.row + 1; row <= end.row; ++row) { var indent = 0; - line = this.doc.getLine(row); + line = this.session.getLine(row); for (var i = 0; i < line.length; ++i) if (line.charAt(i) == '\t') indent += size; @@ -468,18 +468,18 @@ var Editor =function(renderer, doc) { for (var row = cursor.row + 1; row <= end.row; ++row) { var outdent = minIndent; - line = this.doc.getLine(row); + line = this.session.getLine(row); for (var i = 0; i < line.length && outdent > 0; ++i) if (line.charAt(i) == '\t') outdent -= size; else if (line.charAt(i) == ' ') outdent -= 1; - this.doc.replace(new Range(row, 0, row, line.length), line.substr(i)); + this.session.replace(new Range(row, 0, row, line.length), line.substr(i)); } - end.column += this.doc.indentRows(cursor.row + 1, end.row, lineIndent); + end.column += this.session.indentRows(cursor.row + 1, end.row, lineIndent); } else { if (shouldOutdent) { - end.column += this.mode.autoOutdent(lineState, this.doc, cursor.row); + end.column += this.mode.autoOutdent(lineState, this.session, cursor.row); } } @@ -595,7 +595,7 @@ var Editor =function(renderer, doc) { if (this.selection.isEmpty()) { this.selection.selectRight(); } - this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); this.clearSelection(); }; @@ -606,7 +606,7 @@ var Editor =function(renderer, doc) { if (this.selection.isEmpty()) this.selection.selectLeft(); - this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); + this.moveCursorToPosition(this.session.remove(this.getSelectionRange())); this.clearSelection(); }; @@ -614,21 +614,21 @@ var Editor =function(renderer, doc) { if (this.$readOnly) return; - var doc = this.doc, - range = this.getSelectionRange(); + var session = this.session; + var range = this.getSelectionRange(); if (range.start.row < range.end.row || range.start.column < range.end.column) { var rows = this.$getSelectedRows(); - var count = doc.indentRows(rows.first, rows.last, "\t"); + var count = session.indentRows(rows.first, rows.last, "\t"); this.selection.shiftSelection(count); } else { var indentString; - if (this.doc.getUseSoftTabs()) { - var size = doc.getTabSize(), + if (this.session.getUseSoftTabs()) { + var size = session.getTabSize(), position = this.getCursorPosition(), - column = doc.documentToScreenColumn(position.row, position.column), + column = session.documentToScreenColumn(position.row, position.column), count = (size - column % size); indentString = lang.stringRepeat(" ", count); @@ -642,8 +642,8 @@ var Editor =function(renderer, doc) { if (this.$readOnly) return; - var selection = this.doc.getSelection(); - var range = this.doc.outdentRows(selection.getRange()); + var selection = this.session.getSelection(); + var range = this.session.outdentRows(selection.getRange()); selection.setSelectionRange(range, selection.isBackwards()); this.$updateDesiredColumn(); @@ -655,7 +655,7 @@ var Editor =function(renderer, doc) { var state = this.bgTokenizer.getState(this.getCursorPosition().row); var rows = this.$getSelectedRows() - var addedColumns = this.mode.toggleCommentLines(state, this.doc, rows.first, rows.last); + var addedColumns = this.mode.toggleCommentLines(state, this.session, rows.first, rows.last); this.selection.shiftSelection(addedColumns); }; @@ -667,7 +667,7 @@ var Editor =function(renderer, doc) { this.selection.setSelectionAnchor(rows.last+1, 0); this.selection.selectTo(rows.first, 0); - this.doc.remove(this.getSelectionRange()); + this.session.remove(this.getSelectionRange()); this.clearSelection(); }; @@ -676,7 +676,7 @@ var Editor =function(renderer, doc) { return; this.$moveLines(function(firstRow, lastRow) { - return this.doc.moveLinesDown(firstRow, lastRow); + return this.session.moveLinesDown(firstRow, lastRow); }); }; @@ -685,7 +685,7 @@ var Editor =function(renderer, doc) { return; this.$moveLines(function(firstRow, lastRow) { - return this.doc.moveLinesUp(firstRow, lastRow); + return this.session.moveLinesUp(firstRow, lastRow); }); }; @@ -694,7 +694,7 @@ var Editor =function(renderer, doc) { return; this.$moveLines(function(firstRow, lastRow) { - this.doc.duplicateLines(firstRow, lastRow); + this.session.duplicateLines(firstRow, lastRow); return 0; }); }; @@ -704,7 +704,7 @@ var Editor =function(renderer, doc) { return; this.$moveLines(function(firstRow, lastRow) { - return this.doc.duplicateLines(firstRow, lastRow); + return this.session.duplicateLines(firstRow, lastRow); }); }; @@ -798,7 +798,7 @@ var Editor =function(renderer, doc) { this.gotoPageDown = function() { var row = this.getPageDownRow(), column = Math.min(this.getCursorPosition().column, - this.doc.getLine(row).length); + this.session.getLine(row).length); this.scrollToRow(row); this.getSelection().moveCursorTo(row, column); @@ -807,7 +807,7 @@ var Editor =function(renderer, doc) { this.gotoPageUp = function() { var row = this.getPageUpRow(), column = Math.min(this.getCursorPosition().column, - this.doc.getLine(row).length); + this.session.getLine(row).length); this.scrollToRow(row); this.getSelection().moveCursorTo(row, column); @@ -874,7 +874,7 @@ var Editor =function(renderer, doc) { if (this.$desiredColumn) { var cursor = this.getCursorPosition(); - var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn); + var column = this.session.screenToDocumentColumn(cursor.row, this.$desiredColumn); this.selection.moveCursorTo(cursor.row, column); } }; @@ -885,14 +885,14 @@ var Editor =function(renderer, doc) { if (this.$desiredColumn) { var cursor = this.getCursorPosition(); - var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn); + var column = this.session.screenToDocumentColumn(cursor.row, this.$desiredColumn); this.selection.moveCursorTo(cursor.row, column); } }; this.$updateDesiredColumn = function() { var cursor = this.getCursorPosition(); - this.$desiredColumn = this.doc.documentToScreenColumn(cursor.row, cursor.column); + this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column); }; this.navigateLeft = function(times) { @@ -957,7 +957,7 @@ var Editor =function(renderer, doc) { if (options) this.$search.set(options); - var range = this.$search.find(this.doc); + var range = this.$search.find(this.session); this.$tryReplace(range, replacement); if (range !== null) this.selection.setSelectionRange(range); @@ -969,7 +969,7 @@ var Editor =function(renderer, doc) { this.$search.set(options); } - var ranges = this.$search.findAll(this.doc); + var ranges = this.$search.findAll(this.session); if (!ranges.length) return; @@ -984,10 +984,10 @@ var Editor =function(renderer, doc) { }, this.$tryReplace = function(range, replacement) { - var input = this.doc.getTextRange(range); + var input = this.session.getTextRange(range); var replacement = this.$search.replace(input, replacement); if (replacement !== null) { - range.end = this.doc.replace(range, replacement); + range.end = this.session.replace(range, replacement); return range; } else { return null; @@ -1024,13 +1024,13 @@ var Editor =function(renderer, doc) { this.$find = function(backwards) { if (!this.selection.isEmpty()) { - this.$search.set({needle: this.doc.getTextRange(this.getSelectionRange())}); + this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())}); } if (typeof backwards != "undefined") this.$search.set({backwards: backwards}); - var range = this.$search.find(this.doc); + var range = this.$search.find(this.session); if (range) { this.gotoLine(range.end.row+1, range.end.column); this.$updateDesiredColumn(); @@ -1039,11 +1039,11 @@ var Editor =function(renderer, doc) { }; this.undo = function() { - this.doc.getUndoManager().undo(); + this.session.getUndoManager().undo(); }; this.redo = function() { - this.doc.getUndoManager().redo(); + this.session.getUndoManager().redo(); }; }).call(Editor.prototype); diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index 7c65aa1e..60a6938e 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -52,14 +52,14 @@ var Cursor = function(parentEl) { (function() { - this.setDocument = function(doc) { - this.doc = doc; + this.setSession = function(session) { + this.session = session; }; this.setCursor = function(position, overwrite) { this.position = { row : position.row, - column : this.doc.documentToScreenColumn(position.row, position.column) + column : this.session.documentToScreenColumn(position.row, position.column) }; if (overwrite) { dom.addCssClass(this.cursor, "ace_overwrite"); diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 82e860cb..027212b4 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -51,8 +51,8 @@ var Marker = function(parentEl) { (function() { - this.setDocument = function(doc) { - this.doc = doc; + this.setSession = function(session) { + this.session = session; }; this.addMarker = function(range, clazz, type) { @@ -105,7 +105,7 @@ var Marker = function(parentEl) { // selection start var row = range.start.row; - var lineRange = new Range(row, range.start.column, row, this.doc.getLine(row).length); + var lineRange = new Range(row, range.start.column, row, this.session.getLine(row).length); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1); // selection end @@ -116,13 +116,13 @@ var Marker = function(parentEl) { for (var row = range.start.row + 1; row < range.end.row; row++) { lineRange.start.row = row; lineRange.end.row = row; - lineRange.end.column = this.doc.getLine(row).length; // account for endofline characters + lineRange.end.column = this.session.getLine(row).length; // account for endofline characters this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1); } }; this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) { - var range = range.toScreenRange(this.doc); + var range = range.toScreenRange(this.session); // from selection start to the end of the line var height = layerConfig.lineHeight; @@ -164,7 +164,7 @@ var Marker = function(parentEl) { }; this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) { - var range = range.toScreenRange(this.doc); + var range = range.toScreenRange(this.session); var height = layerConfig.lineHeight; var width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth); diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 356e4ad3..8ef2ebf3 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -125,8 +125,8 @@ var Text = function(parentEl) { return size; }; - this.setDocument = function(doc) { - this.doc = doc; + this.setSession = function(session) { + this.session = session; }; this.showInvisibles = false; @@ -139,7 +139,7 @@ var Text = function(parentEl) { }; this.$computeTabString = function() { - var tabSize = this.doc.getTabSize(); + var tabSize = this.session.getTabSize(); if (this.showInvisibles) { var halfTab = (tabSize) / 2; this.$tabString = "" @@ -280,7 +280,7 @@ var Text = function(parentEl) { }; if (this.showInvisibles) { - if (row !== this.doc.getLength() - 1) { + if (row !== this.session.getLength() - 1) { stringBuilder.push("" + this.EOL_CHAR + ""); } else { stringBuilder.push("" + this.EOF_CHAR + ""); diff --git a/lib/ace/test/change_document_test.js b/lib/ace/test/change_document_test.js index 77375781..4a91eeb1 100644 --- a/lib/ace/test/change_document_test.js +++ b/lib/ace/test/change_document_test.js @@ -49,18 +49,18 @@ var EditSession = require("../edit_session").EditSession, var Test = { setUp : function(next) { - this.doc1 = new EditSession(["abc", "def"]); - this.doc2 = new EditSession(["ghi", "jkl"]); + this.session1 = new EditSession(["abc", "def"]); + this.session2 = new EditSession(["ghi", "jkl"]); this.editor = new Editor(new MockRenderer()); next(); }, "test: change document" : function() { - this.editor.setDocument(this.doc1); - assert.equal(this.editor.getDocument(), this.doc1); + this.editor.setSession(this.session1); + assert.equal(this.editor.getSession(), this.session1); - this.editor.setDocument(this.doc2); - assert.equal(this.editor.getDocument(), this.doc2); + this.editor.setSession(this.session2); + assert.equal(this.editor.getSession(), this.session2); }, "test: only changes to the new document should have effect" : function() { @@ -69,24 +69,24 @@ var Test = { called = true; }; - this.editor.setDocument(this.doc1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session1); + this.editor.setSession(this.session2); - this.doc1.duplicateLines(0, 0); + this.session1.duplicateLines(0, 0); assert.notOk(called); - this.doc2.duplicateLines(0, 0); + this.session2.duplicateLines(0, 0); assert.ok(called); }, "test: should use cursor of new document" : function() { - this.doc1.getSelection().moveCursorTo(0, 1); - this.doc2.getSelection().moveCursorTo(1, 0); + this.session1.getSelection().moveCursorTo(0, 1); + this.session2.getSelection().moveCursorTo(1, 0); - this.editor.setDocument(this.doc1); + this.editor.setSession(this.session1); assert.position(this.editor.getCursorPosition(), 0, 1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session2); assert.position(this.editor.getCursorPosition(), 1, 0); }, @@ -95,28 +95,28 @@ var Test = { called = true; }; - this.editor.setDocument(this.doc1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session1); + this.editor.setSession(this.session2); assert.position(this.editor.getCursorPosition(), 0, 0); var called = false; - this.doc1.getSelection().moveCursorTo(0, 1); + this.session1.getSelection().moveCursorTo(0, 1); assert.position(this.editor.getCursorPosition(), 0, 0); assert.notOk(called); - this.doc2.getSelection().moveCursorTo(1, 1); + this.session2.getSelection().moveCursorTo(1, 1); assert.position(this.editor.getCursorPosition(), 1, 1); assert.ok(called); }, "test: should use selection of new document" : function() { - this.doc1.getSelection().selectTo(0, 1); - this.doc2.getSelection().selectTo(1, 0); + this.session1.getSelection().selectTo(0, 1); + this.session2.getSelection().selectTo(1, 0); - this.editor.setDocument(this.doc1); + this.editor.setSession(this.session1); assert.position(this.editor.getSelection().getSelectionLead(), 0, 1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session2); assert.position(this.editor.getSelection().getSelectionLead(), 1, 0); }, @@ -125,16 +125,16 @@ var Test = { called = true; }; - this.editor.setDocument(this.doc1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session1); + this.editor.setSession(this.session2); assert.position(this.editor.getSelection().getSelectionLead(), 0, 0); var called = false; - this.doc1.getSelection().selectTo(0, 1); + this.session1.getSelection().selectTo(0, 1); assert.position(this.editor.getSelection().getSelectionLead(), 0, 0); assert.notOk(called); - this.doc2.getSelection().selectTo(1, 1); + this.session2.getSelection().selectTo(1, 1); assert.position(this.editor.getSelection().getSelectionLead(), 1, 1); assert.ok(called); }, @@ -143,14 +143,14 @@ var Test = { this.editor.onDocumentModeChange = function() { called = true; }; - this.editor.setDocument(this.doc1); - this.editor.setDocument(this.doc2); + this.editor.setSession(this.session1); + this.editor.setSession(this.session2); var called = false; - this.doc1.setMode(new Text()); + this.session1.setMode(new Text()); assert.notOk(called); - this.doc2.setMode(new JavaScriptMode()); + this.session2.setMode(new JavaScriptMode()); assert.ok(called); } }; diff --git a/lib/ace/test/mockrenderer.js b/lib/ace/test/mockrenderer.js index ec068536..be4cd520 100644 --- a/lib/ace/test/mockrenderer.js +++ b/lib/ace/test/mockrenderer.js @@ -69,8 +69,12 @@ MockRenderer.prototype.getMouseEventTarget = function() { return this.container; }; -MockRenderer.prototype.setDocument = function(doc) { - this.doc = doc; +MockRenderer.prototype.setSession = function(session) { + this.session = session; +}; + +MockRenderer.prototype.getSession = function(session) { + return this.session; }; MockRenderer.prototype.setTokenizer = function() { @@ -91,7 +95,7 @@ MockRenderer.prototype.scrollCursorIntoView = function() { }; MockRenderer.prototype.scrollToRow = function(row) { - var row = Math.min(this.doc.getLength() - this.visibleRowCount, Math.max(0, + var row = Math.min(this.session.getLength() - this.visibleRowCount, Math.max(0, row)); this.layerConfig.firstVisibleRow = row; this.layerConfig.lastVisibleRow = row + this.visibleRowCount; diff --git a/lib/ace/test/virtual_renderer_test.js b/lib/ace/test/virtual_renderer_test.js index 24d6e2f3..83e0351c 100644 --- a/lib/ace/test/virtual_renderer_test.js +++ b/lib/ace/test/virtual_renderer_test.js @@ -38,7 +38,7 @@ define(function(require, exports, module) { require("./mockdom"); -var Document = require("../document").Document, +var EditSession = require("ace/edit_session").EditSession, VirtualRenderer = require("../virtual_renderer").VirtualRenderer, assert = require("./assertions"); @@ -54,7 +54,7 @@ var Test = { document.body.appendChild(el); var renderer = new VirtualRenderer(el); - renderer.setDocument(new Document("1234")); + renderer.setSession(new EditSession("1234")); renderer.characterWidth = 10; renderer.lineHeight = 15; diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 45f61c0f..687085fa 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -133,11 +133,11 @@ var VirtualRenderer = function(container, theme) { oop.implement(this, EventEmitter); - this.setDocument = function(doc) { - this.doc = doc; - this.$cursorLayer.setDocument(doc); - this.$markerLayer.setDocument(doc); - this.$textLayer.setDocument(doc); + this.setSession = function(session) { + this.session = session; + this.$cursorLayer.setSession(session); + this.$markerLayer.setSession(session); + this.$textLayer.setSession(session); this.$loop.schedule(this.CHANGE_FULL); }; @@ -193,7 +193,7 @@ var VirtualRenderer = function(container, theme) { this.scroller.style.height = height + "px"; this.scrollBar.setHeight(height); - if (this.doc) { + if (this.session) { this.scrollToY(this.getScrollTop()); changes = changes | this.CHANGE_FULL; } @@ -322,12 +322,12 @@ var VirtualRenderer = function(container, theme) { }; this.$updateScrollBar = function() { - this.scrollBar.setInnerHeight(this.doc.getLength() * this.lineHeight); + this.scrollBar.setInnerHeight(this.session.getLength() * this.lineHeight); this.scrollBar.setScrollTop(this.scrollTop); }; this.$renderChanges = function(changes) { - if (!changes || !this.doc || !this.$tokenizer) + if (!changes || !this.session || !this.$tokenizer) return; // text, scrolling and resize changes can cause the view port size to change @@ -395,7 +395,7 @@ var VirtualRenderer = function(container, theme) { var lineCount = Math.ceil(minHeight / this.lineHeight); var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); - var lastRow = Math.max(0, Math.min(this.doc.getLength(), firstRow + lineCount) - 1); + var lastRow = Math.max(0, Math.min(this.session.getLength(), firstRow + lineCount) - 1); var layerConfig = this.layerConfig = { width : longestLine, @@ -441,7 +441,7 @@ var VirtualRenderer = function(container, theme) { }; this.$getLongestLine = function() { - var charCount = this.doc.getScreenWidth(); + var charCount = this.session.getScreenWidth(); if (this.$textLayer.showInvisibles) charCount += 1; @@ -530,7 +530,7 @@ var VirtualRenderer = function(container, theme) { }; this.scrollToY = function(scrollTop) { - var maxHeight = this.doc.getLength() * this.lineHeight - this.$size.scrollerHeight; + var maxHeight = this.session.getLength() * this.lineHeight - this.$size.scrollerHeight; var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop)); if (this.scrollTop !== scrollTop) { @@ -561,14 +561,14 @@ var VirtualRenderer = function(container, theme) { return { row : row, - column : this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col) + column : this.session.screenToDocumentColumn(Math.max(0, Math.min(row, this.session.getLength()-1)), col) }; }; this.textToScreenCoordinates = function(row, column) { var canvasPos = this.scroller.getBoundingClientRect(); - var x = this.$padding + Math.round(this.doc.documentToScreenColumn(row, column) * this.characterWidth); + var x = this.$padding + Math.round(this.session.documentToScreenColumn(row, column) * this.characterWidth); var y = row * this.lineHeight; return { From dba904d2b9ff53c56ae8075997351bf537fc4c6e Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 09:24:41 +0100 Subject: [PATCH 12/36] data passed in a change event is now a delta --- lib/ace/editor.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 4055d2b2..807d1d2a 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -228,9 +228,15 @@ var Editor =function(renderer, session) { }; this.onDocumentChange = function(e) { - var data = e.data; - this.bgTokenizer.start(data.firstRow); - this.renderer.updateLines(data.firstRow, data.lastRow); + var delta = e.data; + var range = delta.range; + + this.bgTokenizer.start(range.start.row); + if (range.start.row == range.end.row) + var lastRow = range.end.row; + else + lastRow = Infinity; + this.renderer.updateLines(range.start.row, lastRow); // update cursor because tab characters can influence the cursor position this.renderer.updateCursor(this.getCursorPosition(), this.$overwrite); From 6961f375a6487a05e3d14deaa61f29234c46f7ea Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 10:06:13 +0100 Subject: [PATCH 13/36] update pilot --- support/pilot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/pilot b/support/pilot index a7d30d94..250ffe66 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit a7d30d942c7b8f9e68bcb818a83faaa407404c56 +Subproject commit 250ffe66af17457c8d56660b57cdf7ae6cef73c3 From e577a7070e39be2c340f7b95d13bff581802dc96 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 10:42:27 +0100 Subject: [PATCH 14/36] set value on empty document --- lib/ace/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 492c8050..985e2091 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -56,7 +56,7 @@ var Document = function(text) { oop.implement(this, EventEmitter); this.setValue = function(text) { - this.remove(new Range(0, 0, this.$lines.length, this.$lines[this.$lines.length-1].length)); + this.remove(new Range(0, 0, this.$lines.length, this.getLine(this.$lines.length-1).length)); this.insertLines(0, this.$split(text)); }; From af0b9c2d57aca7989408e67cd7a589accf510c77 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 11:19:13 +0100 Subject: [PATCH 15/36] point to cockpit on ajaxorg --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 22e3dda5..b46e518b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,10 +21,10 @@ url = git://github.com/tautologistics/node-htmlparser.git [submodule "support/cockpit"] path = support/cockpit - url = git://github.com/mozilla/cockpit.git + url = git://github.com/ajaxorg/cockpit.git [submodule "support/pilot"] path = support/pilot url = git://github.com/ajaxorg/pilot.git [submodule "support/dryice"] path = support/dryice - url = git://github.com/mozilla/dryice.git \ No newline at end of file + url = git://github.com/mozilla/dryice.git From 81a742e2f1e74882ddca68cf84f42840225f7011 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 12:29:53 +0100 Subject: [PATCH 16/36] Don't use $lines in setValue and $clipPosition to make subclassing easier --- lib/ace/document.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 985e2091..bb25eeb6 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -56,7 +56,8 @@ var Document = function(text) { oop.implement(this, EventEmitter); this.setValue = function(text) { - this.remove(new Range(0, 0, this.$lines.length, this.getLine(this.$lines.length-1).length)); + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-1).length)); this.insertLines(0, this.$split(text)); }; @@ -151,7 +152,7 @@ var Document = function(text) { }; this.$clipPosition = function(position) { - var length = this.$lines.length; + var length = this.getLength(); if (position.row >= length) { position.row = Math.max(0, length - 1); position.column = this.getLine(length-1).length; From c879e0a802835dc9ea149b6a9c11ab3bdfe6babb Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 12:30:09 +0100 Subject: [PATCH 17/36] fix undo manager --- lib/ace/edit_session.js | 52 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index ce959e57..e9e2a66a 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -93,6 +93,7 @@ var EditSession = function(text, mode) { this.setValue = function(text) { this.doc.setValue(text); + this.$deltas = []; }; this.getValue = @@ -479,36 +480,41 @@ var EditSession = function(text, mode) { }; this.undoChanges = function(deltas) { - this.selection.clearSelection(); + if (!deltas.length) + return; + this.$fromUndo = true; - for (var i=deltas.length-1; i>=0; i--) { - var delta = deltas[i]; - if (delta.action == "insertText") { - this.remove(delta.range, true); - this.selection.moveCursorToPosition(delta.range.start); - } else { - this.insert(delta.range.start, delta.text, true); - this.selection.clearSelection(); - } - } + this.doc.revertDeltas(deltas); this.$fromUndo = false; + + // update the selection + var firstDelta = deltas[0]; + var lastDelta = deltas[deltas.length-1]; + + this.selection.clearSelection(); + if (firstDelta.action == "insertText" || firstDelta.action == "insertLines") + this.selection.moveCursorToPosition(firstDelta.range.start); + if (firstDelta.action == "removeText" || firstDelta.action == "removeLines") + this.selection.setSelectionRange(Range.fromPoints(firstDelta.range.start, lastDelta.range.end)); }, this.redoChanges = function(deltas) { - this.selection.clearSelection(); - + if (!deltas.length) + return; + this.$fromUndo = true; - for (var i=0; i Date: Wed, 19 Jan 2011 12:50:19 +0100 Subject: [PATCH 18/36] clean up --- lib/ace/document.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index bb25eeb6..20250ba7 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -166,9 +166,8 @@ var Document = function(text) { position = this.$clipPosition(position); - if (this.$lines.length <= 1) { + if (this.getLength() <= 1) this.$detectNewLine(text); - } var newLines = this.$split(text); @@ -336,15 +335,13 @@ var Document = function(text) { }; this.replace = function(range, text) { - // Shortcut: Nothing to replace in this case. if (text.length == 0 && range.isEmpty()) return range.start; // Shortcut: If the text we want to insert is the same as it is already // in the document, we don't have to replace anything. - if (text == this.getTextRange(range)) { + if (text == this.getTextRange(range)) return range.end; - } this.remove(range); if (text) { From eed67cb9f7de494aa033f35034617d898bea0507 Mon Sep 17 00:00:00 2001 From: Ruben Date: Wed, 19 Jan 2011 07:19:41 -0800 Subject: [PATCH 19/36] Change readme --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 5d7f84c8..161852a0 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ -ACE (Ajax.org Code Editor) +ACE (Ajax.org Cloud9 Editor) ========================== -ACE is a standalone code editor written in JavaScript. It can be easily embedded in any web page and JavaScript application. It is currently used as the editor component of the [Cloud9 IDE](http://cloud9ide.com). +ACE is a standalone code editor written in JavaScript. It can be easily embedded in any web page and JavaScript application. It is developed as the editor component for the [Cloud9 IDE](http://cloud9ide.com). Checkout the [demo](http://ajaxorg.github.com/ace/editor-build.html)! From 61c6638209c9d6db331775069b7c078162c05dac Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 19 Jan 2011 22:31:59 +0100 Subject: [PATCH 20/36] fix pilot path --- Makefile.dryice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 6ed1dd70..d92c938e 100644 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -44,7 +44,7 @@ var aceHome = __dirname; var pilot = copy.createDataObject(); copy({ source: [ { - root: aceHome + '/support/cockpit/support/pilot/lib', + root: aceHome + '/support/pilot/lib', include: /.*\.js$/, exclude: /tests?\// } ], From 4e7f9d4856166a8f28b9a106232f72c4f4b4b017 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Thu, 20 Jan 2011 13:27:54 +0100 Subject: [PATCH 21/36] align readme with ace.ajax.org --- Readme.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 161852a0..f3fa29a8 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,35 @@ ACE (Ajax.org Cloud9 Editor) -========================== +============================ -ACE is a standalone code editor written in JavaScript. It can be easily embedded in any web page and JavaScript application. It is developed as the editor component for the [Cloud9 IDE](http://cloud9ide.com). +Ace is a standalone code editor written in JavaScript. Our goal is to create a web based code editor that matches and extends the features, usability and performance of existing native editors such as TextMate, Vim or Eclipse. It can be easily embedded in any web page and JavaScript application. Ace is developed as the primary editor for [Cloud9 IDE](http://www.cloud9ide.com/) and the successor of the Mozilla Skywriter (Bespin) Project. -Checkout the [demo](http://ajaxorg.github.com/ace/editor-build.html)! +Features +-------- + +* Syntax highlighting +* Auto indentation and outdent +* An optional command line +* Work with huge documents (100,000 lines and more are no problem) +* Fully customizable key bindings including VI and Emacs modes +* Themes (TextMate themes can be imported) +* Search and replace with regular expressions +* Highlight matching parentheses +* Toggle between soft tabs and real tabs +* Displays hidden characters + +Take Ace for a spin! +-------------------- + +Check out the Ace live [demo](http://ajaxorg.github.com/ace/editor-build.html) or get a [Cloud9 IDE account](http://run.cloud9ide.com) to experience Ace while editing one of your own GitHub projects. + +History +------- + +Previously known as “Bespin” or lately “Skywriter” it’s now known as Ace (Ajax.org Cloud9 Editor)! Bespin and Ace started as two independent projects both aiming to build a no compromise code editor component for the web. Bespin started as part of Mozilla Labs and was based on the canvas tag, while Ace is the Editor component of the Cloud9 IDE and is using the DOM for rendering. After the release of Ace at JSConf.eu 2010 in Berlin the Skywriter team decided to merge Ace with a simplified version of Skywriter's plugin system and some of Skywriter's extensibility points. All these changes have been merged back to Ace now, which supersedes Skywriter. Both Ajax.org and Mozilla are actively developing and maintaining Ace. + +Getting the code +---------------- + +Ace is a community project. We actively encourage and support contributions. The Ace source code is hosted on GitHub. It is released under the Mozilla tri-license (MPL/GPL/LGPL). This is the same license used by Firefox. This license is friendly to all kinds of projects, whether open source or not. Take charge of your editor and add your favorite language highlighting and keybindings! + + git clone git://github.com/ajaxorg/ace.git \ No newline at end of file From e051098608772f19d51272c6534d963e21c39e95 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Thu, 20 Jan 2011 13:31:34 +0100 Subject: [PATCH 22/36] comment out console.log --- build_support/mini_require.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_support/mini_require.js b/build_support/mini_require.js index 63bcf28b..9500fbc2 100644 --- a/build_support/mini_require.js +++ b/build_support/mini_require.js @@ -88,6 +88,6 @@ function define(module, payload) { return; } - console.log('defining module: ' + module + ' as a ' + typeof payload); + // console.log('defining module: ' + module + ' as a ' + typeof payload); require.modules[module] = payload; } From 33d24e0b231ee58575c38f140f12bc640b29f57b Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Thu, 20 Jan 2011 13:31:45 +0100 Subject: [PATCH 23/36] update sub modules --- support/cockpit | 2 +- support/pilot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/support/cockpit b/support/cockpit index 82e2468e..dbc78536 160000 --- a/support/cockpit +++ b/support/cockpit @@ -1 +1 @@ -Subproject commit 82e2468eededd319c4a8062baf258f0f2d4f7c86 +Subproject commit dbc78536a4ea61e0f762067fb847213526500d9f diff --git a/support/pilot b/support/pilot index 250ffe66..f0ba9df0 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit 250ffe66af17457c8d56660b57cdf7ae6cef73c3 +Subproject commit f0ba9df06853f733f5a0cd4d774facd1fc067c92 From dad16163b32dc0548f66c3632de1d63abd40d943 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Thu, 20 Jan 2011 04:34:36 -0800 Subject: [PATCH 24/36] it is Ace not ACE --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index f3fa29a8..b4f633a5 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -ACE (Ajax.org Cloud9 Editor) +Ace (Ajax.org Cloud9 Editor) ============================ Ace is a standalone code editor written in JavaScript. Our goal is to create a web based code editor that matches and extends the features, usability and performance of existing native editors such as TextMate, Vim or Eclipse. It can be easily embedded in any web page and JavaScript application. Ace is developed as the primary editor for [Cloud9 IDE](http://www.cloud9ide.com/) and the successor of the Mozilla Skywriter (Bespin) Project. From f804a62f1dae149f093a239bb2e84af165302b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Kleiman?= Date: Fri, 21 Jan 2011 16:18:25 +0800 Subject: [PATCH 25/36] Fix function documentation. --- lib/ace/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 20250ba7..6a6d2b98 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -300,7 +300,7 @@ var Document = function(text) { * Removes a range of full lines * * @param firstRow {Integer} The first row to be removed - * @param firstRow {Integer} The first row to be removed + * @param lastRow {Integer} The last row to be removed * @return {String[]} The removed lines */ this.removeLines = function(firstRow, lastRow) { From f6f97918f5207406eac23b270df4a1a2aa661ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Kleiman?= Date: Fri, 21 Jan 2011 16:26:11 +0800 Subject: [PATCH 26/36] Remove suspicious code that lacks side-effects. --- lib/ace/mode/xml_highlight_rules.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ace/mode/xml_highlight_rules.js b/lib/ace/mode/xml_highlight_rules.js index 807297c2..f8f6fe6c 100644 --- a/lib/ace/mode/xml_highlight_rules.js +++ b/lib/ace/mode/xml_highlight_rules.js @@ -110,8 +110,6 @@ var XmlHighlightRules = function() { }; }; -/fd/g - oop.inherits(XmlHighlightRules, TextHighlightRules); exports.XmlHighlightRules = XmlHighlightRules; From 6e524d5b8d0c1ffb7f723fac64dcbe10efa3b6f0 Mon Sep 17 00:00:00 2001 From: Tom Andrews Date: Fri, 21 Jan 2011 03:37:48 +0800 Subject: [PATCH 27/36] Removed reference to build folder, as that doesn't exist --- editor-build.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editor-build.html b/editor-build.html index e6008471..da01e173 100644 --- a/editor-build.html +++ b/editor-build.html @@ -197,11 +197,11 @@ echo $output; - - + + - \ No newline at end of file + From dc42d5c49b155f51344b2b06ab711b3c568beea5 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 15:01:03 +0100 Subject: [PATCH 28/36] update pilot --- support/pilot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/pilot b/support/pilot index f0ba9df0..9ef10946 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit f0ba9df06853f733f5a0cd4d774facd1fc067c92 +Subproject commit 9ef10946d31d1b0e2bd63466fa5aba9c5269e5fd From 5f909a4f94d8a8fc97cbe79862558b230037afe7 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 15:22:52 +0100 Subject: [PATCH 29/36] uglify filter is broken --- Makefile.dryice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index d92c938e..d1900a5e 100644 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -137,7 +137,7 @@ copy({ // Create the compressed and uncompressed output files copy({ source: data, - filter: copy.filter.uglifyjs, + //filter: copy.filter.uglifyjs, dest: 'build/ace.js' }); copy({ From 730da2ee1ebe0b600c36de19d15f7649aa7256ba Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 15:36:14 +0100 Subject: [PATCH 30/36] define nodejs dependencies --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 01adf13f..386fb113 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ace", "description": "Ajax.org Code Editor is a full featured source code highlighting editor that powers the Cloud9 IDE", - "version": "0.1", + "version": "0.1.0", "homepage" : "http://github.com/ajaxorg/ace", "engines": {"node": ">= 0.2.0"}, "author": "Fabian Jakobs ", @@ -10,6 +10,10 @@ "type" : "git", "url" : "http://github.com/ajaxorg/ace.git" }, + "dependencies": { + "uglify-js": ">=0.0.2", + "step": ">=0.0.3" + }, "licenses": [{ "type": "MPL", "url": "http://www.mozilla.org/MPL/" From 9373f50ddb7e145e03f57d72754d75b6e224ace2 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 15:59:09 +0100 Subject: [PATCH 31/36] make Makefile executable --- Makefile.dryice.js | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 Makefile.dryice.js diff --git a/Makefile.dryice.js b/Makefile.dryice.js old mode 100644 new mode 100755 index d1900a5e..c60702a3 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -1,3 +1,4 @@ +#!/usr/bin/env node /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * From 08c5c0bec7d47d9bdb6db64f5e36ad56a23ebf17 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 15:59:20 +0100 Subject: [PATCH 32/36] add more npm deps --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 386fb113..e1891036 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ }, "dependencies": { "uglify-js": ">=0.0.2", - "step": ">=0.0.3" + "step": ">=0.0.3", + "asyncjs": ">=0.0.2", + "jsdom": ">=0.1.23", + "htmlparser": ">=1.7.2" }, "licenses": [{ "type": "MPL", From c99d9dd262753aee5475c1533331d781ba80945e Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 17:02:11 +0100 Subject: [PATCH 33/36] replace git submodules by npm dependencies --- .gitmodules | 23 +---------------------- package.json | 5 ++--- support/async | 1 - support/dryice | 1 - support/jsdom | 1 - support/node-htmlparser | 1 - support/requirejs | 1 - 7 files changed, 3 insertions(+), 30 deletions(-) delete mode 160000 support/async delete mode 160000 support/dryice delete mode 160000 support/jsdom delete mode 160000 support/node-htmlparser delete mode 160000 support/requirejs diff --git a/.gitmodules b/.gitmodules index b46e518b..aee8d549 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,30 +1,9 @@ -[submodule "tool/support/node-o3-xml"] - path = tool/support/node-o3-xml - url = git://github.com/ajaxorg/node-o3-xml.git -[submodule "tool/support/async"] - path = tool/support/async - url = git://github.com/fjakobs/async.js.git -[submodule "support/requirejs"] - path = support/requirejs - url = git://github.com/jrburke/requirejs.git [submodule "support/node-o3-xml"] path = support/node-o3-xml url = git://github.com/ajaxorg/node-o3-xml.git -[submodule "support/async"] - path = support/async - url = git://github.com/fjakobs/async.js.git -[submodule "support/jsdom"] - path = support/jsdom - url = git://github.com/tmpvar/jsdom.git -[submodule "support/node-htmlparser"] - path = support/node-htmlparser - url = git://github.com/tautologistics/node-htmlparser.git [submodule "support/cockpit"] path = support/cockpit url = git://github.com/ajaxorg/cockpit.git [submodule "support/pilot"] path = support/pilot - url = git://github.com/ajaxorg/pilot.git -[submodule "support/dryice"] - path = support/dryice - url = git://github.com/mozilla/dryice.git + url = git://github.com/ajaxorg/pilot.git \ No newline at end of file diff --git a/package.json b/package.json index e1891036..17b333bb 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,10 @@ "url" : "http://github.com/ajaxorg/ace.git" }, "dependencies": { - "uglify-js": ">=0.0.2", - "step": ">=0.0.3", "asyncjs": ">=0.0.2", "jsdom": ">=0.1.23", - "htmlparser": ">=1.7.2" + "htmlparser": ">=1.7.2", + "dryice": ">=0.1.0" }, "licenses": [{ "type": "MPL", diff --git a/support/async b/support/async deleted file mode 160000 index 6da80763..00000000 --- a/support/async +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6da8076355fc9f06191d39b8f5989159dc8a162c diff --git a/support/dryice b/support/dryice deleted file mode 160000 index 89f99bb6..00000000 --- a/support/dryice +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 89f99bb65c66d0c25d461ab4af5743ef1676a04d diff --git a/support/jsdom b/support/jsdom deleted file mode 160000 index 48675596..00000000 --- a/support/jsdom +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 486755962dc0b69c60bfd04869ff1e0093406bae diff --git a/support/node-htmlparser b/support/node-htmlparser deleted file mode 160000 index 60d64db4..00000000 --- a/support/node-htmlparser +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 60d64db4a9a8b1a26bd099bc34f657bf096c4f39 diff --git a/support/requirejs b/support/requirejs deleted file mode 160000 index 819c4e7b..00000000 --- a/support/requirejs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 819c4e7b9b1e6e5f99696b5c9f2805891a9e7cfd From ad9056cce20ad509839792e82173a2648c3a2e5e Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 17:02:34 +0100 Subject: [PATCH 34/36] user async.js from npm --- lib/ace/test/all.js | 2 +- lib/ace/test/change_document_test.js | 2 +- lib/ace/test/document_test.js | 4 ++-- lib/ace/test/edit_session_test.js | 4 ++-- lib/ace/test/event_emitter_test.js | 2 +- lib/ace/test/mode/css_test.js | 2 +- lib/ace/test/mode/css_tokenizer_test.js | 2 +- lib/ace/test/mode/html_test.js | 2 +- lib/ace/test/mode/html_tokenizer_test.js | 2 +- lib/ace/test/mode/javascript_test.js | 2 +- lib/ace/test/mode/javascript_tokenizer_test.js | 2 +- lib/ace/test/mode/text_test.js | 2 +- lib/ace/test/mode/xml_test.js | 2 +- lib/ace/test/mode/xml_tokenizer_test.js | 2 +- lib/ace/test/navigation_test.js | 2 +- lib/ace/test/range_test.js | 2 +- lib/ace/test/search_test.js | 2 +- lib/ace/test/selection_test.js | 2 +- lib/ace/test/text_edit_test.js | 2 +- lib/ace/test/virtual_renderer_test.js | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/ace/test/all.js b/lib/ace/test/all.js index 5e4dc4e0..00df7b59 100644 --- a/lib/ace/test/all.js +++ b/lib/ace/test/all.js @@ -37,7 +37,7 @@ require("../../../support/paths"); -var async = require("async"); +var async = require("asyncjs"); async.concat( require("./change_document_test"), diff --git a/lib/ace/test/change_document_test.js b/lib/ace/test/change_document_test.js index 4a91eeb1..d00c2af9 100644 --- a/lib/ace/test/change_document_test.js +++ b/lib/ace/test/change_document_test.js @@ -155,7 +155,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/document_test.js b/lib/ace/test/document_test.js index 2d8f9b33..c46602cd 100644 --- a/lib/ace/test/document_test.js +++ b/lib/ace/test/document_test.js @@ -38,7 +38,7 @@ var Document = require("../document").Document, Range = require("../range").Range, assert = require("./assertions"), - async = require("async"); + async = require("asyncjs"); var Test = { @@ -280,7 +280,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); if (module === require.main) { require("../../../support/paths"); diff --git a/lib/ace/test/edit_session_test.js b/lib/ace/test/edit_session_test.js index c5f76b9b..1cf721fa 100644 --- a/lib/ace/test/edit_session_test.js +++ b/lib/ace/test/edit_session_test.js @@ -42,7 +42,7 @@ var EditSession = require("ace/edit_session").EditSession, MockRenderer = require("./mockrenderer"), Range = require("ace/range").Range, assert = require("./assertions"), - async = require("async"); + async = require("asyncjs"); var Test = { @@ -266,7 +266,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/event_emitter_test.js b/lib/ace/test/event_emitter_test.js index 7a98cd9b..6ebe5638 100644 --- a/lib/ace/test/event_emitter_test.js +++ b/lib/ace/test/event_emitter_test.js @@ -60,7 +60,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test) +module.exports = require("asyncjs/test").testcase(Test) if (module === require.main) module.exports.exec() diff --git a/lib/ace/test/mode/css_test.js b/lib/ace/test/mode/css_test.js index 3b2932c0..654d5c83 100644 --- a/lib/ace/test/mode/css_test.js +++ b/lib/ace/test/mode/css_test.js @@ -70,7 +70,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/css_tokenizer_test.js b/lib/ace/test/mode/css_tokenizer_test.js index f26e82d2..0618edac 100644 --- a/lib/ace/test/mode/css_tokenizer_test.js +++ b/lib/ace/test/mode/css_tokenizer_test.js @@ -84,7 +84,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test, "css tokenizer"); +module.exports = require("asyncjs/test").testcase(Test, "css tokenizer"); }); diff --git a/lib/ace/test/mode/html_test.js b/lib/ace/test/mode/html_test.js index d9cf64e4..7184ffc2 100644 --- a/lib/ace/test/mode/html_test.js +++ b/lib/ace/test/mode/html_test.js @@ -62,7 +62,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/html_tokenizer_test.js b/lib/ace/test/mode/html_tokenizer_test.js index a14ece42..6ba8fdea 100644 --- a/lib/ace/test/mode/html_tokenizer_test.js +++ b/lib/ace/test/mode/html_tokenizer_test.js @@ -65,7 +65,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/javascript_test.js b/lib/ace/test/mode/javascript_test.js index 9fcb9c09..a12c4488 100644 --- a/lib/ace/test/mode/javascript_test.js +++ b/lib/ace/test/mode/javascript_test.js @@ -144,7 +144,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/javascript_tokenizer_test.js b/lib/ace/test/mode/javascript_tokenizer_test.js index ebe44c01..73e13f1e 100644 --- a/lib/ace/test/mode/javascript_tokenizer_test.js +++ b/lib/ace/test/mode/javascript_tokenizer_test.js @@ -101,7 +101,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/text_test.js b/lib/ace/test/mode/text_test.js index a39f7d5b..10ca9d13 100644 --- a/lib/ace/test/mode/text_test.js +++ b/lib/ace/test/mode/text_test.js @@ -59,7 +59,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/xml_test.js b/lib/ace/test/mode/xml_test.js index e2375afb..72bd56e1 100644 --- a/lib/ace/test/mode/xml_test.js +++ b/lib/ace/test/mode/xml_test.js @@ -70,7 +70,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/mode/xml_tokenizer_test.js b/lib/ace/test/mode/xml_tokenizer_test.js index 5905bc64..e63980ed 100644 --- a/lib/ace/test/mode/xml_tokenizer_test.js +++ b/lib/ace/test/mode/xml_tokenizer_test.js @@ -60,7 +60,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/navigation_test.js b/lib/ace/test/navigation_test.js index 44938b6f..c9bbdaf6 100644 --- a/lib/ace/test/navigation_test.js +++ b/lib/ace/test/navigation_test.js @@ -150,7 +150,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test) +module.exports = require("asyncjs/test").testcase(Test) }); if (module === require.main) { diff --git a/lib/ace/test/range_test.js b/lib/ace/test/range_test.js index bc5582ad..8415f135 100644 --- a/lib/ace/test/range_test.js +++ b/lib/ace/test/range_test.js @@ -161,7 +161,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/search_test.js b/lib/ace/test/search_test.js index b33a0d0f..1f42571c 100644 --- a/lib/ace/test/search_test.js +++ b/lib/ace/test/search_test.js @@ -344,7 +344,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test) +module.exports = require("asyncjs/test").testcase(Test) }); if (module === require.main) { diff --git a/lib/ace/test/selection_test.js b/lib/ace/test/selection_test.js index bccf0395..06858ec5 100644 --- a/lib/ace/test/selection_test.js +++ b/lib/ace/test/selection_test.js @@ -290,7 +290,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/text_edit_test.js b/lib/ace/test/text_edit_test.js index 3dbcc3b6..0ae2615e 100644 --- a/lib/ace/test/text_edit_test.js +++ b/lib/ace/test/text_edit_test.js @@ -438,7 +438,7 @@ var Test = { } }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { diff --git a/lib/ace/test/virtual_renderer_test.js b/lib/ace/test/virtual_renderer_test.js index 83e0351c..0d4fe8ed 100644 --- a/lib/ace/test/virtual_renderer_test.js +++ b/lib/ace/test/virtual_renderer_test.js @@ -72,7 +72,7 @@ var Test = { // change tab size after setDocument (for text layer) }; -module.exports = require("async/test").testcase(Test); +module.exports = require("asyncjs/test").testcase(Test); }); if (module === require.main) { From fa686c0c2429a78774f9f74130977f4dbf877d88 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 17:15:59 +0100 Subject: [PATCH 35/36] update readme --- Readme.md | 37 ++++++++++++++++++++++++++++++++++++- static.py | 2 +- 2 files changed, 37 insertions(+), 2 deletions(-) mode change 100644 => 100755 static.py diff --git a/Readme.md b/Readme.md index b4f633a5..8897212b 100644 --- a/Readme.md +++ b/Readme.md @@ -32,4 +32,39 @@ Getting the code Ace is a community project. We actively encourage and support contributions. The Ace source code is hosted on GitHub. It is released under the Mozilla tri-license (MPL/GPL/LGPL). This is the same license used by Firefox. This license is friendly to all kinds of projects, whether open source or not. Take charge of your editor and add your favorite language highlighting and keybindings! - git clone git://github.com/ajaxorg/ace.git \ No newline at end of file + git clone git://github.com/ajaxorg/ace.git + git submodule update --init --recursive + +Running Ace +----------- + +After the checkout Ace works out of the box. No build step is required. Simply open 'editor.html' in any browser except Google Chrome. Google Chrome doesn't allow XMLHTTPRequests from files loaded from disc (i.e. with a file:/// URL). To open the Ace in Chrome simply start the bundled mini HTTP server: + + ./static.py + +The editor can then be opened at http://localhost:9999/editor.html. + +Package Ace +----------- + +To package Ace we use the dryice build tool developed by the Mozilla Skywriter team. To install dryice and all its dependencies simply call: + + npm link . + +Afterwards Ace can by build by calling + + ./Makefile.dryice.js + +The packaged Ace will be put in the 'build' folder. + +Running the Unit Tests +---------------------- + +The Ace unit tests run on node.js. Before the first run a couple of node mudules have to be installed. The easiest way to do this is by using the node package manager (npm). In the Ace base directory simply call + + npm link . + +To run the tests call: + + node lib/ace/test/all.js + diff --git a/static.py b/static.py old mode 100644 new mode 100755 index 774cbb9f..8cac3b7a --- a/static.py +++ b/static.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.4 +#!/usr/bin/env python """static - A stupidly simple WSGI way to serve static (or mixed) content. (See the docstrings of the various functions and classes.) From 6abd5dae8e4e971bf3eb966f201e4589c98f72c6 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 22 Jan 2011 17:17:40 +0100 Subject: [PATCH 36/36] cleanup paths.js --- support/paths.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/support/paths.js b/support/paths.js index 09568933..b081ec7a 100644 --- a/support/paths.js +++ b/support/paths.js @@ -1,8 +1,4 @@ require("./requireJS-node"); require.paths.unshift(__dirname + "/../lib"); -require.paths.unshift(__dirname + "/cockpit/lib"); require.paths.unshift(__dirname + "/pilot/lib"); -require.paths.unshift(__dirname + "/async/lib"); -require.paths.unshift(__dirname + "/node-htmlparser/lib"); -require.paths.unshift(__dirname + "/jsdom/lib"); require.paths.unshift(__dirname); \ No newline at end of file