This commit is contained in:
Ruben Daniels 2010-10-21 18:38:45 +02:00
commit 523ea3c082
33 changed files with 618 additions and 354 deletions

View file

@ -13,7 +13,7 @@ setInterval: false, importScripts: false */
var require;
(function () {
//Change this version number for each release.
var version = "0.14.1",
var version = "0.14.2",
empty = {}, s,
i, defContextName = "_", contextLoads = [],
scripts, script, rePkg, src, m, dataMain, cfg = {}, setReadyState,
@ -43,7 +43,7 @@ var require;
cfg = require;
}
}
/**
* Calls a method on a plugin. The obj object should have two property,
* name: the name of the method to call on the plugin
@ -65,7 +65,7 @@ var require;
req(["require/" + prefix], context.contextName);
}
}
/**
* Convenience method to call main for a require.def call that was put on
* hold in the defQueue.
@ -78,6 +78,33 @@ var require;
context.loaded[args[0]] = true;
}
/**
* Used to set up package paths from a packagePaths or packages config object.
* @param {Object} packages the object to store the new package config
* @param {Array} currentPackages an array of packages to configure
* @param {String} [dir] a prefix dir to use.
*/
function configurePackageDir(packages, currentPackages, dir) {
var i, location, pkgObj;
for (i = 0; (pkgObj = currentPackages[i]); i++) {
pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj;
location = pkgObj.location;
//Add dir to the path, but avoid paths that start with a slash
//or have a colon (indicates a protocol)
if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) {
pkgObj.location = dir + "/" + (pkgObj.location || pkgObj.name);
}
//Normalize package paths.
pkgObj.location = pkgObj.location || pkgObj.name;
pkgObj.lib = pkgObj.lib || "lib";
pkgObj.main = pkgObj.main || "main";
packages[pkgObj.name] = pkgObj;
}
}
/**
* Resumes tracing of dependencies and then checks if everything is loaded.
*/
@ -253,7 +280,7 @@ var require;
var context, newContext, loaded, pluginPrefix,
canSetContext, prop, newLength, outDeps, mods, paths, index, i,
deferMods, deferModArgs, lastModArg, waitingName, packages,
packagePaths, pkgPath, pkgNames, pkgName, pkgObj;
packagePaths;
contextName = contextName ? contextName : (config && config.context ? config.context : s.ctxName);
context = s.contexts[contextName];
@ -271,7 +298,7 @@ var require;
pluginPrefix = context.defPlugin[name];
}
//If module already defined for context, or already waiting to be
//evaluated, leave.
waitingName = context.waiting[name];
@ -326,7 +353,7 @@ var require;
if (s.plugins.newContext) {
s.plugins.newContext(newContext);
}
context = s.contexts[contextName] = newContext;
}
@ -365,43 +392,14 @@ var require;
if (packagePaths) {
for (prop in packagePaths) {
if (!(prop in empty)) {
pkgPath = prop;
pkgNames = packagePaths[pkgPath];
for (i = 0; (pkgName = pkgNames[i]); i++) {
if (typeof pkgName === "string") {
//Standard package mapping.
pkgObj = packages[pkgName] = {
name: pkgName,
location: pkgPath + "/" + pkgName
};
} else {
//A custom setup.
pkgObj = context.config.packages[pkgName.name] = pkgName;
pkgObj.location = pkgPath + "/" + (pkgObj.location || pkgObj.name);
}
}
configurePackageDir(packages, packagePaths[prop], prop);
}
}
}
//Adjust packages if necessary.
if (config.packages) {
for (prop in config.packages) {
if (!(prop in empty)) {
pkgObj = packages[prop] = config.packages[prop];
pkgObj.name = pkgObj.name || prop;
}
}
}
//Normalize package paths.
for (prop in packages) {
if (!(prop in empty)) {
pkgObj = packages[prop];
pkgObj.location = pkgObj.location || pkgObj.name;
pkgObj.lib = pkgObj.lib || "lib";
pkgObj.main = pkgObj.main || "main";
}
configurePackageDir(packages, config.packages);
}
//Done with modifications, assing packages back to context config
@ -430,7 +428,7 @@ var require;
if (config.ready) {
req.ready(config.ready);
}
//If it is just a config block, nothing else,
//then return.
if (!deps) {
@ -445,7 +443,7 @@ var require;
outDeps = deps;
deps = [];
for (i = 0; i < outDeps.length; i++) {
deps[i] = req.splitPrefix(outDeps[i], name);
deps[i] = req.splitPrefix(outDeps[i], name, context);
}
}
@ -501,7 +499,7 @@ var require;
args: [name, deps, callback, context]
});
}
//Hold on to the module until a script load or other adapter has finished
//evaluating the whole file. This helps when a file has more than one
//module in it -- dependencies are not traced and fetched until the whole
@ -630,7 +628,7 @@ var require;
return req;
};
/**
* Internal method used by environment adapters to complete a load event.
* A load event could be a script load or just a load pass from a synchronous
@ -663,7 +661,7 @@ var require;
//moduleName that maps to a require.def call. This line is important
//for traditional browser scripts.
context.loaded[moduleName] = true;
context.scriptCount -= 1;
resume(context);
};
@ -788,7 +786,7 @@ var require;
}
}
};
req.isArray = function (it) {
return ostring.call(it) === "[object Array]";
};
@ -817,10 +815,12 @@ var require;
}
contextName = contextName || s.ctxName;
//Normalize module name, if it contains . or ..
moduleName = req.normalizeName(moduleName, relModuleName);
var ret, context = s.contexts[contextName];
var ret = s.contexts[contextName].defined[moduleName];
//Normalize module name, if it contains . or ..
moduleName = req.normalizeName(moduleName, relModuleName, context);
ret = context.defined[moduleName];
if (ret === undefined) {
req.onError(new Error("require: module name '" +
moduleName +
@ -867,16 +867,17 @@ var require;
req.jsExtRegExp = /\.js$/;
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @param {Object} context
* @returns {String} normalized name
*/
req.normalizeName = function (name, baseName) {
req.normalizeName = function (name, baseName, context) {
//Adjust any relative paths.
var part;
if (name.charAt(0) === ".") {
@ -885,13 +886,20 @@ var require;
name +
", no relative module name available."));
}
//Convert baseName to array, and lop off the last part,
//so that . matches that "directory" and not name of the baseName's
//module. For instance, baseName of "one/two/three", maps to
//"one/two/three.js", but we want the directory, "one/two" for
//this normalization.
baseName = baseName.split("/");
baseName = baseName.slice(0, baseName.length - 1);
if (context.config.packages[baseName]) {
//If the baseName is a package name, then just treat it as one
//name to concat the name with.
baseName = [baseName];
} else {
//Convert baseName to array, and lop off the last part,
//so that . matches that "directory" and not name of the baseName's
//module. For instance, baseName of "one/two/three", maps to
//"one/two/three.js", but we want the directory, "one/two" for
//this normalization.
baseName = baseName.split("/");
baseName = baseName.slice(0, baseName.length - 1);
}
name = baseName.concat(name.split("/"));
for (i = 0; (part = name[i]); i++) {
@ -912,16 +920,17 @@ var require;
* Splits a name into a possible plugin prefix and
* the module name. If baseName is provided it will
* also normalize the name via require.normalizeName()
*
*
* @param {String} name the module name
* @param {String} [baseName] base name that name is
* relative to.
* @param {Object} context
*
* @returns {Object} with properties, 'prefix' (which
* may be null), 'name' and 'fullName', which is a combination
* of the prefix (if it exists) and the name.
*/
req.splitPrefix = function (name, baseName) {
req.splitPrefix = function (name, baseName, context) {
var index = name.indexOf("!"), prefix = null;
if (index !== -1) {
prefix = name.substring(0, index);
@ -929,7 +938,7 @@ var require;
}
//Account for relative paths if there is a base name.
name = req.normalizeName(name, baseName);
name = req.normalizeName(name, baseName, context);
return {
prefix: prefix,
@ -943,10 +952,11 @@ var require;
*/
req.nameToUrl = function (moduleName, ext, contextName, relModuleName) {
var paths, packages, pkg, pkgPath, syms, i, parentModule, url,
config = s.contexts[contextName].config;
context = s.contexts[contextName],
config = context.config;
//Normalize module name if have a base relative module name to work from.
moduleName = req.normalizeName(moduleName, relModuleName);
moduleName = req.normalizeName(moduleName, relModuleName, context);
//If a colon is in the URL, it indicates a protocol is used and it is just
//an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.
@ -1010,7 +1020,7 @@ var require;
priorityName,
pIsWaiting = s.plugins.isWaiting, pOrderDeps = s.plugins.orderDeps,
i, module, allDone, loads, loadArgs, err;
//If already doing a checkLoaded call,
@ -1103,7 +1113,7 @@ var require;
if (pOrderDeps) {
pOrderDeps(context);
}
//Before defining the modules, give priority treatment to any modifiers
//for modules that are already defined.
for (prop in modifiers) {
@ -1113,7 +1123,7 @@ var require;
}
}
}
//Define the modules, doing a depth first search.
for (i = 0; (module = waiting[i]); i++) {
req.exec(module, {}, waiting, context);
@ -1212,12 +1222,12 @@ var require;
/**
* Executes the modules in the correct order.
*
*
* @private
*/
req.exec = function (module, traced, waiting, context) {
//Some modules are just plain script files, abddo not have a formal
//module definition,
//module definition,
if (!module) {
//Returning undefined for Spidermonky strict checking in Komodo
return undefined;
@ -1281,7 +1291,7 @@ var require;
ret = defined[name];
} else {
if (cjsModule && "exports" in cjsModule) {
ret = defined[name] = depModule.exports;
ret = defined[name] = cjsModule.exports;
} else {
if (name in defined && !usingExports) {
req.onError(new Error(name + " has already been defined"));
@ -1294,7 +1304,7 @@ var require;
//Execute modifiers, if they exist.
req.execModifiers(name, traced, waiting, context);
return ret;
};
@ -1334,7 +1344,7 @@ var require;
delete modifiers[target];
}
};
/**
* callback for script loads, used to check status of loading.
*
@ -1455,11 +1465,11 @@ var require;
if (cfg.baseUrlMatch) {
rePkg = cfg.baseUrlMatch;
} else {
rePkg = /(allplugins-|transportD-)?require\.js(\W|$)/i;
}
for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {
@ -1590,7 +1600,7 @@ var require;
}
}
//****** END page load functionality ****************
//Set up default context. If require was a configuration object, use that as base config.
req(cfg);
@ -1888,7 +1898,7 @@ var require;
if (loc === "_match") {
//Found default locale to use for the top-level bundle name.
defLoc = msWaiting[loc];
} else if (msWaiting[loc] !== loc) {
//A "best fit" locale, store it off to the end and handle
//it at the end by just assigning the best fit value, since
@ -1918,7 +1928,7 @@ var require;
//loop above so that the default locale bundle has been properly mixed
//together.
context.defined[master] = context.defined[modulePrefix + "/" + defLoc + "/" + moduleSuffix];
//Handle any best fit locale definitions.
if (bestFit) {
for (loc in bestFit) {
@ -1983,7 +1993,7 @@ var require;
progIds = [progId]; // so faster next time
break;
}
}
}
}
if (!xhr) {
@ -1993,7 +2003,7 @@ var require;
return xhr;
};
}
if (!require.fetchText) {
require.fetchText = function (url, callback) {
var xhr = require.getXhr();
@ -2092,7 +2102,7 @@ var require;
require.fetchText(url, function (text) {
context.text[key] = text;
context.loaded[name] = true;
require.checkLoaded(contextName);
require.checkLoaded(contextName);
});
}
},
@ -2376,7 +2386,7 @@ var require;
/**
* Called when all modules have been loaded. Not needed for this plugin.
* State is reset as part of scriptCacheCallback.
* State is reset as part of scriptCacheCallback.
*/
orderDeps: function (context) {
}

View file

@ -2,17 +2,19 @@
server: http://localhost:4224
load:
- src/ace/lib/core.js
- src/ace/lib/*.js
- src/ace/MEventEmitter.js
- src/ace/mode/Text.js
- src/ace/mode/TextHighlightRules.js
- src/ace/mode/*.js
- src/ace/layer/*.js
- src/ace/*.js
- demo/require.js
# - src/ace/lib/core.js
# - src/ace/lib/*.js
# - src/ace/MEventEmitter.js
# - src/ace/mode/Text.js
# - src/ace/mode/TextHighlightRules.js
# - src/ace/mode/*.js
# - src/ace/layer/*.js
# - src/ace/*.js
- src/debug/*.js
# - src/debug/*.js
- src/test/ace/*.js
- src/test/ace/mode/*.js
- src/test/debug/*.js
# - src/test/ace/*.js
# - src/test/ace/mode/*.js
# - src/test/debug/*.js
- src/ace/test/all.js

View file

@ -34,7 +34,7 @@ var BackgroundTokenizer = function(tokenizer, editor) {
processedLines += 1;
if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
self.fireUpdateEvent(startLine, self.currentLine-1);
var timeout = self.currentLine < lastVisibleRow ? 20 : 100;
self.running = setTimeout(self.$worker, timeout);
return;
@ -102,7 +102,7 @@ var BackgroundTokenizer = function(tokenizer, editor) {
this.$tokenizeRows = function(firstRow, lastRow) {
var rows = [];
// determin start state
// determine start state
var state = "start";
var doCache = false;
if (firstRow > 0 && this.lines[firstRow - 1]) {

View file

@ -100,7 +100,7 @@ var Document = function(text, mode) {
this.getTabString = function() {
if (this.getUseSoftTabs()) {
return new Array(this.getTabSize()+1).join(" ");
return lang.stringRepeat(" ", this.getTabSize());
} else {
return "\t";
}
@ -433,10 +433,10 @@ var Document = function(text, mode) {
var lastLine = newLines[newLines.length - 1] + line.substring(position.column);
this.lines[position.row] = firstLine;
this.$insertLines(position.row + 1, [lastLine], fromUndo);
this.$insertLines(position.row + 1, [lastLine], true);
if (newLines.length > 2) {
this.$insertLines(position.row + 1, newLines.slice(1, -1), fromUndo);
this.$insertLines(position.row + 1, newLines.slice(1, -1), true);
}
var end = {
@ -446,7 +446,6 @@ var Document = function(text, mode) {
}
if (!fromUndo && this.$undoManager) {
var nl = this.$getNewLineCharacter();
this.$deltas.push({
action: "insertText",
range: Range.fromPoints(position, end),
@ -549,34 +548,42 @@ var Document = function(text, mode) {
};
this.indentRows = function(range, indentString) {
for (var row=range.start.row; row<= range.end.row; row++) {
indentString.replace("\t", this.getTabString());
for (var row=range.start.row; row<=range.end.row; row++) {
this.$insert({row: row, column:0}, indentString);
}
this.fireChangeEvent(range.start.row, range.end.row);
return indentString.length;
};
this.outdentRows = function(range, indentString) {
outdentLength = indentString.length;
for (var i=range.start.row; i<= range.end.row; i++) {
if (this.getLine(i).substr(0, outdentLength) !== indentString) {
return 0;
}
}
var deleteRange = new Range(0, 0, 0, outdentLength);
for (var i=range.start.row; i<= range.end.row; i++)
{
this.outdentRows = function (range) {
var deleteRange = new Range(0, 0, 0, 0),
size = this.getTabSize();
for (var i = range.start.row; i <= range.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);
}
this.fireChangeEvent(range.start.row, range.end.row);
return -outdentLength;
};
return range;
}
this.moveLinesUp = function(firstRow, lastRow) {
if (firstRow <= 0) return 0;

View file

@ -9,6 +9,7 @@ require.def("ace/Editor",
[
"ace/ace",
"ace/lib/event",
"ace/lib/lang",
"ace/TextInput",
"ace/KeyBinding",
"ace/Document",
@ -16,7 +17,7 @@ require.def("ace/Editor",
"ace/BackgroundTokenizer",
"ace/Range",
"ace/MEventEmitter"
], function(ace, event, TextInput, KeyBinding, Document, Search, BackgroundTokenizer, Range, MEventEmitter) {
], function(ace, event, lang, TextInput, KeyBinding, Document, Search, BackgroundTokenizer, Range, MEventEmitter) {
var Editor = function(renderer, doc) {
var container = renderer.getContainerElement();
@ -344,7 +345,7 @@ var Editor = function(renderer, doc) {
};
this.onMouseWheel = function(e) {
this.renderer.scrollBy(e.wheelX, e.wheelY);
this.renderer.scrollBy(e.wheelX * 2, e.wheelY * 2);
return event.preventDefault(e);
};
@ -524,14 +525,26 @@ var Editor = function(renderer, doc) {
this.clearSelection();
};
this.blockIndent = function(indentString) {
this.indent = function() {
if (this.$readOnly)
return;
var indentString = indentString || this.doc.getTabString();
var addedColumns = this.doc.indentRows(this.getSelectionRange(), indentString);
if (this.selection.isMultiLine()) {
var addedColumns = this.doc.indentRows(this.getSelectionRange(), "\t");
this.selection.shiftSelection(addedColumns);
} else {
if (!this.doc.getUseSoftTabs())
return this.onTextInput("\t");
var cursor = this.doc.remove(this.getSelectionRange());
this.clearSelection();
this.selection.shiftSelection(addedColumns);
// compute indent string
var indentString = lang.stringRepeat(" ", this.doc.getTabSize() - (cursor.column % this.doc.getTabSize()));
var addedColumns = this.doc.indentRows(this.getSelectionRange(), indentString);
cursor.column += addedColumns;
this.moveCursorToPosition(cursor);
}
this.$updateDesiredColumn();
};
@ -539,14 +552,10 @@ var Editor = function(renderer, doc) {
if (this.$readOnly)
return;
var indentString = indentString || this.doc.getTabString();
var addedColumns = this.doc.outdentRows(this.getSelectionRange(), indentString);
// besides the indent string also outdent tabs
if (addedColumns == 0 && indentString != "\t")
var addedColumns = this.doc.outdentRows(this.getSelectionRange(), "\t");
this.selection.shiftSelection(addedColumns);
var selection = this.doc.getSelection(),
range = this.doc.outdentRows(selection.getRange());
selection.setSelectionRange(range, selection.isBackwards());
this.$updateDesiredColumn();
};

View file

@ -170,7 +170,7 @@ Search.SELECTION = 2;
}
var modifier = "g";
if (this.$options.caseSensitive) {
if (!this.$options.caseSensitive) {
modifier += "i";
}

View file

@ -79,7 +79,7 @@ var Selection = function(doc) {
var anchor = this.getSelectionAnchor();
var lead = this.getSelectionLead();
var isBackwards = this.$isBackwards();
var isBackwards = this.isBackwards();
if (!isBackwards || anchor.column !== 0)
this.setSelectionAnchor(anchor.row, anchor.column + columns);
@ -91,7 +91,7 @@ var Selection = function(doc) {
}
};
this.$isBackwards = function() {
this.isBackwards = function() {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
@ -101,7 +101,7 @@ var Selection = function(doc) {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
if (this.$isBackwards()) {
if (this.isBackwards()) {
return Range.fromPoints(lead, anchor);
}
else {
@ -116,7 +116,6 @@ var Selection = function(doc) {
}
};
this.selectAll = function() {
var lastRow = this.doc.getLength() - 1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
@ -126,9 +125,14 @@ var Selection = function(doc) {
});
};
this.setSelectionRange = function(range) {
this.setSelectionAnchor(range.start.row, range.start.column);
this.selectTo(range.end.row, range.end.column);
this.setSelectionRange = function(range, reverse) {
if (reverse) {
this.setSelectionAnchor(range.end.row, range.end.column);
this.selectTo(range.start.row, range.start.column);
} else {
this.setSelectionAnchor(range.start.row, range.start.column);
this.selectTo(range.end.row, range.end.column);
}
};
this.$moveSelection = function(mover) {

View file

@ -71,6 +71,7 @@ var TextInput = function(parentNode, host) {
text.value = host.getCopyText();
text.select();
copied = true;
setTimeout(sendText, 0);
};
var onCut = function() {
@ -78,6 +79,7 @@ var TextInput = function(parentNode, host) {
text.value = host.getCopyText();
host.onCut();
text.select();
setTimeout(sendText, 0);
};
event.addListener(text, "keypress", onTextInput);

View file

@ -151,12 +151,7 @@ PluginManager.registerCommand("outdent", function(editor, selection) {
editor.blockOutdent();
});
PluginManager.registerCommand("indent", function(editor, selection) {
if (selection.isMultiLine()) {
editor.blockIndent();
}
else {
editor.onTextInput("\t");
}
editor.indent();
});
});

View file

@ -16,6 +16,10 @@ require.def("ace/lib/lang", function() {
return string.split("").reverse().join("");
};
lang.stringRepeat = function (string, count) {
return new Array(count + 1).join(string);
}
if (Array.prototype.indexOf) {
lang.arrayIndexOf = function(array, searchElement) {
return array.indexOf(searchElement);

View file

@ -8,40 +8,29 @@
require.def("ace/mode/JavaScriptHighlightRules",
[
"ace/lib/oop",
"ace/lib/lang",
"ace/mode/DocCommentHighlightRules",
"ace/mode/TextHighlightRules"
], function(oop, DocCommentHighlightRules, TextHighlightRules) {
], function(oop, lang, DocCommentHighlightRules, TextHighlightRules) {
JavaScriptHighlightRules = function() {
var docComment = new DocCommentHighlightRules();
var keywords = {
"break" : 1,
"case" : 1,
"catch" : 1,
"continue" : 1,
"default" : 1,
"delete" : 1,
"do" : 1,
"else" : 1,
"finally" : 1,
"for" : 1,
"function" : 1,
"if" : 1,
"in" : 1,
"instanceof" : 1,
"new" : 1,
"return" : 1,
"switch" : 1,
"throw" : 1,
"try" : 1,
"typeof" : 1,
"var" : 1,
"while" : 1,
"with" : 1
};
var keywords = lang.arrayToMap(
("break|case|catch|continue|default|delete|do|else|finally|for|function|" +
"if|in|instanceof|new|return|switch|throw|try|typeof|var|while|with").split("|")
);
var buildinConstants = lang.arrayToMap(
("true|false|null|undefined|Infinity|NaN|undefined").split("|")
);
var futureReserved = lang.arrayToMap(
("class|enum|extends|super|const|export|import|implements|let|private|" +
"public|yield|interface|package|protected|static").split("|")
);
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
@ -80,12 +69,14 @@ JavaScriptHighlightRules = function() {
token : function(value) {
if (value == "this")
return "variable";
if (keywords[value]) {
else if (keywords[value])
return "keyword";
}
else {
else if (buildinConstants[value])
return "buildin-constant";
else if (futureReserved[value] || value == "debugger")
return "invalid";
else
return "identifier";
}
},
regex : "[a-zA-Z_][a-zA-Z0-9_]*\\b"
}, {

View file

@ -0,0 +1,130 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document",
"ace/Editor",
"ace/mode/Text",
"ace/mode/JavaScript",
"ace/test/MockRenderer"
], function(
Document,
Editor,
TextMode,
JavaScriptMode,
MockRenderer
) {
var ChangeDocumentTest = new TestCase("ChangeDocumentTest", {
setUp : function() {
this.doc1 = new Document(["abc", "def"].join("\n"));
this.doc2 = new Document(["ghi", "jkl"].join("\n"));
this.editor = new Editor(new MockRenderer());
},
"test: change document" : function() {
this.editor.setDocument(this.doc1);
assertEquals(this.doc1, this.editor.getDocument());
this.editor.setDocument(this.doc2);
assertEquals(this.doc2, this.editor.getDocument());
},
"test: only changes to the new document should have effect" : function() {
var called = false;
this.editor.onDocumentChange = function() {
called = true;
};
this.editor.setDocument(this.doc1);
this.editor.setDocument(this.doc2);
this.doc1.duplicateLines(0, 0);
assertFalse(called);
this.doc2.duplicateLines(0, 0);
assertTrue(called);
},
"test: should use cursor of new document" : function() {
this.doc1.getSelection().moveCursorTo(0, 1);
this.doc2.getSelection().moveCursorTo(1, 0);
this.editor.setDocument(this.doc1);
assertPosition(0, 1, this.editor.getCursorPosition());
this.editor.setDocument(this.doc2);
assertPosition(1, 0, this.editor.getCursorPosition());
},
"test: only changing the cursor of the new doc should not have an effect" : function() {
this.editor.onCursorChange = function() {
called = true;
};
this.editor.setDocument(this.doc1);
this.editor.setDocument(this.doc2);
assertPosition(0, 0, this.editor.getCursorPosition());
var called = false;
this.doc1.getSelection().moveCursorTo(0, 1);
assertPosition(0, 0, this.editor.getCursorPosition());
assertFalse(called);
this.doc2.getSelection().moveCursorTo(1, 1);
assertPosition(1, 1, this.editor.getCursorPosition());
assertTrue(called);
},
"test: should use selection of new document" : function() {
this.doc1.getSelection().selectTo(0, 1);
this.doc2.getSelection().selectTo(1, 0);
this.editor.setDocument(this.doc1);
assertPosition(0, 1, this.editor.getSelection().getSelectionLead());
this.editor.setDocument(this.doc2);
assertPosition(1, 0, this.editor.getSelection().getSelectionLead());
},
"test: only changing the selection of the new doc should not have an effect" : function() {
this.editor.onSelectionChange = function() {
called = true;
};
this.editor.setDocument(this.doc1);
this.editor.setDocument(this.doc2);
assertPosition(0, 0, this.editor.getSelection().getSelectionLead());
var called = false;
this.doc1.getSelection().selectTo(0, 1);
assertPosition(0, 0, this.editor.getSelection().getSelectionLead());
assertFalse(called);
this.doc2.getSelection().selectTo(1, 1);
assertPosition(1, 1, this.editor.getSelection().getSelectionLead());
assertTrue(called);
},
"test: should use mode of new document" : function() {
this.editor.onDocumentModeChange = function() {
called = true;
};
this.editor.setDocument(this.doc1);
this.editor.setDocument(this.doc2);
var called = false;
this.doc1.setMode(new Text());
assertFalse(called);
this.doc2.setMode(new JavaScriptMode());
assertTrue(called);
}
});
});

View file

@ -0,0 +1,234 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document",
"ace/UndoManager",
"ace/Editor",
"ace/test/MockRenderer"
], function(
Document,
UndoManager,
Editor,
MockRenderer
) {
var TextDocumentTest = new TestCase("TextDocumentTest", {
"test: find matching opening bracket" : function() {
var doc = new Document(["(()(", "())))"]);
assertPosition(0, 1, doc.findMatchingBracket({row: 0, column: 3}));
assertPosition(1, 0, doc.findMatchingBracket({row: 1, column: 2}));
assertPosition(0, 3, doc.findMatchingBracket({row: 1, column: 3}));
assertPosition(0, 0, doc.findMatchingBracket({row: 1, column: 4}));
assertEquals(null, doc.findMatchingBracket({row: 1, column: 5}));
},
"test: find matching closing bracket" : function() {
var doc = new Document(["(()(", "())))"]);
assertPosition(1, 1, doc.findMatchingBracket({row: 1, column: 1}));
assertPosition(1, 1, doc.findMatchingBracket({row: 1, column: 1}));
assertPosition(1, 2, doc.findMatchingBracket({row: 0, column: 4}));
assertPosition(0, 2, doc.findMatchingBracket({row: 0, column: 2}));
assertPosition(1, 3, doc.findMatchingBracket({row: 0, column: 1}));
assertEquals(null, doc.findMatchingBracket({row: 0, column: 0}));
},
"test: match different bracket types" : function() {
var doc = new Document(["({[", ")]}"]);
assertPosition(1, 0, doc.findMatchingBracket({row: 0, column: 1}));
assertPosition(1, 2, doc.findMatchingBracket({row: 0, column: 2}));
assertPosition(1, 1, doc.findMatchingBracket({row: 0, column: 3}));
assertPosition(0, 0, doc.findMatchingBracket({row: 1, column: 1}));
assertPosition(0, 2, doc.findMatchingBracket({row: 1, column: 2}));
assertPosition(0, 1, doc.findMatchingBracket({row: 1, column: 3}));
},
"test: move lines down" : function() {
var doc = new Document(["1", "2", "3", "4"]);
doc.moveLinesDown(0, 1);
assertEquals(["3", "1", "2", "4"].join("\n"), doc.toString());
doc.moveLinesDown(1, 2);
assertEquals(["3", "4", "1", "2"].join("\n"), doc.toString());
doc.moveLinesDown(2, 3);
assertEquals(["3", "4", "1", "2"].join("\n"), doc.toString());
doc.moveLinesDown(2, 2);
assertEquals(["3", "4", "2", "1"].join("\n"), doc.toString());
},
"test: move lines up" : function() {
var doc = new Document(["1", "2", "3", "4"]);
doc.moveLinesUp(2, 3);
assertEquals(["1", "3", "4", "2"].join("\n"), doc.toString());
doc.moveLinesUp(1, 2);
assertEquals(["3", "4", "1", "2"].join("\n"), doc.toString());
doc.moveLinesUp(0, 1);
assertEquals(["3", "4", "1", "2"].join("\n"), doc.toString());
doc.moveLinesUp(2, 2);
assertEquals(["3", "1", "4", "2"].join("\n"), doc.toString());
},
"test: duplicate lines" : function() {
var doc = new Document(["1", "2", "3", "4"]);
doc.duplicateLines(1, 2);
assertEquals(["1", "2", "3", "2", "3", "4"].join("\n"), doc.toString());
},
"test: duplicate last line" : function() {
var doc = new Document(["1", "2", "3"]);
doc.duplicateLines(2, 2);
assertEquals(["1", "2", "3", "3"].join("\n"), doc.toString());
},
"test: duplicate first line" : function() {
var doc = new Document(["1", "2", "3"]);
doc.duplicateLines(0, 0);
assertEquals(["1", "1", "2", "3"].join("\n"), doc.toString());
},
"test: should handle unix style new lines" : function() {
var doc = new Document(["1", "2", "3"]);
assertEquals(["1", "2", "3"].join("\n"), doc.toString());
},
"test: should handle windows style new lines" : function() {
var doc = new Document(["1", "2", "3"].join("\r\n"));
doc.setNewLineMode("unix");
assertEquals(["1", "2", "3"].join("\n"), doc.toString());
},
"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");
assertEquals(["1", "2", "3"].join("\r\n"), doc.toString());
},
"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");
assertEquals(["1", "2", "3"].join("\n"), doc.toString());
},
"test: set new line mode to 'auto' should use detect the incoming nl type": function() {
var doc = new Document(["1", "2", "3"].join("\n"));
doc.setNewLineMode("auto");
assertEquals(["1", "2", "3"].join("\n"), doc.toString());
var doc = new Document(["1", "2", "3"].join("\r\n"));
doc.setNewLineMode("auto");
assertEquals(["1", "2", "3"].join("\r\n"), doc.toString());
doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n"));
assertEquals(["4", "5", "6"].join("\n"), doc.toString());
},
"test: undo/redo for delete line" : function() {
var doc = new Document(["111", "222", "333"]);
var undoManager = new UndoManager();
doc.setUndoManager(undoManager);
var initialText = doc.toString();
var editor = new Editor(new MockRenderer(), doc);
editor.removeLines();
var step1 = doc.toString();
assertEquals("222\n333", step1);
doc.$informUndoManager.call();
editor.removeLines();
var step2 = doc.toString();
assertEquals("333", step2);
doc.$informUndoManager.call();
editor.removeLines();
var step3 = doc.toString();
assertEquals("", step3);
doc.$informUndoManager.call();
undoManager.undo();
doc.$informUndoManager.call();
assertEquals(step2, doc.toString());
undoManager.undo();
doc.$informUndoManager.call();
assertEquals(step1, doc.toString());
undoManager.undo();
doc.$informUndoManager.call();
assertEquals(initialText, doc.toString());
undoManager.undo();
doc.$informUndoManager.call();
assertEquals(initialText, doc.toString());
},
"test: convert document to screen coordinates" : function() {
var doc = new Document("01234\t567890\t1234");
doc.setTabSize(4);
assertEquals(0, doc.documentToScreenColumn(0, 0));
assertEquals(4, doc.documentToScreenColumn(0, 4));
assertEquals(5, doc.documentToScreenColumn(0, 5));
assertEquals(9, doc.documentToScreenColumn(0, 6));
assertEquals(15, doc.documentToScreenColumn(0, 12));
assertEquals(19, doc.documentToScreenColumn(0, 13));
doc.setTabSize(2);
assertEquals(0, doc.documentToScreenColumn(0, 0));
assertEquals(4, doc.documentToScreenColumn(0, 4));
assertEquals(5, doc.documentToScreenColumn(0, 5));
assertEquals(7, doc.documentToScreenColumn(0, 6));
assertEquals(13, doc.documentToScreenColumn(0, 12));
assertEquals(15, doc.documentToScreenColumn(0, 13));
},
"test: convert document to scrren coordinates with leading tabs": function() {
var doc = new Document("\t\t123");
doc.setTabSize(4);
assertEquals(0, doc.documentToScreenColumn(0, 0));
assertEquals(4, doc.documentToScreenColumn(0, 1));
assertEquals(8, doc.documentToScreenColumn(0, 2));
assertEquals(9, doc.documentToScreenColumn(0, 3));
},
"test: convert screen to document coordinates" : function() {
var doc = new Document("01234\t567890\t1234");
doc.setTabSize(4);
assertEquals(0, doc.screenToDocumentColumn(0, 0));
assertEquals(4, doc.screenToDocumentColumn(0, 4));
assertEquals(5, doc.screenToDocumentColumn(0, 5));
assertEquals(5, doc.screenToDocumentColumn(0, 6));
assertEquals(5, doc.screenToDocumentColumn(0, 7));
assertEquals(5, doc.screenToDocumentColumn(0, 8));
assertEquals(6, doc.screenToDocumentColumn(0, 9));
assertEquals(12, doc.screenToDocumentColumn(0, 15));
assertEquals(13, doc.screenToDocumentColumn(0, 19));
}
});
});

View file

@ -0,0 +1,36 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/lib/oop",
"ace/MEventEmitter"
], function(
oop,
MEventEmitter
) {
var EventEmitter = function() {};
oop.implement(EventEmitter.prototype, MEventEmitter);
var EventEmitterTest = new TestCase("EventEmitterTest", {
"test: dispatch event with no data" : function() {
var emitter = new EventEmitter();
var called = false;
emitter.addEventListener("juhu", function(e) {
called = true;
assertEquals("juhu", e.type);
});
emitter.$dispatchEvent("juhu");
assertTrue(called);
}
});
});

View file

@ -0,0 +1,88 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([], function() {
MockRenderer = function(visibleRowCount) {
this.container = document.createElement("div");
this.cursor = {
row : 0,
column : 0
};
this.visibleRowCount = visibleRowCount || 20;
this.layerConfig = {
firstVisibleRow : 0,
lastVisibleRow : this.visibleRowCount
};
};
MockRenderer.prototype.getFirstVisibleRow = function() {
return this.layerConfig.firstVisibleRow;
};
MockRenderer.prototype.getLastVisibleRow = function() {
return this.layerConfig.lastVisibleRow;
};
MockRenderer.prototype.getContainerElement = function() {
return this.container;
};
MockRenderer.prototype.getMouseEventTarget = function() {
return this.container;
};
MockRenderer.prototype.setDocument = function(doc) {
this.lines = doc.lines;
};
MockRenderer.prototype.setTokenizer = function() {
};
MockRenderer.prototype.updateCursor = function(position) {
this.cursor.row = position.row;
this.cursor.column = position.column;
};
MockRenderer.prototype.scrollCursorIntoView = function() {
if (this.cursor.row < this.layerConfig.firstVisibleRow) {
this.scrollToRow(this.cursor.row);
}
else if (this.cursor.row > this.layerConfig.lastVisibleRow) {
this.scrollToRow(this.cursor.row);
}
};
MockRenderer.prototype.scrollToRow = function(row) {
var row = Math.min(this.lines.length - this.visibleRowCount, Math.max(0,
row));
this.layerConfig.firstVisibleRow = row;
this.layerConfig.lastVisibleRow = row + this.visibleRowCount;
};
MockRenderer.prototype.getScrollTopRow = function() {
return this.layerConfig.firstVisibleRow;
};
MockRenderer.prototype.draw = function() {
};
MockRenderer.prototype.updateLines = function(startRow, endRow) {
};
MockRenderer.prototype.addMarker = function() {
};
MockRenderer.prototype.setBreakpoints = function() {
};
return MockRenderer;
});

View file

@ -0,0 +1,126 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document",
"ace/Editor",
"ace/test/MockRenderer"
], function(
Document,
Editor,
MockRenderer
) {
var NavigationTest = TestCase("NavigationTest",
{
createTextDocument : function(rows, cols) {
var line = new Array(cols + 1).join("a");
var text = new Array(rows).join(line + "\n") + line;
return new Document(text);
},
"test: navigate to end of file should scroll the last line into view" : function() {
var doc = this.createTextDocument(200, 10);
var editor = new Editor(new MockRenderer(), doc);
editor.navigateFileEnd();
var cursor = editor.getCursorPosition();
assertTrue(editor.getFirstVisibleRow() <= cursor.row);
assertTrue(editor.getLastVisibleRow() >= cursor.row);
},
"test: navigate to start of file should scroll the first row into view" : function() {
var doc = this.createTextDocument(200, 10);
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(editor.getLastVisibleRow() + 20);
editor.navigateFileStart();
assertEquals(0, editor.getFirstVisibleRow());
},
"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));
editor.navigateTo(0, 0);
editor.gotoLine(101);
assertPosition(100, 0, editor.getCursorPosition());
assertEquals(90, editor.getFirstVisibleRow());
editor.navigateTo(100, 0);
editor.gotoLine(11);
assertPosition(10, 0, editor.getCursorPosition());
assertEquals(0, editor.getFirstVisibleRow());
editor.navigateTo(100, 0);
editor.gotoLine(6);
assertPosition(5, 0, editor.getCursorPosition());
assertEquals(0, editor.getFirstVisibleRow());
editor.navigateTo(100, 0);
editor.gotoLine(1);
assertPosition(0, 0, editor.getCursorPosition());
assertEquals(0, editor.getFirstVisibleRow());
editor.navigateTo(0, 0);
editor.gotoLine(191);
assertPosition(190, 0, editor.getCursorPosition());
assertEquals(180, editor.getFirstVisibleRow());
editor.navigateTo(0, 0);
editor.gotoLine(196);
assertPosition(195, 0, editor.getCursorPosition());
assertEquals(180, editor.getFirstVisibleRow());
},
"test: goto visible line should only move the cursor and not scroll": function() {
var editor = new Editor(new MockRenderer(), this.createTextDocument(200, 5));
editor.navigateTo(0, 0);
editor.gotoLine(12);
assertPosition(11, 0, editor.getCursorPosition());
assertEquals(0, editor.getFirstVisibleRow());
editor.navigateTo(30, 0);
editor.gotoLine(33);
assertPosition(32, 0, editor.getCursorPosition());
assertEquals(30, editor.getFirstVisibleRow());
},
"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"]));
editor.navigateTo(0, 6);
assertPosition(0, 6, editor.getCursorPosition());
editor.navigateDown();
assertPosition(1, 1, editor.getCursorPosition());
editor.navigateUp();
assertPosition(0, 6, editor.getCursorPosition());
},
"test: reset desired column on navigate left or right": function() {
var editor = new Editor(new MockRenderer(), new Document(["123456", "12"]));
editor.navigateTo(0, 6);
assertPosition(0, 6, editor.getCursorPosition());
editor.navigateDown();
assertPosition(1, 2, editor.getCursorPosition());
editor.navigateLeft();
assertPosition(1, 1, editor.getCursorPosition());
editor.navigateUp();
assertPosition(0, 1, editor.getCursorPosition());
}
});
});

123
src/ace/test/RangeTest.js Normal file
View file

@ -0,0 +1,123 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Range"
], function(
Range
) {
RangeTest = new TestCase("RangeTest", {
"test: create range": function() {
var range = new Range(1,2,3,4);
assertEquals(1, range.start.row);
assertEquals(2, range.start.column);
assertEquals(3, range.end.row);
assertEquals(4, range.end.column);
},
"test: create from points": function() {
var range = Range.fromPoints({row: 1, column: 2}, {row:3, column:4});
assertEquals(1, range.start.row);
assertEquals(2, range.start.column);
assertEquals(3, range.end.row);
assertEquals(4, range.end.column);
},
"test: clip to rows": function() {
assertRange(10, 0, 31, 0, new Range(0, 20, 100, 30).clipRows(10, 30));
assertRange(10, 0, 30, 10, new Range(0, 20, 30, 10).clipRows(10, 30));
var range = new Range(0, 20, 3, 10);
var range = range.clipRows(10, 30);
assertTrue(range.isEmpty());
assertRange(10, 0, 10, 0, range);
},
"test: isEmpty": function() {
var range = new Range(1, 2, 1, 2);
assertTrue(range.isEmpty());
var range = new Range(1, 2, 1, 6);
assertFalse(range.isEmpty());
},
"test: is multi line": function() {
var range = new Range(1, 2, 1, 6);
assertFalse(range.isMultiLine());
var range = new Range(1, 2, 2, 6);
assertTrue(range.isMultiLine());
},
"test: clone": function() {
var range = new Range(1, 2, 3, 4);
var clone = range.clone();
assertPosition(1, 2, clone.start);
assertPosition(3, 4, clone.end);
clone.start.column = 20;
assertPosition(1, 2, range.start);
clone.end.column = 20;
assertPosition(3, 4, range.end);
},
"test: contains for multi line ranges": function() {
var range = new Range(1, 10, 5, 20);
assertTrue(range.contains(1, 10));
assertTrue(range.contains(2, 0));
assertTrue(range.contains(3, 100));
assertTrue(range.contains(5, 19));
assertTrue(range.contains(5, 20));
assertFalse(range.contains(1, 9));
assertFalse(range.contains(0, 0));
assertFalse(range.contains(5, 21));
},
"test: contains for single line ranges": function() {
var range = new Range(1, 10, 1, 20);
assertTrue(range.contains(1, 10));
assertTrue(range.contains(1, 15));
assertTrue(range.contains(1, 20));
assertFalse(range.contains(0, 9));
assertFalse(range.contains(2, 9));
assertFalse(range.contains(1, 9));
assertFalse(range.contains(1, 21));
},
"test: extend range": function() {
var range = new Range(2, 10, 2, 30);
var range = range.extend(2, 5);
assertRange(2, 5, 2, 30, range);
var range = range.extend(2, 35);
assertRange(2, 5, 2, 35, range);
var range = range.extend(2, 15);
assertRange(2, 5, 2, 35, range);
var range = range.extend(1, 4);
assertRange(1, 4, 2, 35, range);
var range = range.extend(6, 10);
assertRange(1, 4, 6, 10, range);
}
});
});

322
src/ace/test/SearchTest.js Normal file
View file

@ -0,0 +1,322 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document",
"ace/Search"
], function(
Document,
Search
) {
var SearchTest = new TestCase("SearchTest", {
"test: configure the search object" : function() {
var search = new Search();
search.set({
needle: "juhu",
scope: Search.ALL
});
},
"test: find simple text in document" : function() {
var doc = new Document(["juhu kinners 123", "456"]);
var search = new Search().set({
needle: "kinners"
});
var range = search.find(doc);
assertPosition(0, 5, range.start);
assertPosition(0, 12, range.end);
},
"test: find simple text in next line" : function() {
var doc = new Document(["abc", "juhu kinners 123", "456"]);
var search = new Search().set({
needle: "kinners"
});
var range = search.find(doc);
assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end);
},
"test: find text starting at cursor position" : function() {
var doc = new Document(["juhu kinners", "juhu kinners 123"]);
doc.getSelection().moveCursorTo(0, 6);
var search = new Search().set({
needle: "kinners"
});
var range = search.find(doc);
assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end);
},
"test: wrap search is off by default" : function() {
var doc = new Document(["abc", "juhu kinners 123", "456"]);
doc.getSelection().moveCursorTo(2, 1);
var search = new Search().set({
needle: "kinners"
});
assertEquals(null, search.find(doc));
},
"test: wrap search should wrap at file end" : function() {
var doc = new Document(["abc", "juhu kinners 123", "456"]);
doc.getSelection().moveCursorTo(2, 1);
var search = new Search().set({
needle: "kinners",
wrap: true
});
var range = search.find(doc);
assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end);
},
"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 search = new Search().set({
needle: "xyz",
wrap: true
});
assertEquals(null, search.find(doc));
},
"test: case sensitive is by default off": function() {
var doc = new Document(["abc", "juhu kinners 123", "456"]);
var search = new Search().set({
needle: "JUHU"
});
assertEquals(null, search.find(doc));
},
"test: case sensitive search": function() {
var doc = new Document(["abc", "juhu kinners 123", "456"]);
var search = new Search().set({
needle: "KINNERS",
caseSensitive: true
});
var range = search.find(doc);
assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end);
},
"test: whole word search should not match inside of words": function() {
var doc = new Document(["juhukinners", "juhu kinners 123", "456"]);
var search = new Search().set({
needle: "kinners",
wholeWord: true
});
var range = search.find(doc);
assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end);
},
"test: find backwards": function() {
var doc = new Document(["juhu juhu juhu juhu"]);
doc.getSelection().moveCursorTo(0, 10);
var search = new Search().set({
needle: "juhu",
backwards: true
});
var range = search.find(doc);
assertPosition(0, 5, range.start);
assertPosition(0, 9, range.end);
},
"test: find in selection": function() {
var doc = new Document(["juhu", "juhu", "juhu", "juhu"]);
doc.getSelection().setSelectionAnchor(1, 0);
doc.getSelection().selectTo(3, 5);
var search = new Search().set({
needle: "juhu",
wrap: true,
scope: Search.SELECTION
});
var range = search.find(doc);
assertPosition(1, 0, range.start);
assertPosition(1, 4, range.end);
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(3, 2);
var range = search.find(doc);
assertPosition(1, 0, range.start);
assertPosition(1, 4, range.end);
},
"test: find backwards in selection": function() {
var doc = new Document(["juhu", "juhu", "juhu", "juhu"]);
var search = new Search().set({
needle: "juhu",
wrap: true,
backwards: true,
scope: Search.SELECTION
});
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(3, 2);
var range = search.find(doc);
assertPosition(2, 0, range.start);
assertPosition(2, 4, range.end);
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(1, 2);
assertEquals(null, search.find(doc));
},
"test: edge case - match directly before the cursor" : function() {
var doc = new Document(["123", "123", "juhu"]);
var search = new Search().set({
needle: "juhu",
wrap: true
});
doc.getSelection().moveCursorTo(2, 5);
var range = search.find(doc);
assertPosition(2, 0, range.start);
assertPosition(2, 4, range.end);
},
"test: edge case - match backwards directly after the cursor" : function() {
var doc = new Document(["123", "123", "juhu"]);
var search = new Search().set({
needle: "juhu",
wrap: true,
backwards: true
});
doc.getSelection().moveCursorTo(2, 0);
var range = search.find(doc);
assertPosition(2, 0, range.start);
assertPosition(2, 4, range.end);
},
"test: find using a regular expression" : function() {
var doc = new Document(["abc123 123 cd", "abc"]);
var search = new Search().set({
needle: "\\d+",
regExp: true
});
var range = search.find(doc);
assertPosition(0, 3, range.start);
assertPosition(0, 6, range.end);
},
"test: find using a regular expression and whole word" : function() {
var doc = new Document(["abc123 123 cd", "abc"]);
var search = new Search().set({
needle: "\\d+\\b",
regExp: true,
wholeWord: true
});
var range = search.find(doc);
assertPosition(0, 7, range.start);
assertPosition(0, 10, range.end);
},
"test: use regular expressions with capture groups": function() {
var doc = new Document([" ab: 12px", " <h1 abc"]);
var search = new Search().set({
needle: "(\\d+)",
regExp: true
});
var range = search.find(doc);
assertPosition(0, 6, range.start);
assertPosition(0, 8, range.end);
},
"test: find all matches in selection" : function() {
var doc = new Document(["juhu", "juhu", "juhu", "juhu"]);
var search = new Search().set({
needle: "uh",
wrap: true,
scope: Search.SELECTION
});
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(3, 2);
var ranges = search.findAll(doc);
assertEquals(2, ranges.length);
assertPosition(1, 1, ranges[0].start);
assertPosition(1, 3, ranges[0].end);
assertPosition(2, 1, ranges[1].start);
assertPosition(2, 3, ranges[1].end);
},
"test: replace() should return the replacement if the input matches the needle" : function() {
var search = new Search().set({
needle: "juhu"
});
assertEquals("kinners", search.replace("juhu", "kinners"));
assertEquals(null, search.replace("", "kinners"));
assertEquals(null, search.replace(" juhu", "kinners"));
// regexp replacement
},
"test: replace with a RegExp search" : function() {
var search = new Search().set({
needle: "\\d+",
regExp: true
});
assertEquals("kinners", search.replace("123", "kinners"));
assertEquals("kinners", search.replace("01234", "kinners"));
assertEquals(null, search.replace("", "kinners"));
assertEquals(null, search.replace("a12", "kinners"));
assertEquals(null, search.replace("12a", "kinners"));
},
"test: replace with RegExp match and capture groups" : function() {
var search = new Search().set({
needle: "ab(\\d\\d)",
regExp: true
});
assertEquals("cd12", search.replace("ab12", "cd$1"));
assertEquals("-ab12-", search.replace("ab12", "-$&-"));
assertEquals("$", search.replace("ab12", "$$"));
}
});
});

View file

@ -0,0 +1,266 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document"
], function(
Document
) {
var SelectionTest = TestCase("SelectionTest",
{
createTextDocument : function(rows, cols) {
var line = new Array(cols + 1).join("a");
var text = new Array(rows).join(line + "\n") + line;
return new Document(text);
},
"test: move cursor to end of file should place the cursor on last row and column" : function() {
var doc = this.createTextDocument(200, 10);
var selection = doc.getSelection();
selection.moveCursorFileEnd();
assertPosition(199, 10, selection.getCursor());
},
"test: moveCursor to start of file should place the cursor on the first row and column" : function() {
var doc = this.createTextDocument(200, 10);
var selection = doc.getSelection();
selection.moveCursorFileStart();
assertPosition(0, 0, selection.getCursor());
},
"test: move selection lead to end of file" : function() {
var doc = this.createTextDocument(200, 10);
var selection = doc.getSelection();
selection.moveCursorTo(100, 5);
selection.selectFileEnd();
var range = selection.getRange();
assertPosition(100, 5, range.start);
assertPosition(199, 10, range.end);
},
"test: move selection lead to start of file" : function() {
var doc = this.createTextDocument(200, 10);
var selection = doc.getSelection();
selection.moveCursorTo(100, 5);
selection.selectFileStart();
var range = selection.getRange();
assertPosition(0, 0, range.start);
assertPosition(100, 5, range.end);
},
"test: move cursor word right" : function() {
var doc = new Document( ["ab",
" Juhu Kinners (abc, 12)", " cde"].join("\n"));
var selection = doc.getSelection();
selection.moveCursorDown();
assertPosition(1, 0, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 1, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 5, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 6, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 13, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 15, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 18, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 20, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 22, selection.getCursor());
selection.moveCursorWordRight();
assertPosition(1, 23, selection.getCursor());
// wrap line
selection.moveCursorWordRight();
assertPosition(2, 0, selection.getCursor());
},
"test: select word right if cursor in word" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 2);
selection.moveCursorWordRight();
assertPosition(0, 4, selection.getCursor());
},
"test: moveCursor word left" : function() {
var doc = new Document( ["ab",
" Juhu Kinners (abc, 12)", " cde"].join("\n"));
var selection = doc.getSelection();
selection.moveCursorDown();
selection.moveCursorLineEnd();
assertPosition(1, 23, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 22, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 20, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 18, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 15, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 13, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 6, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 5, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 1, selection.getCursor());
selection.moveCursorWordLeft();
assertPosition(1, 0, selection.getCursor());
// wrap line
selection.moveCursorWordLeft();
assertPosition(0, 2, selection.getCursor());
},
"test: select word left if cursor in word" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 8);
selection.moveCursorWordLeft();
assertPosition(0, 5, selection.getCursor());
},
"test: select word right and select" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 0);
selection.selectWordRight();
var range = selection.getRange();
assertPosition(0, 0, range.start);
assertPosition(0, 4, range.end);
},
"test: select word left and select" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 3);
selection.selectWordLeft();
var range = selection.getRange();
assertPosition(0, 0, range.start);
assertPosition(0, 3, range.end);
},
"test: select word with cursor in word should select the word" : function() {
var doc = new Document("Juhu Kinners 123");
var selection = doc.getSelection();
selection.moveCursorTo(0, 8);
selection.selectWord();
var range = selection.getRange();
assertPosition(0, 5, range.start);
assertPosition(0, 12, range.end);
},
"test: select word with cursor betwen white space and word should select the word" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 4);
selection.selectWord();
var range = selection.getRange();
assertPosition(0, 0, range.start);
assertPosition(0, 4, range.end);
selection.moveCursorTo(0, 5);
selection.selectWord();
var range = selection.getRange();
assertPosition(0, 5, range.start);
assertPosition(0, 12, range.end);
},
"test: select word with cursor in white space should select white space" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 5);
selection.selectWord();
var range = selection.getRange();
assertPosition(0, 4, range.start);
assertPosition(0, 6, range.end);
},
"test: moving cursor should fire a 'changeCursor' event" : function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 5);
var called = false;
selection.addEventListener("changeCursor", function() {
called = true;
});
selection.moveCursorTo(0, 6);
assertTrue(called);
},
"test: calling setCursor with the same position should not fire an event": function() {
var doc = new Document("Juhu Kinners");
var selection = doc.getSelection();
selection.moveCursorTo(0, 5);
var called = false;
selection.addEventListener("changeCursor", function() {
called = true;
});
selection.moveCursorTo(0, 5);
assertFalse(called);
}
});
});

View file

@ -0,0 +1,315 @@
/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def([
"ace/Document",
"ace/Editor",
"ace/mode/JavaScript",
"ace/test/MockRenderer"
], function(
Document,
Editor,
JavaScriptMode,
MockRenderer
) {
var TextEditTest = TestCase("TextEditTest",
{
"test: delete line from the middle" : function() {
var doc = new Document(["a", "b", "c", "d"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 1);
editor.removeLines();
assertEquals("a\nc\nd", doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
editor.removeLines();
assertEquals("a\nd", doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
editor.removeLines();
assertEquals("a\n", doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
editor.removeLines();
assertEquals("a\n", doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
},
"test: delete multiple selected lines" : function() {
var doc = new Document(["a", "b", "c", "d"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 1);
editor.getSelection().selectDown();
editor.removeLines();
assertEquals("a\nd", doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
},
"test: delete first line" : function() {
var doc = new Document(["a", "b", "c"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.removeLines();
assertEquals("b\nc", doc.toString());
assertPosition(0, 0, editor.getCursorPosition());
},
"test: delete last" : function() {
var doc = new Document(["a", "b", "c"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(2, 1);
editor.removeLines();
assertEquals("a\nb\n", doc.toString());
assertPosition(2, 0, editor.getCursorPosition());
},
"test: indent block" : function() {
var doc = new Document(["a12345", "b12345", "c12345"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 3);
editor.getSelection().selectDown();
editor.blockIndent(" ");
assertEquals(["a12345", " b12345", " c12345"].join("\n"),
doc.toString());
assertPosition(2, 7, editor.getCursorPosition());
var range = editor.getSelectionRange();
assertPosition(1, 7, range.start);
assertPosition(2, 7, range.end);
},
"test: outdent block" : function() {
var doc = new Document([" a12345", " b12345", " c12345"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 3);
editor.getSelection().selectDown();
editor.getSelection().selectDown();
editor.blockOutdent(" ");
assertEquals([" a12345", "b12345", " c12345"].join("\n"),
doc.toString());
assertPosition(2, 1, editor.getCursorPosition());
var range = editor.getSelectionRange();
assertPosition(0, 1, range.start);
assertPosition(2, 1, range.end);
editor.blockOutdent(" ");
assertEquals([" a12345", "b12345", " c12345"].join("\n"),
doc.toString());
var range = editor.getSelectionRange();
assertPosition(0, 1, range.start);
assertPosition(2, 1, range.end);
},
"test: outent without a selection should update cursor" : function() {
var doc = new Document(" 12");
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 3);
editor.blockOutdent(" ");
assertEquals(" 12", doc.toString());
assertPosition(0, 1, editor.getCursorPosition());
},
"test: comment lines should perserve selection" : function() {
var doc = new Document([" abc", "cde"].join("\n"), new JavaScriptMode());
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 2);
editor.getSelection().selectDown();
editor.toggleCommentLines();
assertEquals(["// abc", "//cde"].join("\n"), doc.toString());
var selection = editor.getSelectionRange();
assertPosition(0, 4, selection.start);
assertPosition(1, 4, selection.end);
},
"test: uncomment lines should perserve selection" : function() {
var doc = new Document(["// abc", "//cde"].join("\n"), new JavaScriptMode());
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 1);
editor.getSelection().selectDown();
editor.getSelection().selectRight();
editor.getSelection().selectRight();
editor.toggleCommentLines();
assertEquals([" abc", "cde"].join("\n"), doc.toString());
assertRange(0, 0, 1, 1, editor.getSelectionRange());
},
"test: comment lines - if the selection end is at the line start it should stay there": function() {
//select down
var doc = new Document(["abc", "cde"].join("\n"), new JavaScriptMode());
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 0);
editor.getSelection().selectDown();
editor.toggleCommentLines();
assertRange(0, 2, 1, 0, editor.getSelectionRange());
// select up
var doc = new Document(["abc", "cde"].join("\n"), new JavaScriptMode());
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 0);
editor.getSelection().selectUp();
editor.toggleCommentLines();
assertRange(0, 2, 1, 0, editor.getSelectionRange());
},
"test: move lines down should select moved lines" : function() {
var doc = new Document(["11", "22", "33", "44"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(0, 1);
editor.getSelection().selectDown();
editor.moveLinesDown();
assertEquals(["33", "11", "22", "44"].join("\n"), doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
assertPosition(3, 0, editor.getSelection().getSelectionAnchor());
assertPosition(1, 0, editor.getSelection().getSelectionLead());
editor.moveLinesDown();
assertEquals(["33", "44", "11", "22"].join("\n"), doc.toString());
assertPosition(2, 0, editor.getCursorPosition());
assertPosition(3, 2, editor.getSelection().getSelectionAnchor());
assertPosition(2, 0, editor.getSelection().getSelectionLead());
// moving again should have no effect
editor.moveLinesDown();
assertEquals(["33", "44", "11", "22"].join("\n"), doc.toString());
assertPosition(2, 0, editor.getCursorPosition());
assertPosition(3, 2, editor.getSelection().getSelectionAnchor());
assertPosition(2, 0, editor.getSelection().getSelectionLead());
},
"test: move lines up should select moved lines" : function() {
var doc = new Document(["11", "22", "33", "44"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(2, 1);
editor.getSelection().selectDown();
editor.moveLinesUp();
assertEquals(["11", "33", "44", "22"].join("\n"), doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
assertPosition(3, 0, editor.getSelection().getSelectionAnchor());
assertPosition(1, 0, editor.getSelection().getSelectionLead());
editor.moveLinesUp();
assertEquals(["33", "44", "11", "22"].join("\n"), doc.toString());
assertPosition(0, 0, editor.getCursorPosition());
assertPosition(2, 0, editor.getSelection().getSelectionAnchor());
assertPosition(0, 0, editor.getSelection().getSelectionLead());
},
"test: move line without active selection should move cursor to start of the moved line" : function()
{
var doc = new Document(["11", "22", "33", "44"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 1);
editor.clearSelection();
editor.moveLinesDown();
assertEquals(["11", "33", "22", "44"].join("\n"), doc.toString());
assertPosition(2, 0, editor.getCursorPosition());
editor.clearSelection();
editor.moveLinesUp();
assertEquals(["11", "22", "33", "44"].join("\n"), doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
},
"test: copy lines down should select lines and place cursor at the selection start" : function() {
var doc = new Document(["11", "22", "33", "44"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 1);
editor.getSelection().selectDown();
editor.copyLinesDown();
assertEquals(["11", "22", "33", "22", "33", "44"].join("\n"), doc.toString());
assertPosition(3, 0, editor.getCursorPosition());
assertPosition(5, 0, editor.getSelection().getSelectionAnchor());
assertPosition(3, 0, editor.getSelection().getSelectionLead());
},
"test: copy lines up should select lines and place cursor at the selection start" : function() {
var doc = new Document(["11", "22", "33", "44"].join("\n"));
var editor = new Editor(new MockRenderer(), doc);
editor.moveCursorTo(1, 1);
editor.getSelection().selectDown();
editor.copyLinesUp();
assertEquals(["11", "22", "33", "22", "33", "44"].join("\n"), doc.toString());
assertPosition(1, 0, editor.getCursorPosition());
assertPosition(3, 0, editor.getSelection().getSelectionAnchor());
assertPosition(1, 0, editor.getSelection().getSelectionLead());
},
"test: input a tab with soft tab should convert it to spaces" : function() {
var doc = new Document("");
var editor = new Editor(new MockRenderer(), doc);
doc.setTabSize(2);
doc.setUseSoftTabs(true);
editor.onTextInput("\t");
assertEquals(" ", doc.toString());
doc.setTabSize(5);
editor.onTextInput("\t");
assertEquals(" ", doc.toString());
},
"test: input tab without soft tabs should keep the tab character" : function() {
var doc = new Document("");
var editor = new Editor(new MockRenderer(), doc);
doc.setUseSoftTabs(false);
editor.onTextInput("\t");
assertEquals("\t", doc.toString());
}
});
});

Some files were not shown because too many files have changed in this diff Show more