diff --git a/.gitmodules b/.gitmodules index 22e3dda5..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/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/ajaxorg/pilot.git \ No newline at end of file diff --git a/Makefile.dryice.js b/Makefile.dryice.js old mode 100644 new mode 100755 index 6ed1dd70..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 * @@ -44,7 +45,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?\// } ], @@ -137,7 +138,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({ diff --git a/Readme.md b/Readme.md index 5d7f84c8..8897212b 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,70 @@ -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. 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. + +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 + 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 -Checkout the [demo](http://ajaxorg.github.com/ace/editor-build.html)! 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/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; } diff --git a/demo/startup.js b/demo/startup.js index 41d8321f..419e2667 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; @@ -63,26 +63,26 @@ 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()); var worker = new WorkerClient("../..", ["ace", "pilot"], "ace/worker/demo", "Demo"); worker.send("juhu"); - 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()); @@ -107,7 +107,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(); @@ -125,7 +125,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) { @@ -245,7 +245,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/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 + diff --git a/lib/ace/document.js b/lib/ace/document.js index dd8ad7d9..6a6d2b98 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -38,40 +38,33 @@ 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) { + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-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,17 +121,17 @@ 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); }; + + /** + * 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; @@ -363,480 +147,243 @@ 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; + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; } + return position; + } - 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) { + + position = this.$clipPosition(position); + + if (this.getLength() <= 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 - }; + 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)); + + 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 - 1, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._dispatchEvent("change", { data: delta }); + return range.end; + }, + + this.insertNewLine = function(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)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + 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); + + 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 }); - + this._dispatchEvent("change", { data: delta }); + return end; }; - this.$isNewLine = function(text) { - return (text == "\r\n" || text == "\r" || text == "\n"); - }; + this.remove = function(range) { + // clip to document + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); - 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 }); + if (range.isMultiLine()) { + + // 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); + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } 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; + + this.revertDeltas = function(deltas) { + for (var i=deltas.length-1; 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/edit_session.js b/lib/ace/edit_session.js new file mode 100644 index 00000000..e9e2a66a --- /dev/null +++ b/lib/ace/edit_session.js @@ -0,0 +1,642 @@ +/* ***** 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 Document = require("ace/document").Document; + +var NO_CHANGE_DELTAS = {}; + +var EditSession = function(text, mode) { + this.$modified = true; + this.selection = new Selection(this); + this.$breakpoints = []; + + this.listeners = []; + if (mode) { + this.setMode(mode); + } + + if (text instanceof Document) { + this.setDocument(text) + } else { + this.setDocument(new Document(text)); + } +}; + + +(function() { + + oop.implement(this, EventEmitter); + + 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.getDocument = function() { + return this.doc; + }; + + 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.setValue = function(text) { + this.doc.setValue(text); + this.$deltas = []; + }; + + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + + this.getSelection = function() { + return this.selection; + }; + + 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.setNewLineMode = function(newLineMode) { + this.doc.setNewLineMode(newLineMode); + }; + + this.getNewLineMode = function() { + return this.doc.getNewLineMode(); + }; + + 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.doc.getAllLines(); + 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/g, 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.doc.getLine(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.doc.getLine(row).replace(/\t/g, tab); + }; + + this.getLines = function(firstRow, lastRow) { + return this.doc.getLines(firstRow, lastRow); + }; + + this.getLength = function() { + return this.doc.getLength(); + }; + + this.getTextRange = function(range) { + return this.doc.getTextRange(range); + }; + + 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) { + return this.doc.insert(position, text); + }; + + /** + * @param rows Array[Integer] sorted list of rows + */ + this.multiRowInsert = function(rows, column, text) { + for (var i=rows.length-1; i>=0; i--) { + var row = rows[i]; + if (row >= this.doc.getLength()) + continue; + + var diff = column - this.doc.getLine(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); + } + + return { + rows: end ? end.row - rows[0] : 0, + columns: end ? end.column - column : 0 + } + }; + + this.remove = function(range) { + return this.doc.remove(range); + }; + + 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.doc.getLength()) + continue; + + var end = this.remove(new Range(row, range.start.column, row+height, range.end.column)); + } + }; + + this.undoChanges = function(deltas) { + if (!deltas.length) + return; + + this.$fromUndo = true; + 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) { + if (!deltas.length) + return; + + this.$fromUndo = true; + this.doc.applyDeltas(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.setSelectionRange(Range.fromPoints(firstDelta.range.start, lastDelta.range.end)); + if (firstDelta.action == "removeText" || firstDelta.action == "removeLines") + this.selection.moveCursorToPosition(firstDelta.range.start); + }, + + this.replace = function(range, text) { + return this.doc.replace(range, text); + }; + + this.indentRows = function(startRow, endRow, indentString) { + indentString = indentString.replace(/\t/g, this.getTabString()); + for (var row=startRow; row<=endRow; row++) { + this.insert({row: row, column:0}, indentString); + } + return indentString.length; + }; + + this.outdentRows = function (range) { + var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); + var size = this.getTabSize(); + + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { + var line = this.getLine(i); + + deleteRange.start.row = i; + deleteRange.end.row = i; + for (var j = 0; j < size; ++j) + if (line.charAt(j) != ' ') + break; + if (j < size && line.charAt(j) == '\t') { + deleteRange.start.column = j; + deleteRange.end.column = j + 1; + } else { + deleteRange.start.column = 0; + deleteRange.end.column = j; + } + if (i == range.start.row) + range.start.column -= deleteRange.end.column - deleteRange.start.column; + if (i == range.end.row) + range.end.column -= deleteRange.end.column - deleteRange.start.column; + this.remove(deleteRange); + } + return range; + } + + this.moveLinesUp = function(firstRow, lastRow) { + if (firstRow <= 0) return 0; + + var removed = this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow - 1, removed); + return -1; + }; + + this.moveLinesDown = function(firstRow, lastRow) { + if (lastRow >= this.doc.getLength()-1) return 0; + + var removed = this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow+1, removed); + return 1; + }; + + this.duplicateLines = function(firstRow, lastRow) { + var firstRow = this.$clipRowToDocument(firstRow); + var lastRow = this.$clipRowToDocument(lastRow); + + var lines = this.getLines(firstRow, lastRow); + this.doc.insertLines(firstRow, lines); + + var addedRows = lastRow - firstRow + 1; + return addedRows; + }; + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.doc.getLength()-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/editor.js b/lib/ace/editor.js index e6576dbf..807d1d2a 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -42,13 +42,13 @@ 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; 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 Document("")); + 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"); @@ -228,9 +228,15 @@ var Editor =function(renderer, doc) { }; 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); @@ -280,11 +286,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 +314,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 +351,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 +400,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 +412,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 +422,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 +453,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 +474,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 +601,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 +612,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 +620,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 +648,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 +661,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 +673,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 +682,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 +691,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 +700,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 +710,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 +804,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 +813,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 +880,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 +891,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 +963,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 +975,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 +990,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 +1030,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 +1045,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/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; 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..00df7b59 100644 --- a/lib/ace/test/all.js +++ b/lib/ace/test/all.js @@ -37,11 +37,12 @@ require("../../../support/paths"); -var async = require("async"); +var async = require("asyncjs"); 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..d00c2af9 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,18 +47,20 @@ 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.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() { @@ -67,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); }, @@ -93,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); }, @@ -123,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); }, @@ -141,19 +143,19 @@ 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); } }; -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 1df5f511..c46602cd 100644 --- a/lib/ace/test/document_test.js +++ b/lib/ace/test/document_test.js @@ -35,259 +35,252 @@ * * ***** 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"); + async = require("asyncjs"); var Test = { - "test: find matching opening bracket" : function() { - var doc = new Document(["(()(", "())))"]); + "test: insert text in line" : function() { + var doc = new Document(["12", "34"]); - 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); + 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: 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: 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: 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: 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: move lines down" : function() { - var doc = new Document(["a1", "a2", "a3", "a4"]); + + "test: delete full lines" : function() { + var doc = new Document(["1234", "5678", "abcd"]); - doc.moveLinesDown(0, 1); - assert.equal(doc.toString(), ["a3", "a1", "a2", "a4"].join("\n")); + var deltas = []; + doc.on("change", function(e) { deltas.push(e.data); }); - 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")); + doc.remove(new Range(1, 0, 3, 0)); + assert.equal(doc.getValue(), ["1234", ""].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")); + + "test: remove lines should return the removed lines" : function() { + var doc = new Document(["1234", "5678", "abcd"]); - 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")); + 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"]); - - 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); -}); +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 new file mode 100644 index 00000000..1cf721fa --- /dev/null +++ b/lib/ace/test/edit_session_test.js @@ -0,0 +1,275 @@ +/* ***** 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 EditSession = require("ace/edit_session").EditSession, + UndoManager = require("ace/undomanager").UndoManager, + MockRenderer = require("./mockrenderer"), + Range = require("ace/range").Range, + assert = require("./assertions"), + async = require("asyncjs"); + +var Test = { + + "test: find matching opening bracket" : function() { + var session = new EditSession(["(()(", "())))"]); + + 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 session = new EditSession(["(()(", "())))"]); + + 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 session = new EditSession(["({[", ")]}"]); + + 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(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 session = new EditSession(["a1", "a2", "a3", "a4"]); + + session.moveLinesDown(0, 1); + assert.equal(session.getValue(), ["a3", "a1", "a2", "a4"].join("\n")); + + session.moveLinesDown(1, 2); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); + + session.moveLinesDown(2, 3); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); + + session.moveLinesDown(2, 2); + assert.equal(session.getValue(), ["a3", "a4", "a2", "a1"].join("\n")); + }, + + "test: move lines up" : function() { + var session = new EditSession(["a1", "a2", "a3", "a4"]); + + session.moveLinesUp(2, 3); + assert.equal(session.getValue(), ["a1", "a3", "a4", "a2"].join("\n")); + + session.moveLinesUp(1, 2); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); + + session.moveLinesUp(0, 1); + assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n")); + + session.moveLinesUp(2, 2); + assert.equal(session.getValue(), ["a3", "a1", "a4", "a2"].join("\n")); + }, + + "test: duplicate lines" : function() { + var session = new EditSession(["1", "2", "3", "4"]); + + session.duplicateLines(1, 2); + assert.equal(session.getValue(), ["1", "2", "3", "2", "3", "4"].join("\n")); + }, + + "test: duplicate last line" : function() { + var session = new EditSession(["1", "2", "3"]); + + session.duplicateLines(2, 2); + assert.equal(session.getValue(), ["1", "2", "3", "3"].join("\n")); + }, + + "test: duplicate first line" : function() { + var session = new EditSession(["1", "2", "3"]); + + session.duplicateLines(0, 0); + assert.equal(session.getValue(), ["1", "1", "2", "3"].join("\n")); + }, + + "test: convert document to screen coordinates" : function() { + var session = new EditSession("01234\t567890\t1234"); + session.setTabSize(4); + + 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); + + session.setTabSize(2); + + 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 session = new EditSession("\t\t123"); + session.setTabSize(4); + + 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 session = new EditSession("01234\t567890\t1234"); + session.setTabSize(4); + + 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 session = new EditSession(["12", "", "abcd"]); + + var inserted = session.multiRowInsert([0, 1, 2], 2, "juhu 1"); + assert.equal(inserted.rows, 0); + assert.equal(inserted.columns, 6); + + assert.equal(session.getValue(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + }, + + "test: undo insert text in multiple rows": function() { + var session = new EditSession(["12", "", "abcd"]); + + var undoManager = new UndoManager(); + session.setUndoManager(undoManager); + + 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(session.getValue(), ["12", "", "abcd"].join("\n")); + + undoManager.redo(); + assert.equal(session.getValue(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n")); + }, + + "test: insert new line in multiple rows": function() { + var session = new EditSession(["12", "", "abcd"]); + + var inserted = session.multiRowInsert([0, 1, 2], 2, "\n"); + assert.equal(inserted.rows, 1); + assert.equal(session.getValue(), ["12\n", " \n", "ab\ncd"].join("\n")); + }, + + "test: insert multi line text in multiple rows": function() { + var session = new EditSession(["12", "", "abcd"]); + + var inserted = session.multiRowInsert([0, 1, 2], 2, "juhu\n12"); + assert.equal(inserted.rows, 1); + assert.equal(session.getValue(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n")); + }, + + "test: remove right in multiple rows" : function() { + var session = new EditSession(["12", "", "abcd"]); + + 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 session = new EditSession(["12", "", "abcd"]); + var undoManager = new UndoManager(); + session.setUndoManager(undoManager); + + 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(session.getValue(), ["12", "", "abcd"].join("\n")); + + 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); + } +}; + +module.exports = require("asyncjs/test").testcase(Test); +}); + +if (module === require.main) { + require("../../../support/paths"); + exports.exec() +} \ No newline at end of file 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/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/mode/css_test.js b/lib/ace/test/mode/css_test.js index 77573871..654d5c83 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()); }, @@ -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 a9c7e4fd..7184ffc2 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() { @@ -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 0acf55b1..a12c4488 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,19 +132,19 @@ 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)); } }; -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 06c93f7b..10ca9d13 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()); }, @@ -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 01f86760..72bd56e1 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() { @@ -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 30a1c144..c9bbdaf6 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); @@ -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 00f35b2b..1f42571c 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", "

= 0.2.0"}, "author": "Fabian Jakobs ", @@ -10,6 +10,12 @@ "type" : "git", "url" : "http://github.com/ajaxorg/ace.git" }, + "dependencies": { + "asyncjs": ">=0.0.2", + "jsdom": ">=0.1.23", + "htmlparser": ">=1.7.2", + "dryice": ">=0.1.0" + }, "licenses": [{ "type": "MPL", "url": "http://www.mozilla.org/MPL/" 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.) 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/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/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/paths.js b/support/paths.js index e5b06350..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 + "/cockpit/support/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 + "/pilot/lib"); require.paths.unshift(__dirname); \ No newline at end of file diff --git a/support/pilot b/support/pilot index a7d30d94..9ef10946 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit a7d30d942c7b8f9e68bcb818a83faaa407404c56 +Subproject commit 9ef10946d31d1b0e2bd63466fa5aba9c5269e5fd 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