merge from ajaxorg/master
This commit is contained in:
commit
1e984d5733
243 changed files with 63871 additions and 4746 deletions
79
lib/ace/ace.js
Normal file
79
lib/ace/ace.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* ***** 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 Mozilla Skywriter.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kevin Dangoor (kdangoor@mozilla.com)
|
||||
*
|
||||
* 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 catalog = require("pilot/plugin_manager").catalog;
|
||||
require("pilot/index");
|
||||
catalog.registerPlugins([ "pilot/index" ]);
|
||||
|
||||
var Dom = require("pilot/dom");
|
||||
var Event = require("pilot/event");
|
||||
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var UndoManager = require("ace/undomanager").UndoManager;
|
||||
var Renderer = require("ace/virtual_renderer").VirtualRenderer;
|
||||
|
||||
exports.edit = function(el) {
|
||||
if (typeof(el) == "string") {
|
||||
el = document.getElementById(el);
|
||||
}
|
||||
|
||||
var doc = new EditSession(Dom.getInnerText(el));
|
||||
doc.setUndoManager(new UndoManager());
|
||||
el.innerHTML = '';
|
||||
|
||||
var editor = new Editor(new Renderer(el, require("ace/theme/textmate")));
|
||||
editor.setSession(doc);
|
||||
|
||||
var env = require("pilot/environment").create();
|
||||
catalog.startupPlugins({ env: env }).then(function() {
|
||||
env.document = doc;
|
||||
env.editor = editor;
|
||||
editor.resize();
|
||||
Event.addListener(window, "resize", function() {
|
||||
editor.resize();
|
||||
});
|
||||
el.env = env;
|
||||
});
|
||||
// Store env on editor such that it can be accessed later on from
|
||||
// the returned object.
|
||||
editor.env = env;
|
||||
return editor;
|
||||
};
|
||||
});
|
||||
191
lib/ace/anchor.js
Normal file
191
lib/ace/anchor.js
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
*
|
||||
* 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 EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
/**
|
||||
* An Anchor is a floating pointer in the document. Whenever text is inserted or
|
||||
* deleted before the cursor, the position of the cursor is updated
|
||||
*/
|
||||
var Anchor = exports.Anchor = function(doc, row, column) {
|
||||
this.document = doc;
|
||||
|
||||
if (typeof column == "undefined")
|
||||
this.setPosition(row.row, row.column);
|
||||
else
|
||||
this.setPosition(row, column);
|
||||
|
||||
this.$onChange = this.onChange.bind(this);
|
||||
doc.on("change", this.$onChange);
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
oop.implement(this, EventEmitter);
|
||||
|
||||
this.getPosition = function() {
|
||||
return this.$clipPositionToDocument(this.row, this.column);
|
||||
};
|
||||
|
||||
this.getDocument = function() {
|
||||
return this.document;
|
||||
};
|
||||
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
|
||||
if (range.start.row == range.end.row && range.start.row != this.row)
|
||||
return;
|
||||
|
||||
if (range.start.row > this.row)
|
||||
return;
|
||||
|
||||
if (range.start.row == this.row && range.start.column > this.column)
|
||||
return;
|
||||
|
||||
var row = this.row;
|
||||
var column = this.column;
|
||||
|
||||
if (delta.action === "insertText") {
|
||||
if (range.start.row === row && range.start.column <= column) {
|
||||
if (range.start.row === range.end.row) {
|
||||
column += range.end.column - range.start.column;
|
||||
}
|
||||
else {
|
||||
column -= range.start.column;
|
||||
row += range.end.row - range.start.row;
|
||||
}
|
||||
}
|
||||
else if (range.start.row !== range.end.row && range.start.row < row) {
|
||||
row += range.end.row - range.start.row;
|
||||
}
|
||||
} else if (delta.action === "insertLines") {
|
||||
if (range.start.row <= row) {
|
||||
row += range.end.row - range.start.row;
|
||||
}
|
||||
}
|
||||
else if (delta.action == "removeText") {
|
||||
if (range.start.row == row && range.start.column < column) {
|
||||
if (range.end.column >= column)
|
||||
column = range.start.column;
|
||||
else
|
||||
column = Math.max(0, column - (range.end.column - range.start.column));
|
||||
|
||||
} else if (range.start.row !== range.end.row && range.start.row < row) {
|
||||
if (range.end.row == row) {
|
||||
column = Math.max(0, column - range.end.column) + range.start.column;
|
||||
}
|
||||
row -= (range.end.row - range.start.row);
|
||||
}
|
||||
else if (range.end.row == row) {
|
||||
row -= range.end.row - range.start.row;
|
||||
column = Math.max(0, column - range.end.column) + range.start.column;
|
||||
}
|
||||
} else if (delta.action == "removeLines") {
|
||||
if (range.start.row <= row) {
|
||||
if (range.end.row <= row)
|
||||
row -= range.end.row - range.start.row;
|
||||
else {
|
||||
row = range.start.row;
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setPosition(row, column, true);
|
||||
};
|
||||
|
||||
this.setPosition = function(row, column, noClip) {
|
||||
if (noClip) {
|
||||
pos = {
|
||||
row: row,
|
||||
column: column
|
||||
};
|
||||
}
|
||||
else {
|
||||
pos = this.$clipPositionToDocument(row, column);
|
||||
}
|
||||
|
||||
if (this.row == pos.row && this.column == pos.column)
|
||||
return;
|
||||
|
||||
var old = {
|
||||
row: this.row,
|
||||
column: this.column
|
||||
};
|
||||
|
||||
this.row = pos.row;
|
||||
this.column = pos.column;
|
||||
this._dispatchEvent("change", {
|
||||
old: old,
|
||||
value: pos
|
||||
});
|
||||
};
|
||||
|
||||
this.detach = function() {
|
||||
this.document.removeEventListener("change", this.$onChange);
|
||||
};
|
||||
|
||||
this.$clipPositionToDocument = function(row, column) {
|
||||
var pos = {};
|
||||
|
||||
if (row >= this.document.getLength()) {
|
||||
pos.row = Math.max(0, this.document.getLength() - 1);
|
||||
pos.column = this.document.getLine(pos.row).length;
|
||||
}
|
||||
else if (row < 0) {
|
||||
pos.row = 0;
|
||||
pos.column = 0;
|
||||
}
|
||||
else {
|
||||
pos.row = row;
|
||||
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
|
||||
}
|
||||
|
||||
if (column < 0)
|
||||
pos.column = 0;
|
||||
|
||||
return pos;
|
||||
};
|
||||
|
||||
}).call(Anchor.prototype);
|
||||
|
||||
});
|
||||
183
lib/ace/anchor_test.js
Normal file
183
lib/ace/anchor_test.js
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("ace/document").Document;
|
||||
var Anchor = require("ace/anchor").Anchor;
|
||||
var Range = require("ace/range").Range;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
"test create anchor" : function() {
|
||||
var doc = new Document("juhu");
|
||||
var anchor = new Anchor(doc, 0, 0);
|
||||
|
||||
assert.position(anchor.getPosition(), 0, 0);
|
||||
assert.equal(anchor.getDocument(), doc);
|
||||
},
|
||||
|
||||
"test insert text in same row before cursor should move anchor column": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insert({row: 1, column: 1}, "123");
|
||||
assert.position(anchor.getPosition(), 1, 7);
|
||||
},
|
||||
|
||||
"test insert lines before cursor should move anchor row": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertLines(1, ["123", "456"]);
|
||||
assert.position(anchor.getPosition(), 3, 4);
|
||||
},
|
||||
|
||||
"test insert new line before cursor should move anchor column": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertNewLine({row: 0, column: 0});
|
||||
assert.position(anchor.getPosition(), 2, 4);
|
||||
},
|
||||
|
||||
"test insert new line in anchor line before anchor should move anchor column and row": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertNewLine({row: 1, column: 2});
|
||||
assert.position(anchor.getPosition(), 2, 2);
|
||||
},
|
||||
|
||||
"test delete text in anchor line before anchor should move anchor column": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.remove(new Range(1, 1, 1, 3));
|
||||
assert.position(anchor.getPosition(), 1, 2);
|
||||
},
|
||||
|
||||
"test remove range which contains the anchor should move the anchor to the start of the range": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 0, 3);
|
||||
|
||||
doc.remove(new Range(0, 1, 1, 3));
|
||||
assert.position(anchor.getPosition(), 0, 1);
|
||||
},
|
||||
|
||||
"test delete character before the anchor should have no effect": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.remove(new Range(1, 4, 1, 5));
|
||||
assert.position(anchor.getPosition(), 1, 4);
|
||||
},
|
||||
|
||||
"test delete lines in anchor line before anchor should move anchor row": function() {
|
||||
var doc = new Document("juhu\n1\n2\nkinners");
|
||||
var anchor = new Anchor(doc, 3, 4);
|
||||
|
||||
doc.removeLines(1, 2);
|
||||
assert.position(anchor.getPosition(), 1, 4);
|
||||
},
|
||||
|
||||
"test remove new line before the cursor": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.removeNewLine(0);
|
||||
assert.position(anchor.getPosition(), 0, 8);
|
||||
},
|
||||
|
||||
"test delete range which contains the anchor should move anchor to the end of the range": function() {
|
||||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.remove(new Range(0, 2, 1, 2));
|
||||
assert.position(anchor.getPosition(), 0, 4);
|
||||
},
|
||||
|
||||
"test delete line which contains the anchor should move anchor to the end of the range": function() {
|
||||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 5);
|
||||
|
||||
doc.removeLines(1, 1);
|
||||
assert.position(anchor.getPosition(), 1, 0);
|
||||
},
|
||||
|
||||
"test remove after the anchor should have no effect": function() {
|
||||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 2);
|
||||
|
||||
doc.remove(new Range(1, 4, 2, 2));
|
||||
assert.position(anchor.getPosition(), 1, 2);
|
||||
},
|
||||
|
||||
"test anchor changes triggered by document changes should emit change event": function(next) {
|
||||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 5);
|
||||
|
||||
anchor.on("change", function(e) {
|
||||
assert.position(anchor.getPosition(), 0, 0);
|
||||
next();
|
||||
});
|
||||
|
||||
doc.remove(new Range(0, 0, 2, 1));
|
||||
},
|
||||
|
||||
"test only fire change event if position changes": function() {
|
||||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 5);
|
||||
|
||||
anchor.on("change", function(e) {
|
||||
assert.fail();
|
||||
});
|
||||
|
||||
doc.remove(new Range(2, 0, 2, 1));
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -41,8 +41,7 @@ var oop = require("pilot/oop");
|
|||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
var BackgroundTokenizer = function(tokenizer, editor) {
|
||||
this.running = false;
|
||||
this.doc = [];
|
||||
this.running = false;
|
||||
this.lines = [];
|
||||
this.currentLine = 0;
|
||||
this.tokenizer = tokenizer;
|
||||
|
|
@ -57,7 +56,6 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
var doc = self.doc;
|
||||
|
||||
var processedLines = 0;
|
||||
var lastVisibleRow = editor.getLastVisibleRow();
|
||||
|
||||
var len = doc.getLength();
|
||||
while (self.currentLine < len) {
|
||||
|
|
@ -68,9 +66,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);
|
||||
self.running = setTimeout(self.$worker, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +130,9 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
};
|
||||
|
||||
this.$tokenizeRows = function(firstRow, lastRow) {
|
||||
if (!this.doc)
|
||||
return [];
|
||||
|
||||
var rows = [];
|
||||
|
||||
// determine start state
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -41,6 +43,14 @@ define(function(require, exports, module) {
|
|||
var lang = require("pilot/lang");
|
||||
var canon = require("pilot/canon");
|
||||
|
||||
function bindKey(win, mac) {
|
||||
return {
|
||||
win: win,
|
||||
mac: mac,
|
||||
sender: "editor"
|
||||
};
|
||||
}
|
||||
|
||||
canon.addCommand({
|
||||
name: "null",
|
||||
exec: function(env, args, request) { }
|
||||
|
|
@ -48,14 +58,17 @@ canon.addCommand({
|
|||
|
||||
canon.addCommand({
|
||||
name: "selectall",
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectAll(); }
|
||||
bindKey: bindKey("Ctrl-A", "Command-A"),
|
||||
exec: function(env, args, request) { env.editor.selectAll(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "removeline",
|
||||
bindKey: bindKey("Ctrl-D", "Command-D"),
|
||||
exec: function(env, args, request) { env.editor.removeLines(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotoline",
|
||||
bindKey: bindKey("Ctrl-L", "Command-L"),
|
||||
exec: function(env, args, request) {
|
||||
var line = parseInt(prompt("Enter line number:"));
|
||||
if (!isNaN(line)) {
|
||||
|
|
@ -65,197 +78,291 @@ canon.addCommand({
|
|||
});
|
||||
canon.addCommand({
|
||||
name: "togglecomment",
|
||||
bindKey: bindKey("Ctrl-7", "Command-7"),
|
||||
exec: function(env, args, request) { env.editor.toggleCommentLines(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "findnext",
|
||||
bindKey: bindKey("Ctrl-K", "Command-G"),
|
||||
exec: function(env, args, request) { env.editor.findNext(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "findprevious",
|
||||
bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
|
||||
exec: function(env, args, request) { env.editor.findPrevious(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "find",
|
||||
bindKey: bindKey("Ctrl-F", "Command-F"),
|
||||
exec: function(env, args, request) {
|
||||
var needle = prompt("Find:");
|
||||
env.editor.find(needle);
|
||||
}
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "replace",
|
||||
bindKey: bindKey("Ctrl-R", "Command-Option-F"),
|
||||
exec: function(env, args, request) {
|
||||
var needle = prompt("Find:");
|
||||
if (!needle)
|
||||
return;
|
||||
var replacement = prompt("Replacement:");
|
||||
if (!replacement)
|
||||
return;
|
||||
env.editor.replace(replacement, {needle: needle});
|
||||
}
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "replaceall",
|
||||
bindKey: bindKey("Ctrl-Shift-R", "Command-Shift-Option-F"),
|
||||
exec: function(env, args, request) {
|
||||
var needle = prompt("Find:");
|
||||
if (!needle)
|
||||
return;
|
||||
var replacement = prompt("Replacement:");
|
||||
if (!replacement)
|
||||
return;
|
||||
env.editor.replaceAll(replacement, {needle: needle});
|
||||
}
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "undo",
|
||||
bindKey: bindKey("Ctrl-Z", "Command-Z"),
|
||||
exec: function(env, args, request) { env.editor.undo(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "redo",
|
||||
exec: function(env, args, request) { env.editor.redo(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "redo",
|
||||
bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
|
||||
exec: function(env, args, request) { env.editor.redo(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "overwrite",
|
||||
bindKey: bindKey("Insert", "Insert"),
|
||||
exec: function(env, args, request) { env.editor.toggleOverwrite(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "copylinesup",
|
||||
bindKey: bindKey("Ctrl-Alt-Up", "Command-Option-Up"),
|
||||
exec: function(env, args, request) { env.editor.copyLinesUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "movelinesup",
|
||||
bindKey: bindKey("Alt-Up", "Option-Up"),
|
||||
exec: function(env, args, request) { env.editor.moveLinesUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selecttostart",
|
||||
bindKey: bindKey("Alt-Shift-Up", "Command-Shift-Up"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectFileStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotostart",
|
||||
bindKey: bindKey("Ctrl-Home|Ctrl-Up", "Command-Home|Command-Up"),
|
||||
exec: function(env, args, request) { env.editor.navigateFileStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectup",
|
||||
bindKey: bindKey("Shift-Up", "Shift-Up"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "golineup",
|
||||
bindKey: bindKey("Up", "Up|Ctrl-P"),
|
||||
exec: function(env, args, request) { env.editor.navigateUp(args.times); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "copylinesdown",
|
||||
bindKey: bindKey("Ctrl-Alt-Down", "Command-Option-Down"),
|
||||
exec: function(env, args, request) { env.editor.copyLinesDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "movelinesdown",
|
||||
bindKey: bindKey("Alt-Down", "Option-Down"),
|
||||
exec: function(env, args, request) { env.editor.moveLinesDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selecttoend",
|
||||
bindKey: bindKey("Alt-Shift-Down", "Command-Shift-Down"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectFileEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotoend",
|
||||
bindKey: bindKey("Ctrl-End|Ctrl-Down", "Command-End|Command-Down"),
|
||||
exec: function(env, args, request) { env.editor.navigateFileEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectdown",
|
||||
bindKey: bindKey("Shift-Down", "Shift-Down"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "golinedown",
|
||||
bindKey: bindKey("Down", "Down|Ctrl-N"),
|
||||
exec: function(env, args, request) { env.editor.navigateDown(args.times); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectwordleft",
|
||||
bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectWordLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotowordleft",
|
||||
bindKey: bindKey("Ctrl-Left", "Option-Left"),
|
||||
exec: function(env, args, request) { env.editor.navigateWordLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selecttolinestart",
|
||||
bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectLineStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotolinestart",
|
||||
bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
|
||||
exec: function(env, args, request) { env.editor.navigateLineStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectleft",
|
||||
bindKey: bindKey("Shift-Left", "Shift-Left"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotoleft",
|
||||
bindKey: bindKey("Left", "Left|Ctrl-B"),
|
||||
exec: function(env, args, request) { env.editor.navigateLeft(args.times); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectwordright",
|
||||
bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectWordRight(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotowordright",
|
||||
bindKey: bindKey("Ctrl-Right", "Option-Right"),
|
||||
exec: function(env, args, request) { env.editor.navigateWordRight(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selecttolineend",
|
||||
bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectLineEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotolineend",
|
||||
bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
|
||||
exec: function(env, args, request) { env.editor.navigateLineEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectright",
|
||||
bindKey: bindKey("Shift-Right", "Shift-Right"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectRight(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotoright",
|
||||
bindKey: bindKey("Right", "Right|Ctrl-F"),
|
||||
exec: function(env, args, request) { env.editor.navigateRight(args.times); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectpagedown",
|
||||
bindKey: bindKey("Shift-PageDown", "Shift-PageDown"),
|
||||
exec: function(env, args, request) { env.editor.selectPageDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "pagedown",
|
||||
bindKey: bindKey(null, "PageDown"),
|
||||
exec: function(env, args, request) { env.editor.scrollPageDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotopagedown",
|
||||
bindKey: bindKey("PageDown", "Option-PageDown|Ctrl-V"),
|
||||
exec: function(env, args, request) { env.editor.gotoPageDown(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectpageup",
|
||||
bindKey: bindKey("Shift-PageUp", "Shift-PageUp"),
|
||||
exec: function(env, args, request) { env.editor.selectPageUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "pageup",
|
||||
bindKey: bindKey(null, "PageUp"),
|
||||
exec: function(env, args, request) { env.editor.scrollPageUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotopageup",
|
||||
bindKey: bindKey("PageUp", "Option-PageUp"),
|
||||
exec: function(env, args, request) { env.editor.gotoPageUp(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectlinestart",
|
||||
bindKey: bindKey("Shift-Home", "Shift-Home"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectLineStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotolinestart",
|
||||
exec: function(env, args, request) { env.editor.navigateLineStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "selectlineend",
|
||||
bindKey: bindKey("Shift-End", "Shift-End"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectLineEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "gotolineend",
|
||||
exec: function(env, args, request) { env.editor.navigateLineEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "del",
|
||||
bindKey: bindKey("Delete", "Delete|Ctrl-D"),
|
||||
exec: function(env, args, request) { env.editor.removeRight(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "backspace",
|
||||
bindKey: bindKey(
|
||||
"Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
|
||||
"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
|
||||
),
|
||||
exec: function(env, args, request) { env.editor.removeLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "removetolinestart",
|
||||
bindKey: bindKey(null, "Option-Backspace"),
|
||||
exec: function(env, args, request) { env.editor.removeToLineStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "removetolineend",
|
||||
bindKey: bindKey(null, "Ctrl-K"),
|
||||
exec: function(env, args, request) { env.editor.removeToLineEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "removewordleft",
|
||||
bindKey: bindKey(null, "Alt-Backspace|Ctrl-Alt-Backspace"),
|
||||
exec: function(env, args, request) { env.editor.removeWordLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "removewordright",
|
||||
bindKey: bindKey(null, "Alt-Delete"),
|
||||
exec: function(env, args, request) { env.editor.removeWordRight(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "outdent",
|
||||
bindKey: bindKey("Shift-Tab", "Shift-Tab"),
|
||||
exec: function(env, args, request) { env.editor.blockOutdent(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "indent",
|
||||
bindKey: bindKey("Tab", "Tab"),
|
||||
exec: function(env, args, request) { env.editor.indent(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "inserttext",
|
||||
exec: function(env, args, request) {
|
||||
env.editor.insert(lang.stringRepeat(args.text || "",
|
||||
args.times || 1));
|
||||
env.editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
|
||||
}
|
||||
});
|
||||
|
||||
canon.addCommand({
|
||||
name: "centerselection",
|
||||
bindKey: bindKey(null, "Ctrl-L"),
|
||||
exec: function(env, args, request) { env.editor.centerSelection(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "splitline",
|
||||
bindKey: bindKey(null, "Ctrl-O"),
|
||||
exec: function(env, args, request) { env.editor.splitLine(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
name: "transposeletters",
|
||||
bindKey: bindKey("Ctrl-T", "Ctrl-T"),
|
||||
exec: function(env, args, request) { env.editor.transposeLetters(); }
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,88 +1,158 @@
|
|||
.ace_editor {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
|
||||
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ace_scroller {
|
||||
position: absolute;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
position: absolute;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ace_content {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ace_composition {
|
||||
position: absolute;
|
||||
background: #555;
|
||||
color: #DDD;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.ace_gutter {
|
||||
position: absolute;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ace_gutter-cell.ace_error {
|
||||
background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4px center;
|
||||
}
|
||||
|
||||
.ace_gutter-cell.ace_warning {
|
||||
background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4px center;
|
||||
}
|
||||
|
||||
.ace_editor .ace_sb {
|
||||
position: absolute;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ace_editor .ace_sb div {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
left: 0px;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ace_editor .ace_print_margin_layer {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ace_editor .ace_print_margin {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ace_editor textarea {
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
width: 10px;
|
||||
height: 30px;
|
||||
opacity: 0;
|
||||
background: transparent;
|
||||
appearance: none;
|
||||
border: none;
|
||||
resize: none;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ace_layer {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ace_text-layer {
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
color: black;
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.ace_cjk {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ace_cursor-layer {
|
||||
cursor: text;
|
||||
z-index: 4;
|
||||
cursor: text;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ace_cursor {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ace_line {
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ace_marker-layer {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_step {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_selection {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_bracket {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_active_line {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_selected_word {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {
|
||||
cursor: move;
|
||||
}
|
||||
|
|
|
|||
51
lib/ace/defaults.js
Normal file
51
lib/ace/defaults.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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):
|
||||
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
||||
*
|
||||
* 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 settings = require("ace/settings/default-settings")
|
||||
|
||||
exports.startup = function startup(data, reason) {
|
||||
settings.startup(data, reason)
|
||||
}
|
||||
|
||||
exports.shutdown = function shutdown(data, reason) {
|
||||
settings.shutdown(data, reason)
|
||||
}
|
||||
|
||||
})
|
||||
File diff suppressed because it is too large
Load diff
313
lib/ace/document_test.js
Normal file
313
lib/ace/document_test.js
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("ace/document").Document;
|
||||
var Range = require("ace/range").Range;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
"test: insert text in line" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "juhu");
|
||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert new line" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertNewLine({row: 0, column: 1});
|
||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert lines at the beginning" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertLines(0, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert lines at the end" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertLines(2, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert lines in the middle" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertLines(1, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert multi line string at the start" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert multi line string at the end" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert multi line string in the middle" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||
},
|
||||
|
||||
"test: delete in line" : function() {
|
||||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 1, 0, 3));
|
||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||
},
|
||||
|
||||
"test: delete new line" : function() {
|
||||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 4, 1, 0));
|
||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||
},
|
||||
|
||||
"test: delete multi line range line" : function() {
|
||||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 2, 2, 2));
|
||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
doc.revertDeltas(d);
|
||||
assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n"));
|
||||
|
||||
doc.applyDeltas(d);
|
||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: delete full lines" : function() {
|
||||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(1, 0, 3, 0));
|
||||
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
|
||||
},
|
||||
|
||||
"test: remove lines should return the removed lines" : function() {
|
||||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var removed = doc.removeLines(1, 2);
|
||||
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: should handle unix style new lines" : function() {
|
||||
var doc = new Document(["1", "2", "3"]);
|
||||
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.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.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.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.getValue(), ["1", "2", "3"].join("\n"));
|
||||
|
||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||
|
||||
doc.setNewLineMode("auto");
|
||||
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.getValue());
|
||||
},
|
||||
|
||||
"test: set value": function() {
|
||||
var doc = new Document("1");
|
||||
assert.equal("1", doc.getValue());
|
||||
|
||||
doc.setValue(doc.getValue());
|
||||
assert.equal("1", doc.getValue());
|
||||
|
||||
var doc = new Document("1\n2");
|
||||
assert.equal("1\n2", doc.getValue());
|
||||
|
||||
doc.setValue(doc.getValue());
|
||||
assert.equal("1\n2", doc.getValue());
|
||||
},
|
||||
|
||||
"test: empty document has to contain one line": function() {
|
||||
var doc = new Document("");
|
||||
assert.equal(doc.$lines.length, 1);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
1633
lib/ace/edit_session.js
Normal file
1633
lib/ace/edit_session.js
Normal file
File diff suppressed because it is too large
Load diff
273
lib/ace/edit_session/fold_line.js
Normal file
273
lib/ace/edit_session/fold_line.js
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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):
|
||||
* Julian Viereck <julian DOT viereck AT gmail DOT com>
|
||||
*
|
||||
* 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 Range = require("ace/range").Range;
|
||||
|
||||
/**
|
||||
* If the an array is passed in, the folds are expected to be sorted already.
|
||||
*/
|
||||
function FoldLine(foldData, folds) {
|
||||
this.foldData = foldData;
|
||||
if (Array.isArray(folds)) {
|
||||
this.folds = folds;
|
||||
} else {
|
||||
folds = this.folds = [ folds ];
|
||||
}
|
||||
|
||||
var last = folds[folds.length - 1]
|
||||
this.range = new Range(folds[0].start.row, folds[0].start.column,
|
||||
last.end.row, last.end.column);
|
||||
this.start = this.range.start;
|
||||
this.end = this.range.end;
|
||||
|
||||
this.folds.forEach(function(fold) {
|
||||
fold.foldLine = this;
|
||||
}, this);
|
||||
}
|
||||
|
||||
(function() {
|
||||
/**
|
||||
* Note: This doesn't update wrapData!
|
||||
*/
|
||||
this.shiftRow = function(shift) {
|
||||
this.start.row += shift;
|
||||
this.end.row += shift;
|
||||
this.folds.forEach(function(fold) {
|
||||
fold.start.row += shift;
|
||||
fold.end.row += shift;
|
||||
});
|
||||
}
|
||||
|
||||
this.addFold = function(fold) {
|
||||
if (fold.sameRow) {
|
||||
if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
|
||||
throw "Can't add a fold to this FoldLine as it has no connection";
|
||||
}
|
||||
this.folds.push(fold);
|
||||
this.folds.sort(function(a, b) {
|
||||
return -a.range.compareEnd(b.start.row, b.start.column);
|
||||
});
|
||||
if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {
|
||||
this.end.row = fold.end.row;
|
||||
this.end.column = fold.end.column;
|
||||
} else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {
|
||||
this.start.row = fold.start.row;
|
||||
this.start.column = fold.start.column;
|
||||
}
|
||||
} else if (fold.start.row == this.end.row) {
|
||||
this.folds.push(fold);
|
||||
this.end.row = fold.end.row;
|
||||
this.end.column = fold.end.column;
|
||||
} else if (fold.end.row == this.start.row) {
|
||||
this.folds.unshift(fold);
|
||||
this.start.row = fold.start.row;
|
||||
this.start.column = fold.start.column;
|
||||
} else {
|
||||
throw "Trying to add fold to FoldRow that doesn't have a matching row";
|
||||
}
|
||||
fold.foldLine = this;
|
||||
}
|
||||
|
||||
this.containsRow = function(row) {
|
||||
return row >= this.start.row && row <= this.end.row;
|
||||
}
|
||||
|
||||
this.walk = function(callback, endRow, endColumn) {
|
||||
var lastEnd = 0,
|
||||
folds = this.folds,
|
||||
fold,
|
||||
comp, stop, isNewRow = true;
|
||||
|
||||
if (endRow == null) {
|
||||
endRow = this.end.row;
|
||||
endColumn = this.end.column;
|
||||
}
|
||||
|
||||
for (var i = 0; i < folds.length; i++) {
|
||||
fold = folds[i];
|
||||
|
||||
comp = fold.range.compareStart(endRow, endColumn);
|
||||
// This fold is after the endRow/Column.
|
||||
if (comp == -1) {
|
||||
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
||||
return;
|
||||
}
|
||||
|
||||
stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
|
||||
stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
|
||||
|
||||
// If the user requested to stop the walk or endRow/endColumn is
|
||||
// inside of this fold (comp == 0), then end here.
|
||||
if (stop || comp == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note the new lastEnd might not be on the same line. However,
|
||||
// it's the callback's job to recognize this.
|
||||
isNewRow = !fold.sameRow;
|
||||
lastEnd = fold.end.column;
|
||||
}
|
||||
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
||||
}
|
||||
|
||||
this.getNextFoldTo = function(row, column) {
|
||||
var fold, cmp;
|
||||
for (var i = 0; i < this.folds.length; i++) {
|
||||
fold = this.folds[i];
|
||||
cmp = fold.range.compareEnd(row, column);
|
||||
if (cmp == -1) {
|
||||
return {
|
||||
fold: fold,
|
||||
kind: "after"
|
||||
};
|
||||
} else if (cmp == 0) {
|
||||
return {
|
||||
fold: fold,
|
||||
kind: "inside"
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
this.addRemoveChars = function(row, column, len) {
|
||||
var ret = this.getNextFoldTo(row, column),
|
||||
fold, folds;
|
||||
if (ret) {
|
||||
fold = ret.fold;
|
||||
if (ret.kind == "inside"
|
||||
&& fold.start.column != column
|
||||
&& fold.start.row != row)
|
||||
{
|
||||
throw "Moving characters inside of a fold should never be reached";
|
||||
} else if (fold.start.row == row) {
|
||||
folds = this.folds;
|
||||
var i = folds.indexOf(fold);
|
||||
if (i == 0) {
|
||||
this.start.column += len;
|
||||
}
|
||||
for (i; i < folds.length; i++) {
|
||||
fold = folds[i];
|
||||
fold.start.column += len;
|
||||
if (!fold.sameRow) {
|
||||
return;
|
||||
}
|
||||
fold.end.column += len;
|
||||
}
|
||||
this.end.column += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.split = function(row, column) {
|
||||
var fold = this.getNextFoldTo(row, column).fold,
|
||||
folds = this.folds;
|
||||
var foldData = this.foldData;
|
||||
|
||||
if (!fold) {
|
||||
return null;
|
||||
}
|
||||
var i = folds.indexOf(fold);
|
||||
var foldBefore = folds[i - 1];
|
||||
this.end.row = foldBefore.end.row;
|
||||
this.end.column = foldBefore.end.column;
|
||||
|
||||
// Remove the folds after row/column and create a new FoldLine
|
||||
// containing these removed folds.
|
||||
folds = folds.splice(i, folds.length - i);
|
||||
|
||||
var newFoldLine = new FoldLine(foldData, folds);
|
||||
foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
|
||||
return newFoldLine;
|
||||
}
|
||||
|
||||
this.merge = function(foldLineNext) {
|
||||
var folds = foldLineNext.folds;
|
||||
for (var i = 0; i < folds.length; i++) {
|
||||
this.addFold(folds[i]);
|
||||
}
|
||||
// Remove the foldLineNext - no longer needed, as
|
||||
// it's merged now with foldLineNext.
|
||||
var foldData = this.foldData;
|
||||
foldData.splice(foldData.indexOf(foldLineNext), 1);
|
||||
}
|
||||
|
||||
this.toString = function() {
|
||||
var ret = [this.range.toString() + ": [" ];
|
||||
|
||||
this.folds.forEach(function(fold) {
|
||||
ret.push(" " + fold.toString());
|
||||
});
|
||||
ret.push("]")
|
||||
return ret.join("\n");
|
||||
}
|
||||
|
||||
this.idxToPosition = function(idx) {
|
||||
var lastFoldEndColumn = 0;
|
||||
var fold;
|
||||
|
||||
for (var i = 0; i < this.folds.length; i++) {
|
||||
var fold = this.folds[i];
|
||||
|
||||
idx -= fold.start.column - lastFoldEndColumn;
|
||||
if (idx < 0) {
|
||||
return {
|
||||
row: fold.start.row,
|
||||
column: fold.start.column + idx
|
||||
};
|
||||
}
|
||||
|
||||
idx -= fold.placeholder.length;
|
||||
if (idx < 0) {
|
||||
return fold.start;
|
||||
}
|
||||
|
||||
lastFoldEndColumn = fold.end.column;
|
||||
}
|
||||
|
||||
return {
|
||||
row: this.end.row,
|
||||
column: this.end.column + idx
|
||||
};
|
||||
}
|
||||
}).call(FoldLine.prototype);
|
||||
|
||||
exports.FoldLine = FoldLine;
|
||||
});
|
||||
487
lib/ace/edit_session/folding.js
Normal file
487
lib/ace/edit_session/folding.js
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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):
|
||||
* Julian Viereck <julian DOT viereck AT gmail DOT com>
|
||||
*
|
||||
* 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 Range = require("ace/range").Range;
|
||||
var FoldLine = require("ace/edit_session/fold_line").FoldLine;
|
||||
|
||||
/**
|
||||
* Simple fold-data struct.
|
||||
**/
|
||||
function Fold(range, placeholder) {
|
||||
this.foldLine = null;
|
||||
this.placeholder = placeholder;
|
||||
this.range = range;
|
||||
this.start = range.start;
|
||||
this.end = range.end;
|
||||
|
||||
this.sameRow = range.start.row == range.end.row;
|
||||
this.subFolds = [];
|
||||
}
|
||||
|
||||
Fold.prototype.toString = function() {
|
||||
return '"' + this.placeholder + '" ' + this.range.toString();
|
||||
}
|
||||
|
||||
function Folding() {
|
||||
/**
|
||||
* Looks up a fold at a given row/column. Possible values for side:
|
||||
* -1: ignore a fold if fold.start = row/column
|
||||
* +1: ignore a fold if fold.end = row/column
|
||||
*/
|
||||
this.getFoldAt = function(row, column, side) {
|
||||
var foldLine = this.getFoldLine(row);
|
||||
if (foldLine) {
|
||||
var folds = foldLine.folds,
|
||||
fold;
|
||||
|
||||
for (var i = 0; i < folds.length; i++) {
|
||||
fold = folds[i];
|
||||
if (fold.range.contains(row, column)) {
|
||||
if (side == 1 && fold.range.isEnd(row, column)) {
|
||||
continue;
|
||||
} else if (side == -1 && fold.range.isStart(row, column)) {
|
||||
continue;
|
||||
}
|
||||
return fold;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all folds in the given range. Note, that this will return folds
|
||||
*
|
||||
*/
|
||||
this.getFoldsInRange = function(range) {
|
||||
range = range.clone();
|
||||
var start = range.start,
|
||||
end = range.end;
|
||||
var foldLines = this.$foldData,
|
||||
folds,
|
||||
fold;
|
||||
var cmp,
|
||||
foundFolds = [];
|
||||
|
||||
start.column += 1;
|
||||
end.column -= 1;
|
||||
|
||||
for (var i = 0; i < foldLines.length; i++) {
|
||||
cmp = foldLines[i].range.compareRange(range);
|
||||
// Range is before foldLine. No intersection. This means,
|
||||
// there might be other foldLines that intersect.
|
||||
if (cmp == 2) {
|
||||
continue;
|
||||
} else
|
||||
// Range is after foldLine. There can't be any other foldLines then,
|
||||
// so let's give up.
|
||||
if (cmp == -2) {
|
||||
break;
|
||||
}
|
||||
|
||||
folds = foldLines[i].folds;
|
||||
for (var j = 0; j < folds.length; j++) {
|
||||
fold = folds[j];
|
||||
cmp = fold.range.compareRange(range);
|
||||
if (cmp == -2) {
|
||||
break;
|
||||
} else if (cmp == 2) {
|
||||
continue;
|
||||
} else
|
||||
// WTF-state: Can happen due to -1/+1 to start/end column.
|
||||
if (cmp == 42) {
|
||||
break;
|
||||
}
|
||||
foundFolds.push(fold);
|
||||
}
|
||||
}
|
||||
return foundFolds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string between folds at the given position.
|
||||
* E.g.
|
||||
* foo<fold>b|ar<fold>wolrd -> "bar"
|
||||
* foo<fold>bar<fold>wol|rd -> "world"
|
||||
* foo<fold>bar<fo|ld>wolrd -> <null>
|
||||
*
|
||||
* where | means the position of row/column
|
||||
*
|
||||
* The trim option determs if the return string should be trimed according
|
||||
* to the "side" passed with the trim value:
|
||||
*
|
||||
* E.g.
|
||||
* foo<fold>b|ar<fold>wolrd -trim=-1> "b"
|
||||
* foo<fold>bar<fold>wol|rd -trim=+1> "rld"
|
||||
* fo|o<fold>bar<fold>wolrd -trim=00> "foo"
|
||||
*/
|
||||
this.getFoldStringAt = function(row, column, trim, foldLine) {
|
||||
var foldLine = foldLine || this.getFoldLine(row);
|
||||
if (!foldLine) {
|
||||
return null;
|
||||
} else {
|
||||
var fold, lastFold, cmp, str;
|
||||
lastFold = {
|
||||
end: { column: 0 }
|
||||
};
|
||||
// TODO: Refactor to use getNextFoldTo function.
|
||||
for (var i = 0; i < foldLine.folds.length; i++) {
|
||||
fold = foldLine.folds[i];
|
||||
cmp = fold.range.compareEnd(row, column);
|
||||
if (cmp == -1) {
|
||||
str = this.getLine(fold.start.row).
|
||||
substring(lastFold.end.column, fold.start.column);
|
||||
break;
|
||||
} else if (cmp == 0) {
|
||||
return null;
|
||||
}
|
||||
lastFold = fold;
|
||||
}
|
||||
if (!str) {
|
||||
str = this.getLine(fold.start.row).
|
||||
substring(lastFold.end.column);
|
||||
}
|
||||
if (trim == -1) {
|
||||
return str.substring(0, column - lastFold.end.column);
|
||||
} else if (trim == 1) {
|
||||
return str.substring(column - lastFold.end.column)
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.getFoldLine = function(docRow, startFoldLine) {
|
||||
var foldData = this.$foldData;
|
||||
var i = Math.max(foldData.indexOf(startFoldLine), 0);
|
||||
for (i; i < foldData.length; i++) {
|
||||
var foldLine = foldData[i];
|
||||
if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {
|
||||
return foldLine;
|
||||
} else if (foldLine.end.row > docRow) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
this.$addFoldLine = function(foldLine) {
|
||||
this.$foldData.push(foldLine);
|
||||
this.$foldData.sort(function(a, b) {
|
||||
return a.start.row - b.start.row;
|
||||
});
|
||||
return foldLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new fold.
|
||||
*
|
||||
* @returns
|
||||
* The new created Fold object or an existing fold object in case the
|
||||
* passed in range fits an existing fold exactly.
|
||||
*/
|
||||
this.addFold = function(placeholder, startRow, startColumn, endRow, endColumn) {
|
||||
var range;
|
||||
var foldData = this.$foldData;
|
||||
var foldRow = null;
|
||||
var foldLine;
|
||||
var fold;
|
||||
var argsFold;
|
||||
var folds;
|
||||
var added = false;
|
||||
|
||||
if (placeholder instanceof Fold) {
|
||||
argsFold = placeholder;
|
||||
startRow = argsFold.range;
|
||||
placeholder = argsFold.placeholder;
|
||||
}
|
||||
|
||||
// Normalize parameters.
|
||||
if (!(startRow instanceof Range)) {
|
||||
range = new Range(startRow, startColumn, endRow, endColumn);
|
||||
} else {
|
||||
range = startRow;
|
||||
startRow = range.start.row;
|
||||
startColumn = range.start.column;
|
||||
endRow = range.end.row;
|
||||
endColumn = range.end.column;
|
||||
}
|
||||
|
||||
// --- Some checking ---
|
||||
if (placeholder.length < 2) {
|
||||
throw "Placeholder has to be at least 2 characters";
|
||||
}
|
||||
|
||||
if (startRow == endRow && endColumn - startColumn < 2) {
|
||||
throw "The range has to be at least 2 characters width";
|
||||
}
|
||||
|
||||
fold = this.getFoldAt(startRow, startColumn, 1);
|
||||
if (fold
|
||||
&& fold.range.isEnd(endRow, endColumn)
|
||||
&& fold.range.isStart(startRow, startColumn))
|
||||
{
|
||||
return fold;
|
||||
}
|
||||
|
||||
fold = this.getFoldAt(startRow, startColumn, 1);
|
||||
if (fold && !fold.range.isStart(startRow, startColumn)) {
|
||||
throw "A fold can't start inside of an already existing fold";
|
||||
}
|
||||
|
||||
fold = this.getFoldAt(endRow, endColumn, -1);
|
||||
if (fold && !fold.range.isEnd(endRow, endColumn)) {
|
||||
throw "A fold can't end inside of an already existing fold";
|
||||
}
|
||||
|
||||
if (endRow >= this.doc.$lines.length) {
|
||||
throw "End of fold is outside of the document.";
|
||||
}
|
||||
|
||||
if (endColumn > this.getLine(endRow).length
|
||||
|| startColumn > this.getLine(startRow).length)
|
||||
{
|
||||
throw "End of fold is outside of the document.";
|
||||
}
|
||||
|
||||
// --- Start adding the fold ---
|
||||
// Use the passed in fold or create a new one.
|
||||
fold = argsFold || new Fold(range, placeholder);
|
||||
|
||||
// Check if there are folds in the range we create the new fold for.
|
||||
folds = this.getFoldsInRange(range);
|
||||
if (folds.length > 0) {
|
||||
// Remove the folds from fold data.
|
||||
this.removeFolds(folds);
|
||||
// Add the removed folds as subfolds on the new fold.
|
||||
fold.subFolds = folds;
|
||||
}
|
||||
|
||||
for (var i = 0; i < foldData.length; i++) {
|
||||
foldLine = foldData[i];
|
||||
if (endRow == foldLine.start.row) {
|
||||
foldLine.addFold(fold);
|
||||
added = true;
|
||||
break;
|
||||
} else if (startRow == foldLine.end.row) {
|
||||
foldLine.addFold(fold);
|
||||
added = true;
|
||||
if (!fold.sameRow) {
|
||||
// Check if we might have to merge two FoldLines.
|
||||
foldLineNext = foldData[i + 1];
|
||||
if (foldLineNext && foldLineNext.start.row == endRow) {
|
||||
// We need to merge!
|
||||
foldLine.merge(foldLineNext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (endRow <= foldLine.start.row) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
|
||||
}
|
||||
|
||||
if (this.$useWrapMode) {
|
||||
this.$updateWrapData(foldLine.start.row, foldLine.start.row);
|
||||
}
|
||||
|
||||
// Notify that fold data has changed.
|
||||
this.$modified = true;
|
||||
this._dispatchEvent("changeFold", { data: fold });
|
||||
|
||||
return fold;
|
||||
};
|
||||
|
||||
this.addFolds = function(folds) {
|
||||
folds.forEach(function(fold) {
|
||||
this.addFold(fold);
|
||||
}, this);
|
||||
};
|
||||
|
||||
this.removeFold = function(fold) {
|
||||
var foldLine = fold.foldLine;
|
||||
var startRow = foldLine.start.row;
|
||||
var endRow = foldLine.end.row;
|
||||
|
||||
var foldLines = this.$foldData,
|
||||
folds = foldLine.folds;
|
||||
// Simple case where there is only one fold in the FoldLine such that
|
||||
// the entire fold line can get removed directly.
|
||||
if (folds.length == 1) {
|
||||
foldLines.splice(foldLines.indexOf(foldLine), 1);
|
||||
} else
|
||||
// If the fold is the last fold of the foldLine, just remove it.
|
||||
if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {
|
||||
folds.pop();
|
||||
foldLine.end.row = folds[folds.length - 1].end.row;
|
||||
foldLine.end.column = folds[folds.length - 1].end.column;
|
||||
} else
|
||||
// If the fold is the first fold of the foldLine, just remove it.
|
||||
if (foldLine.range.isStart(fold.start.row, fold.start.column)) {
|
||||
folds.shift();
|
||||
foldLine.start.row = folds[0].start.row;
|
||||
foldLine.start.column = folds[0].start.column;
|
||||
} else
|
||||
// We know there are more then 2 folds and the fold is not at the edge.
|
||||
// This means, the fold is somewhere in between.
|
||||
//
|
||||
// If the fold is in one row, we just can remove it.
|
||||
if (fold.sameRow) {
|
||||
folds.splice(folds.indexOf(fold), 1);
|
||||
} else
|
||||
// The fold goes over more then one row. This means remvoing this fold
|
||||
// will cause the fold line to get splitted up.
|
||||
{
|
||||
var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
|
||||
newFoldLine.folds.shift();
|
||||
foldLine.start.row = folds[0].start.row;
|
||||
foldLine.start.column = folds[0].start.column;
|
||||
this.$addFoldLine(newFoldLine);
|
||||
}
|
||||
|
||||
if (this.$useWrapMode) {
|
||||
this.$updateWrapData(startRow, endRow);
|
||||
}
|
||||
|
||||
// Notify that fold data has changed.
|
||||
this.$modified = true;
|
||||
this._dispatchEvent("changeFold", { data: fold });
|
||||
}
|
||||
|
||||
this.removeFolds = function(folds) {
|
||||
// We need to clone the folds array passed in as it might be the folds
|
||||
// array of a fold line and as we call this.removeFold(fold), folds
|
||||
// are removed from folds and changes the current index.
|
||||
var cloneFolds = [];
|
||||
for (var i = 0; i < folds.length; i++) {
|
||||
cloneFolds.push(folds[i]);
|
||||
}
|
||||
|
||||
cloneFolds.forEach(function(fold) {
|
||||
this.removeFold(fold);
|
||||
}, this);
|
||||
this.$modified = true;
|
||||
}
|
||||
|
||||
this.expandFold = function(fold) {
|
||||
this.removeFold(fold);
|
||||
fold.subFolds.forEach(function(fold) {
|
||||
this.addFold(fold);
|
||||
}, this);
|
||||
fold.subFolds = [];
|
||||
}
|
||||
|
||||
this.expandFolds = function(folds) {
|
||||
folds.forEach(function(fold) {
|
||||
this.expandFold(fold);
|
||||
}, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given documentRow is folded. This is true if there are some
|
||||
* folded parts such that some parts of the line is still visible.
|
||||
**/
|
||||
this.isRowFolded = function(docRow, startFoldRow) {
|
||||
return !!this.getFoldLine(docRow, startFoldRow);
|
||||
};
|
||||
|
||||
this.getRowFoldEnd = function(docRow, startFoldRow) {
|
||||
var foldLine = this.getFoldLine(docRow, startFoldRow);
|
||||
return (foldLine
|
||||
? foldLine.end.row
|
||||
: docRow)
|
||||
};
|
||||
|
||||
this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
|
||||
if (startRow == null) {
|
||||
startRow = foldLine.start.row;
|
||||
startColumn = 0;
|
||||
}
|
||||
|
||||
if (endRow == null) {
|
||||
endRow = foldLine.end.row;
|
||||
endColumn = this.getLine(endRow).length;
|
||||
}
|
||||
|
||||
// Build the textline using the FoldLine walker.
|
||||
var line = "";
|
||||
var lines = this.doc.$lines;
|
||||
var textLine = "";
|
||||
|
||||
foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
|
||||
if (row < startRow) {
|
||||
return;
|
||||
} else if (row == startRow) {
|
||||
if (column < startColumn) {
|
||||
return;
|
||||
}
|
||||
lastColumn = Math.max(startColumn, lastColumn);
|
||||
}
|
||||
if (placeholder) {
|
||||
textLine += placeholder;
|
||||
} else {
|
||||
textLine += lines[row].substring(lastColumn, column);
|
||||
}
|
||||
}.bind(this), endRow, endColumn);
|
||||
return textLine;
|
||||
};
|
||||
|
||||
this.getDisplayLine = function(row, endColumn, startRow, startColumn) {
|
||||
var foldLine = this.getFoldLine(row);
|
||||
|
||||
if (!foldLine) {
|
||||
var line;
|
||||
line = this.doc.$lines[row];
|
||||
return line.substring(startColumn || 0, endColumn || line.length);
|
||||
} else {
|
||||
return this.getFoldDisplayLine(
|
||||
foldLine, row, endColumn, startRow, startColumn);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.Folding = Folding;
|
||||
|
||||
});
|
||||
865
lib/ace/edit_session_test.js
Normal file
865
lib/ace/edit_session_test.js
Normal file
|
|
@ -0,0 +1,865 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian DOT viereck AT gmail DOT com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var lang = require("pilot/lang");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var UndoManager = require("ace/undomanager").UndoManager;
|
||||
var MockRenderer = require("ace/test/mockrenderer");
|
||||
var Range = require("ace/range").Range;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
function createFoldTestSession() {
|
||||
var lines = [
|
||||
"function foo(items) {",
|
||||
" for (var i=0; i<items.length; i++) {",
|
||||
" alert(items[i] + \"juhu\");",
|
||||
" } // Real Tab.",
|
||||
"}"
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"));
|
||||
session.setUndoManager(new UndoManager());
|
||||
session.addFold("args...", new Range(0, 13, 0, 18));
|
||||
session.addFold("foo...", new Range(1, 10, 2, 10));
|
||||
session.addFold("bar...", new Range(2, 20, 2, 25));
|
||||
return session;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
"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), 8);
|
||||
assert.equal(session.documentToScreenColumn(0, 12), 14);
|
||||
assert.equal(session.documentToScreenColumn(0, 13), 16);
|
||||
|
||||
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), 6);
|
||||
assert.equal(session.documentToScreenColumn(0, 7), 7);
|
||||
assert.equal(session.documentToScreenColumn(0, 12), 12);
|
||||
assert.equal(session.documentToScreenColumn(0, 13), 14);
|
||||
},
|
||||
|
||||
"test: convert document to screen 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: documentToScreen with soft wrap and multibyte characters": function() {
|
||||
var tabSize = 4;
|
||||
var wrapLimit = 12;
|
||||
var session = new EditSession(["foo bar foo bar"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(12, 12);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
assert.position(session.documentToScreenPosition(0, 11), 0, 11);
|
||||
assert.position(session.documentToScreenPosition(0, 12), 1, 0);
|
||||
|
||||
session = new EditSession(["ぁぁa"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(2, 2);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
assert.position(session.documentToScreenPosition(0, 1), 1, 0);
|
||||
assert.position(session.documentToScreenPosition(0, 2), 2, 0);
|
||||
assert.position(session.documentToScreenPosition(0, 4), 2, 1);
|
||||
},
|
||||
|
||||
"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), 6);
|
||||
assert.equal(session.screenToDocumentColumn(0, 9), 7);
|
||||
assert.equal(session.screenToDocumentColumn(0, 15), 12);
|
||||
assert.equal(session.screenToDocumentColumn(0, 19), 16);
|
||||
|
||||
session.setTabSize(2);
|
||||
|
||||
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), 6);
|
||||
assert.equal(session.screenToDocumentColumn(0, 12), 12);
|
||||
assert.equal(session.screenToDocumentColumn(0, 13), 12);
|
||||
assert.equal(session.screenToDocumentColumn(0, 14), 13);
|
||||
},
|
||||
|
||||
"test: screenToDocument with soft wrap and multi byte characters": function() {
|
||||
var tabSize = 4;
|
||||
var wrapLimit = 12;
|
||||
var session = new EditSession(["foo bar foo bar"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(12, 12);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
assert.position(session.screenToDocumentPosition(1, 0), 0, 12);
|
||||
assert.position(session.screenToDocumentPosition(0, 11), 0, 11);
|
||||
// Check if the position is clamped the right way.
|
||||
assert.position(session.screenToDocumentPosition(0, 12), 0, 11);
|
||||
assert.position(session.screenToDocumentPosition(0, 20), 0, 11);
|
||||
|
||||
session = new EditSession(["ぁ a"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
assert.position(session.screenToDocumentPosition(0, 1), 0, 0);
|
||||
assert.position(session.screenToDocumentPosition(0, 2), 0, 1);
|
||||
assert.position(session.screenToDocumentPosition(0, 3), 0, 2);
|
||||
assert.position(session.screenToDocumentPosition(0, 4), 0, 3);
|
||||
assert.position(session.screenToDocumentPosition(0, 5), 0, 3);
|
||||
},
|
||||
|
||||
"test: wrapLine split function" : function() {
|
||||
var splits;
|
||||
var c = 0;
|
||||
|
||||
function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
|
||||
wrapLimit = wrapLimit || 12;
|
||||
tabSize = tabSize || 4;
|
||||
line = lang.stringTrimRight(line);
|
||||
var tokens = EditSession.prototype.$getDisplayTokens(line);
|
||||
var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
||||
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
||||
assert.ok(splits.length == assertEqual.length);
|
||||
for (var i = 0; i < splits.length; i++) {
|
||||
assert.ok(splits[i] == assertEqual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Basic splitting.
|
||||
computeAndAssert("foo bar foo bar", [ 12 ]);
|
||||
computeAndAssert("foo bar f bar", [ 12 ]);
|
||||
computeAndAssert("foo bar f r", [ 14 ]);
|
||||
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
|
||||
|
||||
// Don't split if there is only whitespaces/tabs at the end of the line.
|
||||
computeAndAssert("foo foo foo \t \t", [ ]);
|
||||
|
||||
// If there is no space to split, force split.
|
||||
computeAndAssert("foooooooooooooo", [ 12 ]);
|
||||
computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]);
|
||||
computeAndAssert("foo bar fooooooooooobooooooo", [8, 20]);
|
||||
|
||||
// Basic splitting + tabs.
|
||||
computeAndAssert("foo \t\tbar", [ 6 ]);
|
||||
computeAndAssert("foo \t \tbar", [ 7 ]);
|
||||
|
||||
// Ignore spaces/tabs at beginning of split.
|
||||
computeAndAssert("foo \t \t \t \t bar", [ 14 ]);
|
||||
|
||||
// Test wrapping for asian characters.
|
||||
computeAndAssert("ぁぁ", [1], 2);
|
||||
computeAndAssert(" ぁぁ", [1, 2], 2);
|
||||
computeAndAssert(" ぁ\tぁ", [1, 3], 2);
|
||||
computeAndAssert(" ぁぁ\tぁ", [1, 4], 4);
|
||||
},
|
||||
|
||||
"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);
|
||||
},
|
||||
|
||||
"test getDisplayString": function() {
|
||||
var session = new EditSession(["12"]);
|
||||
session.setTabSize(4);
|
||||
|
||||
assert.equal(session.$getDisplayTokens("\t").length, 4);
|
||||
assert.equal(session.$getDisplayTokens("abc").length, 3);
|
||||
assert.equal(session.$getDisplayTokens("abc\t").length, 4);
|
||||
},
|
||||
|
||||
"test issue 83": function() {
|
||||
var session = new EditSession("");
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
var document = session.getDocument();
|
||||
|
||||
session.setUseWrapMode(true);
|
||||
|
||||
document.insertLines(0, ["a", "b"]);
|
||||
document.insertLines(2, ["c", "d"]);
|
||||
document.removeLines(1, 2);
|
||||
},
|
||||
|
||||
"test wrapMode init has to create wrapData array": function() {
|
||||
var session = new EditSession("foo bar\nfoo bar");
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
var document = session.getDocument();
|
||||
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(3, 3);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
// Test if wrapData is there and was computed.
|
||||
assert.equal(session.$wrapData.length, 2);
|
||||
assert.equal(session.$wrapData[0].length, 1);
|
||||
assert.equal(session.$wrapData[1].length, 1);
|
||||
},
|
||||
|
||||
"test first line blank with wrap": function() {
|
||||
var session = new EditSession("\nfoo");
|
||||
session.setUseWrapMode(true);
|
||||
assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
|
||||
},
|
||||
|
||||
"test first line blank with wrap 2" : function() {
|
||||
var session = new EditSession("");
|
||||
session.setUseWrapMode(true);
|
||||
session.setValue("\nfoo");
|
||||
|
||||
assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
|
||||
},
|
||||
|
||||
"test fold getFoldDisplayLine": function() {
|
||||
var session = createFoldTestSession();
|
||||
function assertDisplayLine(foldLine, str) {
|
||||
var line = session.getLine(foldLine.end.row);
|
||||
var displayLine =
|
||||
session.getFoldDisplayLine(foldLine, foldLine.end.row, line.length);
|
||||
assert.equal(displayLine, str);
|
||||
}
|
||||
|
||||
assertDisplayLine(session.$foldData[0], "function foo(args...) {")
|
||||
assertDisplayLine(session.$foldData[1], " for (vfoo...ert(items[bar...\"juhu\");");
|
||||
},
|
||||
|
||||
"test foldLine idxToPosition": function() {
|
||||
var session = createFoldTestSession();
|
||||
|
||||
function assertIdx2Pos(foldLineIdx, idx, row, column) {
|
||||
var foldLine = session.$foldData[foldLineIdx];
|
||||
assert.position(foldLine.idxToPosition(idx), row, column);
|
||||
}
|
||||
|
||||
// "function foo(items) {",
|
||||
// " for (var i=0; i<items.length; i++) {",
|
||||
// " alert(items[i] + \"juhu\");",
|
||||
// " } // Real Tab.",
|
||||
// "}"
|
||||
|
||||
assertIdx2Pos(0, 12, 0, 12);
|
||||
assertIdx2Pos(0, 13, 0, 13);
|
||||
assertIdx2Pos(0, 14, 0, 13);
|
||||
assertIdx2Pos(0, 19, 0, 13);
|
||||
assertIdx2Pos(0, 20, 0, 18);
|
||||
|
||||
assertIdx2Pos(1, 10, 1, 10);
|
||||
assertIdx2Pos(1, 11, 1, 10);
|
||||
assertIdx2Pos(1, 15, 1, 10);
|
||||
assertIdx2Pos(1, 16, 2, 10);
|
||||
assertIdx2Pos(1, 26, 2, 20);
|
||||
assertIdx2Pos(1, 27, 2, 20);
|
||||
assertIdx2Pos(1, 32, 2, 25);
|
||||
},
|
||||
|
||||
"test fold documentToScreen": function() {
|
||||
var session = createFoldTestSession();
|
||||
function assertDoc2Screen(docRow, docCol, screenRow, screenCol) {
|
||||
assert.position(
|
||||
session.documentToScreenPosition(docRow, docCol),
|
||||
screenRow, screenCol
|
||||
);
|
||||
}
|
||||
|
||||
// One fold ending in the same row.
|
||||
assertDoc2Screen(0, 0, 0, 0);
|
||||
assertDoc2Screen(0, 13, 0, 13);
|
||||
assertDoc2Screen(0, 14, 0, 13);
|
||||
assertDoc2Screen(0, 17, 0, 13);
|
||||
assertDoc2Screen(0, 18, 0, 20);
|
||||
|
||||
// Fold ending on some other row.
|
||||
assertDoc2Screen(1, 0, 1, 0);
|
||||
assertDoc2Screen(1, 10, 1, 10);
|
||||
assertDoc2Screen(1, 11, 1, 10);
|
||||
assertDoc2Screen(1, 99, 1, 10);
|
||||
|
||||
assertDoc2Screen(2, 0, 1, 10);
|
||||
assertDoc2Screen(2, 9, 1, 10);
|
||||
assertDoc2Screen(2, 10, 1, 16);
|
||||
assertDoc2Screen(2, 11, 1, 17);
|
||||
|
||||
// Fold in the same row with fold over more then one row in the same row.
|
||||
assertDoc2Screen(2, 19, 1, 25);
|
||||
assertDoc2Screen(2, 20, 1, 26);
|
||||
assertDoc2Screen(2, 21, 1, 26);
|
||||
|
||||
assertDoc2Screen(2, 24, 1, 26);
|
||||
assertDoc2Screen(2, 25, 1, 32);
|
||||
assertDoc2Screen(2, 26, 1, 33);
|
||||
assertDoc2Screen(2, 99, 1, 40);
|
||||
|
||||
// Test one position after the folds. Should be all like normal.
|
||||
assertDoc2Screen(3, 0, 2, 0);
|
||||
},
|
||||
|
||||
"test fold screenToDocument": function() {
|
||||
var session = createFoldTestSession();
|
||||
function assertScreen2Doc(docRow, docCol, screenRow, screenCol) {
|
||||
assert.position(
|
||||
session.screenToDocumentPosition(screenRow, screenCol),
|
||||
docRow, docCol
|
||||
);
|
||||
}
|
||||
|
||||
// One fold ending in the same row.
|
||||
assertScreen2Doc(0, 0, 0, 0);
|
||||
assertScreen2Doc(0, 13, 0, 13);
|
||||
assertScreen2Doc(0, 13, 0, 14);
|
||||
assertScreen2Doc(0, 18, 0, 20);
|
||||
assertScreen2Doc(0, 19, 0, 21);
|
||||
|
||||
// Fold ending on some other row.
|
||||
assertScreen2Doc(1, 0, 1, 0);
|
||||
assertScreen2Doc(1, 10, 1, 10);
|
||||
assertScreen2Doc(1, 10, 1, 11);
|
||||
|
||||
assertScreen2Doc(1, 10, 1, 15);
|
||||
assertScreen2Doc(2, 10, 1, 16);
|
||||
assertScreen2Doc(2, 11, 1, 17);
|
||||
|
||||
// Fold in the same row with fold over more then one row in the same row.
|
||||
assertScreen2Doc(2, 19, 1, 25);
|
||||
assertScreen2Doc(2, 20, 1, 26);
|
||||
assertScreen2Doc(2, 20, 1, 27);
|
||||
|
||||
assertScreen2Doc(2, 20, 1, 31);
|
||||
assertScreen2Doc(2, 25, 1, 32);
|
||||
assertScreen2Doc(2, 26, 1, 33);
|
||||
assertScreen2Doc(2, 33, 1, 99);
|
||||
|
||||
// Test one position after the folds. Should be all like normal.
|
||||
assertScreen2Doc(3, 0, 2, 0);
|
||||
},
|
||||
|
||||
"test getFoldsInRange()": function() {
|
||||
var session = createFoldTestSession(),
|
||||
foldLines = session.$foldData;
|
||||
folds = foldLines[0].folds.concat(foldLines[1].folds);
|
||||
|
||||
function test(startRow, startColumn, endColumn, endRow, folds) {
|
||||
var r = new Range(startRow, startColumn, endColumn, endRow);
|
||||
var retFolds = session.getFoldsInRange(r);
|
||||
|
||||
assert.ok(retFolds.length == folds.length);
|
||||
for (var i = 0; i < retFolds.length; i++) {
|
||||
assert.equal(retFolds[i].range + "", folds[i].range + "");
|
||||
}
|
||||
}
|
||||
|
||||
test(0, 0, 0, 13, [ ]);
|
||||
test(0, 0, 0, 14, [ folds[0] ]);
|
||||
test(0, 0, 0, 18, [ folds[0] ]);
|
||||
test(0, 0, 1, 10, [ folds[0] ]);
|
||||
test(0, 0, 1, 11, [ folds[0], folds[1] ]);
|
||||
test(0, 18, 1, 11, [ folds[1] ]);
|
||||
test(2, 0, 2, 13, [ folds[1] ]);
|
||||
test(2, 10, 2, 20, [ ]);
|
||||
test(2, 10, 2, 11, [ ]);
|
||||
test(2, 19, 2, 20, [ ]);
|
||||
},
|
||||
|
||||
"test fold one-line text insert": function() {
|
||||
// These are mostly test for the FoldLine.addRemoveChars function.
|
||||
var session = createFoldTestSession(),
|
||||
undoManager = session.getUndoManager(),
|
||||
foldLines = session.$foldData;
|
||||
function insert(row, column, text) {
|
||||
session.insert({row: row, column: column}, text);
|
||||
|
||||
// Force the session to store all changes made to the document NOW
|
||||
// on the undoManager's queue. Otherwise we can't undo in separate
|
||||
// steps later.
|
||||
session.$syncInformUndoManager();
|
||||
}
|
||||
|
||||
var foldLine, fold, folds;
|
||||
// First line.
|
||||
foldLine = session.$foldData[0];
|
||||
fold = foldLine.folds[0];
|
||||
|
||||
insert(0, 0, "0");
|
||||
assert.range(foldLine.range, 0, 14, 0, 19);
|
||||
assert.range(fold.range, 0, 14, 0, 19);
|
||||
insert(0, 14, "1");
|
||||
assert.range(foldLine.range, 0, 15, 0, 20);
|
||||
assert.range(fold.range, 0, 15, 0, 20);
|
||||
insert(0, 20, "2");
|
||||
assert.range(foldLine.range, 0, 15, 0, 20);
|
||||
assert.range(fold.range, 0, 15, 0, 20);
|
||||
|
||||
// Second line.
|
||||
foldLine = session.$foldData[1];
|
||||
folds = foldLine.folds;
|
||||
|
||||
insert(1, 0, "3");
|
||||
assert.range(foldLine.range, 1, 11, 2, 25);
|
||||
assert.range(folds[0].range, 1, 11, 2, 10);
|
||||
assert.range(folds[1].range, 2, 20, 2, 25);
|
||||
|
||||
insert(1, 11, "4");
|
||||
assert.range(foldLine.range, 1, 12, 2, 25);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 20, 2, 25);
|
||||
|
||||
insert(2, 10, "5");
|
||||
assert.range(foldLine.range, 1, 12, 2, 26);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 21, 2, 26);
|
||||
|
||||
insert(2, 21, "6");
|
||||
assert.range(foldLine.range, 1, 12, 2, 27);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 22, 2, 27);
|
||||
|
||||
insert(2, 27, "7");
|
||||
assert.range(foldLine.range, 1, 12, 2, 27);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 22, 2, 27);
|
||||
|
||||
// UNDO = REMOVE
|
||||
undoManager.undo(); // 6
|
||||
assert.range(foldLine.range, 1, 12, 2, 27);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 22, 2, 27);
|
||||
|
||||
undoManager.undo(); // 5
|
||||
assert.range(foldLine.range, 1, 12, 2, 26);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 21, 2, 26);
|
||||
|
||||
undoManager.undo(); // 4
|
||||
assert.range(foldLine.range, 1, 12, 2, 25);
|
||||
assert.range(folds[0].range, 1, 12, 2, 10);
|
||||
assert.range(folds[1].range, 2, 20, 2, 25);
|
||||
|
||||
undoManager.undo(); // 3
|
||||
assert.range(foldLine.range, 1, 11, 2, 25);
|
||||
assert.range(folds[0].range, 1, 11, 2, 10);
|
||||
assert.range(folds[1].range, 2, 20, 2, 25);
|
||||
|
||||
undoManager.undo(); // Beginning first line.
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 0, 15, 0, 20);
|
||||
assert.range(foldLines[1].range, 1, 10, 2, 25);
|
||||
|
||||
foldLine = session.$foldData[0];
|
||||
fold = foldLine.folds[0];
|
||||
|
||||
undoManager.undo(); // 2
|
||||
assert.range(foldLine.range, 0, 15, 0, 20);
|
||||
assert.range(fold.range, 0, 15, 0, 20);
|
||||
|
||||
undoManager.undo(); // 1
|
||||
assert.range(foldLine.range, 0, 14, 0, 19);
|
||||
assert.range(fold.range, 0, 14, 0, 19);
|
||||
|
||||
undoManager.undo(); // 0
|
||||
assert.range(foldLine.range, 0, 13, 0, 18);
|
||||
assert.range(fold.range, 0, 13, 0, 18);
|
||||
},
|
||||
|
||||
"test fold multi-line insert/remove": function() {
|
||||
var session = createFoldTestSession(),
|
||||
undoManager = session.getUndoManager(),
|
||||
foldLines = session.$foldData;
|
||||
function insert(row, column, text) {
|
||||
session.insert({row: row, column: column}, text);
|
||||
// Force the session to store all changes made to the document NOW
|
||||
// on the undoManager's queue. Otherwise we can't undo in separate
|
||||
// steps later.
|
||||
session.$syncInformUndoManager();
|
||||
}
|
||||
|
||||
var foldLines = session.$foldData, foldLine, fold, folds;
|
||||
|
||||
insert(0, 0, "\nfo0");
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 2, 10, 3, 25);
|
||||
|
||||
insert(2, 0, "\nba1");
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 3, 13, 4, 25);
|
||||
|
||||
insert(3, 10, "\nfo2");
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 4, 6, 5, 25);
|
||||
|
||||
insert(5, 10, "\nba3");
|
||||
assert.equal(foldLines.length, 3);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 4, 6, 5, 10);
|
||||
assert.range(foldLines[2].range, 6, 13, 6, 18);
|
||||
|
||||
insert(6, 18, "\nfo4");
|
||||
assert.equal(foldLines.length, 3);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 4, 6, 5, 10);
|
||||
assert.range(foldLines[2].range, 6, 13, 6, 18);
|
||||
|
||||
undoManager.undo(); // 3
|
||||
assert.equal(foldLines.length, 3);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 4, 6, 5, 10);
|
||||
assert.range(foldLines[2].range, 6, 13, 6, 18);
|
||||
|
||||
undoManager.undo(); // 2
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 4, 6, 5, 25);
|
||||
|
||||
undoManager.undo(); // 1
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 3, 13, 4, 25);
|
||||
|
||||
undoManager.undo(); // 0
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 1, 16, 1, 21);
|
||||
assert.range(foldLines[1].range, 2, 10, 3, 25);
|
||||
|
||||
undoManager.undo(); // Beginning
|
||||
assert.equal(foldLines.length, 2);
|
||||
assert.range(foldLines[0].range, 0, 13, 0, 18);
|
||||
assert.range(foldLines[1].range, 1, 10, 2, 25);
|
||||
// TODO: Add test for inseration inside of folds.
|
||||
},
|
||||
|
||||
"test fold wrap data compution": function() {
|
||||
function assertArray(a, b) {
|
||||
assert.ok(a.length == b.length);
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
assert.equal(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function assertWrap(line0, line1, line2) {
|
||||
line0 && assertArray(wrapData[0], line0);
|
||||
line1 && assertArray(wrapData[1], line1);
|
||||
line2 && assertArray(wrapData[2], line2);
|
||||
}
|
||||
|
||||
function removeFoldAssertWrap(docRow, docColumn, line0, line1, line2) {
|
||||
session.removeFold(session.getFoldAt(docRow, docColumn));
|
||||
assertWrap(line0, line1, line2);
|
||||
}
|
||||
|
||||
var lines = [
|
||||
"foo bar foo bar",
|
||||
"foo bar foo bar",
|
||||
"foo bar foo bar"
|
||||
];
|
||||
|
||||
var session = new EditSession(lines.join("\n"));
|
||||
session.setUseWrapMode(true);
|
||||
session.$wrapLimit = 7;
|
||||
session.$updateWrapData(0, 2);
|
||||
var wrapData = session.$wrapData;
|
||||
|
||||
// Do a simple assertion without folds to check basic functionallity.
|
||||
assertWrap([8], [8], [8]);
|
||||
|
||||
// --- Do in line folding ---
|
||||
|
||||
// Adding a fold. The split position is inside of the fold. As placeholder
|
||||
// are not splitable, the split should be before the split.
|
||||
session.addFold("woot", 0, 4, 0, 15);
|
||||
assertWrap([4], [8], [8]);
|
||||
|
||||
// Remove the fold again which should reset the wrapData.
|
||||
removeFoldAssertWrap(0, 4, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot", 0, 6, 0, 9);
|
||||
assertWrap([6, 13], [8], [8]);
|
||||
removeFoldAssertWrap(0, 6, [8], [8], [8]);
|
||||
|
||||
// The fold fits into the wrap limit - no split expected.
|
||||
session.addFold("woot", 0, 3, 0, 15);
|
||||
assertWrap([], [8], [8]);
|
||||
removeFoldAssertWrap(0, 4, [8], [8], [8]);
|
||||
|
||||
// Fold after split position should be all fine.
|
||||
session.addFold("woot", 0, 8, 0, 15);
|
||||
assertWrap([8], [8], [8]);
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
// Fold's placeholder is far too long for wrapSplit.
|
||||
session.addFold("woot0123456789", 0, 8, 0, 15);
|
||||
assertWrap([8], [8], [8]);
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
// Fold's placeholder is far too long for wrapSplit
|
||||
// + content at the end of the line
|
||||
session.addFold("woot0123456789", 0, 6, 0, 8);
|
||||
assertWrap([6, 20], [8], [8]);
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot0123456789", 0, 6, 0, 8);
|
||||
session.addFold("woot0123456789", 0, 8, 0, 10);
|
||||
assertWrap([6, 20, 34], [8], [8]);
|
||||
session.removeFold(session.getFoldAt(0, 7));
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot0123456789", 0, 7, 0, 9);
|
||||
session.addFold("woot0123456789", 0, 13, 0, 15);
|
||||
assertWrap([7, 21, 25], [8], [8]);
|
||||
session.removeFold(session.getFoldAt(0, 7));
|
||||
removeFoldAssertWrap(0, 14, [8], [8], [8]);
|
||||
|
||||
// --- Do some multiline folding ---
|
||||
|
||||
// Add a fold over two lines. Note, that the wrapData[1] stays the
|
||||
// same. This is an implementation detail and expected behavior.
|
||||
session.addFold("woot", 0, 8, 1, 15);
|
||||
assertWrap([8], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot", 0, 9, 1, 11);
|
||||
assertWrap([8, 14], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 9, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot", 0, 9, 1, 15);
|
||||
assertWrap([8], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 9, [8], [8], [8]);
|
||||
|
||||
return session;
|
||||
},
|
||||
|
||||
"test add fold": function() {
|
||||
var session = createFoldTestSession();
|
||||
var fold;
|
||||
|
||||
function tryAddFold(
|
||||
placeholder,
|
||||
startRow, startColumn, endRow, endColumn, shouldFail)
|
||||
{
|
||||
var fail = false;
|
||||
try {
|
||||
fold = session.addFold(placeholder,
|
||||
startRow, startColumn, endRow, endColumn);
|
||||
} catch (e) {
|
||||
fail = true;
|
||||
}
|
||||
if (fail != shouldFail) {
|
||||
throw "Expected to get an exception";
|
||||
}
|
||||
}
|
||||
|
||||
tryAddFold("foo", 0, 13, 0, 17, true);
|
||||
tryAddFold("foo", 0, 14, 0, 18, true);
|
||||
tryAddFold("foo", 0, 13, 0, 18, false);
|
||||
assert.equal(session.$foldData[0].folds.length, 1);
|
||||
|
||||
tryAddFold("f", 0, 13, 0, 18, true);
|
||||
tryAddFold("foo", 0, 18, 0, 21, false);
|
||||
assert.equal(session.$foldData[0].folds.length, 2);
|
||||
session.removeFold(fold);
|
||||
|
||||
tryAddFold("foo", 0, 18, 0, 22, true);
|
||||
tryAddFold("foo", 0, 18, 0, 19, true);
|
||||
tryAddFold("foo", 0, 22, 1, 10, true);
|
||||
},
|
||||
|
||||
"test add subfolds": function() {
|
||||
var session = createFoldTestSession();
|
||||
var fold, oldFold;
|
||||
var foldData = session.$foldData;
|
||||
|
||||
oldFold = foldData[0].folds[0];
|
||||
|
||||
fold = session.addFold("fold0", 0, 10, 0, 21);
|
||||
assert.equal(foldData[0].folds.length, 1);
|
||||
assert.equal(fold.subFolds.length, 1);
|
||||
assert.equal(fold.subFolds[0], oldFold);
|
||||
|
||||
session.expandFold(fold);
|
||||
assert.equal(foldData[0].folds.length, 1);
|
||||
assert.equal(foldData[0].folds[0], oldFold);
|
||||
assert.equal(fold.subFolds.length, 0);
|
||||
|
||||
fold = session.addFold("fold0", 0, 13, 2, 10);
|
||||
assert.equal(foldData.length, 1);
|
||||
assert.equal(fold.subFolds.length, 2);
|
||||
assert.equal(fold.subFolds[0], oldFold);
|
||||
|
||||
session.expandFold(fold);
|
||||
assert.equal(foldData.length, 2);
|
||||
assert.equal(foldData[0].folds.length, 1);
|
||||
assert.equal(foldData[0].folds[0], oldFold);
|
||||
assert.equal(fold.subFolds.length, 0);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs/test").testcase(module.exports).exec()
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -35,30 +35,35 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
require("./mockdom");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var Text = require("ace/mode/text").Mode;
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var MockRenderer = require("ace/test/mockrenderer");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Document = require("../document").Document,
|
||||
Editor = require("../editor").Editor,
|
||||
Text = require("../mode/text").Mode,
|
||||
JavaScriptMode = require("../mode/javascript").Mode,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
assert = require("./assertions");
|
||||
module.exports = {
|
||||
|
||||
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 +72,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 +98,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,40 +128,38 @@ 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);
|
||||
},
|
||||
|
||||
"test: should use mode of new document" : function() {
|
||||
this.editor.onDocumentModeChange = function() {
|
||||
this.editor.onChangeMode = 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);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
215
lib/ace/editor_highlight_selected_word_test.js
Normal file
215
lib/ace/editor_highlight_selected_word_test.js
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
* Mihai Sucan.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var MockRenderer = require("ace/test/mockrenderer");
|
||||
var TextMode = require("ace/mode/text").Mode;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Mauris at arcu mi, eu lobortis mauris. Quisque ut libero eget " +
|
||||
"diam congue vehicula. Quisque ut odio ut mi aliquam tincidunt. " +
|
||||
"Duis lacinia aliquam lorem eget eleifend. Morbi eget felis mi. " +
|
||||
"Duis quam ligula, consequat vitae convallis volutpat, blandit " +
|
||||
"nec neque. Nulla facilisi. Etiam suscipit lorem ac justo " +
|
||||
"sollicitudin tristique. Phasellus ut posuere nunc. Aliquam " +
|
||||
"scelerisque mollis felis non gravida. Vestibulum lacus sem, " +
|
||||
"posuere non bibendum id, luctus non dolor. Aenean id metus " +
|
||||
"lorem, vel dapibus est. Donec gravida feugiat augue nec " +
|
||||
"accumsan.Lorem ipsum dolor sit amet, consectetur adipiscing " +
|
||||
"elit. Nulla vulputate, velit vitae tincidunt congue, nunc " +
|
||||
"augue accumsan velit, eu consequat turpis lectus ac orci. " +
|
||||
"Pellentesque ornare dolor feugiat dui auctor eu varius nulla " +
|
||||
"fermentum. Sed aliquam odio at velit lacinia vel fermentum " +
|
||||
"felis sodales. In dignissim magna eget nunc lobortis non " +
|
||||
"fringilla nibh ullamcorper. Donec facilisis malesuada elit " +
|
||||
"at egestas. Etiam bibendum, diam vitae tempor aliquet, dui " +
|
||||
"libero vehicula odio, eget bibendum mauris velit eu lorem.\n" +
|
||||
"consectetur";
|
||||
|
||||
module.exports = {
|
||||
setUp: function(next) {
|
||||
this.session = new EditSession(lipsum);
|
||||
this.editor = new Editor(new MockRenderer(), this.session);
|
||||
this.selection = this.session.getSelection();
|
||||
this.search = this.editor.$search;
|
||||
next();
|
||||
},
|
||||
|
||||
"test: highlight selected words by default": function() {
|
||||
assert.equal(this.editor.getHighlightSelectedWord(), true);
|
||||
},
|
||||
|
||||
"test: highlight a word": function() {
|
||||
this.editor.moveCursorTo(0, 9);
|
||||
this.selection.selectWord();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "ipsum");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 1);
|
||||
},
|
||||
|
||||
"test: highlight a word and clear highlight": function() {
|
||||
this.editor.moveCursorTo(0, 8);
|
||||
this.selection.selectWord();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "ipsum");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 1);
|
||||
|
||||
this.session.getMode().clearSelectionHighlight(this.editor);
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: highlight another word": function() {
|
||||
this.selection.moveCursorTo(0, 14);
|
||||
this.selection.selectWord();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "dolor");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 3);
|
||||
},
|
||||
|
||||
"test: no selection, no highlight": function() {
|
||||
this.selection.clearSelection();
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: select a word, no highlight": function() {
|
||||
this.editor.setHighlightSelectedWord(false);
|
||||
this.selection.moveCursorTo(0, 14);
|
||||
this.selection.selectWord();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "dolor");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: select a word with no matches": function() {
|
||||
this.editor.setHighlightSelectedWord(true);
|
||||
|
||||
var currentOptions = this.search.getOptions();
|
||||
var newOptions = {
|
||||
wrap: true,
|
||||
wholeWord: true,
|
||||
caseSensitive: true,
|
||||
needle: "Mauris"
|
||||
};
|
||||
this.search.set(newOptions);
|
||||
|
||||
var match = this.search.find(this.session);
|
||||
assert.notEqual(match, null, "found a match for 'Mauris'");
|
||||
|
||||
this.search.set(currentOptions);
|
||||
|
||||
this.selection.setSelectionRange(match);
|
||||
|
||||
assert.equal(this.session.getTextRange(match), "Mauris");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: partial word selection 1": function() {
|
||||
this.selection.moveCursorTo(0, 14);
|
||||
this.selection.selectWord();
|
||||
this.selection.selectLeft();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "dolo");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: partial word selection 2": function() {
|
||||
this.selection.moveCursorTo(0, 13);
|
||||
this.selection.selectWord();
|
||||
this.selection.selectRight();
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "dolor ");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: partial word selection 3": function() {
|
||||
this.selection.moveCursorTo(0, 14);
|
||||
this.selection.selectWord();
|
||||
this.selection.selectLeft();
|
||||
this.selection.shiftSelection(1);
|
||||
|
||||
var range = this.selection.getRange();
|
||||
assert.equal(this.session.getTextRange(range), "olor");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 0);
|
||||
},
|
||||
|
||||
"test: select last word": function() {
|
||||
this.selection.moveCursorTo(0, 1);
|
||||
|
||||
var currentOptions = this.search.getOptions();
|
||||
var newOptions = {
|
||||
wrap: true,
|
||||
wholeWord: true,
|
||||
caseSensitive: true,
|
||||
backwards: true,
|
||||
needle: "consectetur"
|
||||
};
|
||||
this.search.set(newOptions);
|
||||
|
||||
var match = this.search.find(this.session);
|
||||
assert.notEqual(match, null, "found a match for 'consectetur'");
|
||||
assert.position(match.start, 1, 0);
|
||||
|
||||
this.search.set(currentOptions);
|
||||
|
||||
this.selection.setSelectionRange(match);
|
||||
|
||||
assert.equal(this.session.getTextRange(match), "consectetur");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 2);
|
||||
},
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,24 +35,27 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
require("./mockdom");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var MockRenderer = require("ace/test/mockrenderer");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Document = require("../Document").Document,
|
||||
Editor = require("../Editor").Editor,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
assert = require("./assertions");
|
||||
|
||||
var Test = {
|
||||
createTextDocument : function(rows, cols) {
|
||||
module.exports = {
|
||||
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 +66,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 +76,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 +110,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 +124,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 +137,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,10 +153,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test)
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,86 +35,90 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
require("./mockdom");
|
||||
|
||||
var Document = require("../document").Document,
|
||||
Editor = require("../editor").Editor,
|
||||
JavaScriptMode = require("../mode/javascript").Mode,
|
||||
UndoManager = require("../undomanager").UndoManager,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
assert = require("./assertions");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var UndoManager = require("ace/undomanager").UndoManager;
|
||||
var MockRenderer = require("ace/test/mockrenderer");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
"test: delete line from the middle" : function() {
|
||||
var doc = new Document(["a", "b", "c", "d"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["a", "b", "c", "d"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "a\nc\nd");
|
||||
assert.equal(session.toString(), "a\nc\nd");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "a\nd");
|
||||
assert.equal(session.toString(), "a\nd");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "a\n");
|
||||
assert.equal(session.toString(), "a\n");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "a\n");
|
||||
assert.equal(session.toString(), "a\n");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
},
|
||||
|
||||
"test: delete multiple selected lines" : function() {
|
||||
var doc = new Document(["a", "b", "c", "d"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["a", "b", "c", "d"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.removeLines();
|
||||
assert.equal(doc.toString(), "a\nd");
|
||||
assert.equal(session.toString(), "a\nd");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
},
|
||||
|
||||
"test: delete first line" : function() {
|
||||
var doc = new Document(["a", "b", "c"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["a", "b", "c"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "b\nc");
|
||||
assert.equal(session.toString(), "b\nc");
|
||||
assert.position(editor.getCursorPosition(), 0, 0);
|
||||
},
|
||||
|
||||
"test: delete last" : function() {
|
||||
var doc = new Document(["a", "b", "c"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["a", "b", "c"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(2, 1);
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(doc.toString(), "a\nb\n");
|
||||
assert.equal(session.toString(), "a\nb\n");
|
||||
assert.position(editor.getCursorPosition(), 2, 0);
|
||||
},
|
||||
|
||||
"test: indent block" : function() {
|
||||
var doc = new Document(["a12345", "b12345", "c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["a12345", "b12345", "c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 3);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.indent();
|
||||
|
||||
assert.equal(["a12345", " b12345", " c12345"].join("\n"), doc.toString());
|
||||
assert.equal(["a12345", " b12345", " c12345"].join("\n"), session.toString());
|
||||
|
||||
assert.position(editor.getCursorPosition(), 2, 7);
|
||||
|
||||
|
|
@ -124,35 +128,35 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: indent selected lines" : function() {
|
||||
var doc = new Document(["a12345", "b12345", "c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
|
||||
editor.moveCursorTo(1, 0);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.indent();
|
||||
assert.equal(["a12345", " b12345", "c12345"].join("\n"), doc.toString());
|
||||
},
|
||||
|
||||
var session = new EditSession(["a12345", "b12345", "c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 0);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.indent();
|
||||
assert.equal(["a12345", " b12345", "c12345"].join("\n"), session.toString());
|
||||
},
|
||||
|
||||
"test: no auto indent if cursor is before the {" : function() {
|
||||
var doc = new Document("{", new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
|
||||
editor.moveCursorTo(0, 0);
|
||||
var session = new EditSession("{", new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 0);
|
||||
editor.onTextInput("\n");
|
||||
assert.equal(["", "{"].join("\n"), doc.toString());
|
||||
assert.equal(["", "{"].join("\n"), session.toString());
|
||||
},
|
||||
|
||||
"test: outdent block" : function() {
|
||||
var doc = new Document([" a12345", " b12345", " c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession([" a12345", " b12345", " c12345"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 5);
|
||||
editor.getSelection().selectDown();
|
||||
editor.getSelection().selectDown();
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.blockOutdent();
|
||||
assert.equal(doc.toString(), [" a12345", "b12345", " c12345"].join("\n"));
|
||||
assert.equal(session.toString(), [" a12345", "b12345", " c12345"].join("\n"));
|
||||
|
||||
assert.position(editor.getCursorPosition(), 2, 1);
|
||||
|
||||
|
|
@ -161,7 +165,7 @@ var Test = {
|
|||
assert.position(range.end, 2, 1);
|
||||
|
||||
editor.blockOutdent();
|
||||
assert.equal(doc.toString(), ["a12345", "b12345", "c12345"].join("\n"));
|
||||
assert.equal(session.toString(), ["a12345", "b12345", "c12345"].join("\n"));
|
||||
|
||||
var range = editor.getSelectionRange();
|
||||
assert.position(range.start, 0, 0);
|
||||
|
|
@ -169,25 +173,25 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: outent without a selection should update cursor" : function() {
|
||||
var doc = new Document(" 12");
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(" 12");
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 3);
|
||||
editor.blockOutdent(" ");
|
||||
|
||||
assert.equal(doc.toString(), " 12");
|
||||
assert.equal(session.toString(), " 12");
|
||||
assert.position(editor.getCursorPosition(), 0, 0);
|
||||
},
|
||||
|
||||
"test: comment lines should perserve selection" : function() {
|
||||
var doc = new Document([" abc", "cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession([" abc", "cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 2);
|
||||
editor.getSelection().selectDown();
|
||||
editor.toggleCommentLines();
|
||||
|
||||
assert.equal(["// abc", "//cde"].join("\n"), doc.toString());
|
||||
assert.equal(["// abc", "//cde"].join("\n"), session.toString());
|
||||
|
||||
var selection = editor.getSelectionRange();
|
||||
assert.position(selection.start, 0, 4);
|
||||
|
|
@ -195,8 +199,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: uncomment lines should perserve selection" : function() {
|
||||
var doc = new Document(["// abc", "//cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["// abc", "//cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
|
@ -205,29 +209,29 @@ var Test = {
|
|||
|
||||
editor.toggleCommentLines();
|
||||
|
||||
assert.equal([" abc", "cde"].join("\n"), doc.toString());
|
||||
assert.equal([" abc", "cde"].join("\n"), session.toString());
|
||||
assert.range(editor.getSelectionRange(), 0, 0, 1, 1);
|
||||
},
|
||||
|
||||
|
||||
"test: toggle comment lines twice should return the original text" : function() {
|
||||
var doc = new Document([" abc", "cde", "fg"], new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
|
||||
var session = new EditSession([" abc", "cde", "fg"], new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 0);
|
||||
editor.getSelection().selectDown();
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
|
||||
editor.toggleCommentLines();
|
||||
editor.toggleCommentLines();
|
||||
|
||||
assert.equal([" abc", "cde", "fg"].join("\n"), doc.toString());
|
||||
|
||||
assert.equal([" abc", "cde", "fg"].join("\n"), session.toString());
|
||||
},
|
||||
|
||||
|
||||
|
||||
"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);
|
||||
var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 0);
|
||||
editor.getSelection().selectDown();
|
||||
|
|
@ -236,8 +240,8 @@ var Test = {
|
|||
assert.range(editor.getSelectionRange(), 0, 2, 1, 0);
|
||||
|
||||
// select up
|
||||
var doc = new Document(["abc", "cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 0);
|
||||
editor.getSelection().selectUp();
|
||||
|
|
@ -247,47 +251,47 @@ var Test = {
|
|||
},
|
||||
|
||||
"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);
|
||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(0, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.moveLinesDown();
|
||||
assert.equal(["33", "11", "22", "44"].join("\n"), doc.toString());
|
||||
assert.equal(["33", "11", "22", "44"].join("\n"), session.toString());
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
||||
assert.position(editor.getSelection().getSelectionLead(), 1, 0);
|
||||
|
||||
editor.moveLinesDown();
|
||||
assert.equal(["33", "44", "11", "22"].join("\n"), doc.toString());
|
||||
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
||||
assert.position(editor.getCursorPosition(), 2, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);
|
||||
assert.position(editor.getSelection().getSelectionLead(), 2, 0);
|
||||
|
||||
// moving again should have no effect
|
||||
editor.moveLinesDown();
|
||||
assert.equal(["33", "44", "11", "22"].join("\n"), doc.toString());
|
||||
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
||||
assert.position(editor.getCursorPosition(), 2, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);
|
||||
assert.position(editor.getSelection().getSelectionLead(), 2, 0);
|
||||
},
|
||||
|
||||
"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);
|
||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(2, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.moveLinesUp();
|
||||
assert.equal(doc.toString(), ["11", "33", "44", "22"].join("\n"));
|
||||
assert.equal(session.toString(), ["11", "33", "44", "22"].join("\n"));
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
||||
assert.position(editor.getSelection().getSelectionLead(), 1, 0);
|
||||
|
||||
editor.moveLinesUp();
|
||||
assert.equal(doc.toString(), ["33", "44", "11", "22"].join("\n"));
|
||||
assert.equal(session.toString(), ["33", "44", "11", "22"].join("\n"));
|
||||
assert.position(editor.getCursorPosition(), 0, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 2, 0);
|
||||
assert.position(editor.getSelection().getSelectionLead(), 0, 0);
|
||||
|
|
@ -295,32 +299,32 @@ var Test = {
|
|||
|
||||
"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);
|
||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.clearSelection();
|
||||
|
||||
editor.moveLinesDown();
|
||||
assert.equal(["11", "33", "22", "44"].join("\n"), doc.toString());
|
||||
assert.equal(["11", "33", "22", "44"].join("\n"), session.toString());
|
||||
assert.position(editor.getCursorPosition(), 2, 0);
|
||||
|
||||
editor.clearSelection();
|
||||
|
||||
editor.moveLinesUp();
|
||||
assert.equal(["11", "22", "33", "44"].join("\n"), doc.toString());
|
||||
assert.equal(["11", "22", "33", "44"].join("\n"), session.toString());
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
},
|
||||
|
||||
"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);
|
||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.copyLinesDown();
|
||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), doc.toString());
|
||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
||||
|
||||
assert.position(editor.getCursorPosition(), 3, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 5, 0);
|
||||
|
|
@ -328,14 +332,14 @@ var Test = {
|
|||
},
|
||||
|
||||
"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);
|
||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.getSelection().selectDown();
|
||||
|
||||
editor.copyLinesUp();
|
||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), doc.toString());
|
||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
||||
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
||||
|
|
@ -343,107 +347,153 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: input a tab with soft tab should convert it to spaces" : function() {
|
||||
var doc = new Document("");
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession("");
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
doc.setTabSize(2);
|
||||
doc.setUseSoftTabs(true);
|
||||
session.setTabSize(2);
|
||||
session.setUseSoftTabs(true);
|
||||
|
||||
editor.onTextInput("\t");
|
||||
assert.equal(doc.toString(), " ");
|
||||
assert.equal(session.toString(), " ");
|
||||
|
||||
doc.setTabSize(5);
|
||||
session.setTabSize(5);
|
||||
editor.onTextInput("\t");
|
||||
assert.equal(doc.toString(), " ");
|
||||
assert.equal(session.toString(), " ");
|
||||
},
|
||||
|
||||
"test: input tab without soft tabs should keep the tab character" : function() {
|
||||
var doc = new Document("");
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession("");
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
doc.setUseSoftTabs(false);
|
||||
session.setUseSoftTabs(false);
|
||||
|
||||
editor.onTextInput("\t");
|
||||
assert.equal(doc.toString(), "\t");
|
||||
assert.equal(session.toString(), "\t");
|
||||
},
|
||||
|
||||
|
||||
"test: undo/redo for delete line" : function() {
|
||||
var doc = new Document(["111", "222", "333"]);
|
||||
var session = new EditSession(["111", "222", "333"]);
|
||||
var undoManager = new UndoManager();
|
||||
doc.setUndoManager(undoManager);
|
||||
|
||||
var initialText = doc.toString();
|
||||
|
||||
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
|
||||
session.setUndoManager(undoManager);
|
||||
|
||||
var initialText = session.toString();
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.removeLines();
|
||||
var step1 = doc.toString();
|
||||
var step1 = session.toString();
|
||||
assert.equal(step1, "222\n333");
|
||||
doc.$informUndoManager.call();
|
||||
|
||||
session.$informUndoManager.call();
|
||||
|
||||
editor.removeLines();
|
||||
var step2 = doc.toString();
|
||||
var step2 = session.toString();
|
||||
assert.equal(step2, "333");
|
||||
doc.$informUndoManager.call();
|
||||
|
||||
session.$informUndoManager.call();
|
||||
|
||||
editor.removeLines();
|
||||
var step3 = doc.toString();
|
||||
var step3 = session.toString();
|
||||
assert.equal(step3, "");
|
||||
doc.$informUndoManager.call();
|
||||
|
||||
|
||||
session.$informUndoManager.call();
|
||||
|
||||
|
||||
undoManager.undo();
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), step2);
|
||||
|
||||
session.$informUndoManager.call();
|
||||
assert.equal(session.toString(), step2);
|
||||
|
||||
undoManager.undo();
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), step1);
|
||||
|
||||
session.$informUndoManager.call();
|
||||
assert.equal(session.toString(), step1);
|
||||
|
||||
undoManager.undo();
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), initialText);
|
||||
|
||||
session.$informUndoManager.call();
|
||||
assert.equal(session.toString(), initialText);
|
||||
|
||||
undoManager.undo();
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), initialText);
|
||||
session.$informUndoManager.call();
|
||||
assert.equal(session.toString(), initialText);
|
||||
},
|
||||
|
||||
|
||||
"test: remove left should remove character left of the cursor" : function() {
|
||||
var doc = new Document(["123", "456"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["123", "456"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.removeLeft();
|
||||
assert.equal(doc.toString(), "123\n56");
|
||||
assert.equal(session.toString(), "123\n56");
|
||||
},
|
||||
|
||||
|
||||
"test: remove left should remove line break if cursor is at line start" : function() {
|
||||
var doc = new Document(["123", "456"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["123", "456"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 0);
|
||||
editor.removeLeft();
|
||||
assert.equal(doc.toString(), "123456");
|
||||
assert.equal(session.toString(), "123456");
|
||||
},
|
||||
|
||||
|
||||
"test: remove left should remove tabsize spaces if cursor is on a tab stop and preceeded by spaces" : function() {
|
||||
var doc = new Document(["123", " 456"]);
|
||||
doc.setUseSoftTabs(true);
|
||||
doc.setTabSize(4);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), doc);
|
||||
var session = new EditSession(["123", " 456"]);
|
||||
session.setUseSoftTabs(true);
|
||||
session.setTabSize(4);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 8);
|
||||
editor.removeLeft();
|
||||
assert.equal(doc.toString(), "123\n 456");
|
||||
assert.equal(session.toString(), "123\n 456");
|
||||
},
|
||||
|
||||
"test: transpose at line start should be a noop": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 0);
|
||||
editor.transposeLetters();
|
||||
|
||||
assert.equal(session.getValue(), ["123", "4567", "89"].join("\n"));
|
||||
},
|
||||
|
||||
"test: transpose in line should swap the charaters before and after the cursor": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 2);
|
||||
editor.transposeLetters();
|
||||
|
||||
assert.equal(session.getValue(), ["123", "4657", "89"].join("\n"));
|
||||
},
|
||||
|
||||
"test: transpose at line end should swap the last two characters": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 4);
|
||||
editor.transposeLetters();
|
||||
|
||||
assert.equal(session.getValue(), ["123", "4576", "89"].join("\n"));
|
||||
},
|
||||
|
||||
"test: transpose with non empty selection should be a noop": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 1);
|
||||
editor.getSelection().selectRight();
|
||||
editor.transposeLetters();
|
||||
|
||||
assert.equal(session.getValue(), ["123", "4567", "89"].join("\n"));
|
||||
},
|
||||
|
||||
"test: transpose should move the cursor behind the last swapped character": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 2);
|
||||
editor.transposeLetters();
|
||||
assert.position(editor.getCursorPosition(), 1, 3);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -42,19 +42,13 @@ var useragent = require("pilot/useragent");
|
|||
var keyUtil = require("pilot/keys");
|
||||
var event = require("pilot/event");
|
||||
var settings = require("pilot/settings").settings;
|
||||
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
|
||||
var default_mac = require("ace/keyboard/keybinding/default_mac").bindings;
|
||||
var default_win = require("ace/keyboard/keybinding/default_win").bindings;
|
||||
var canon = require("pilot/canon");
|
||||
require("ace/commands/default_commands");
|
||||
|
||||
var KeyBinding = function(editor, config) {
|
||||
var KeyBinding = function(editor) {
|
||||
this.$editor = editor;
|
||||
this.$data = { };
|
||||
this.$keyboardHandler = null;
|
||||
this.$defaulKeyboardHandler = new HashHandler(config || (useragent.isMac
|
||||
? default_mac
|
||||
: default_win));
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
|
@ -70,7 +64,9 @@ var KeyBinding = function(editor, config) {
|
|||
};
|
||||
|
||||
this.$callKeyboardHandler = function (e, hashId, keyOrText, keyCode) {
|
||||
var toExecute;
|
||||
var env = {editor: this.$editor},
|
||||
toExecute;
|
||||
|
||||
if (this.$keyboardHandler) {
|
||||
toExecute =
|
||||
this.$keyboardHandler.handleKeyboard(this.$data, hashId, keyOrText, keyCode, e);
|
||||
|
|
@ -78,13 +74,23 @@ var KeyBinding = function(editor, config) {
|
|||
|
||||
// If there is nothing to execute yet, then use the default keymapping.
|
||||
if (!toExecute || !toExecute.command) {
|
||||
toExecute = this.$defaulKeyboardHandler.
|
||||
handleKeyboard(this.$data, hashId, keyOrText, keyCode, e);
|
||||
if (hashId != 0 || keyCode != 0) {
|
||||
toExecute = {
|
||||
command: canon.findKeyCommand(env, "editor", hashId, keyOrText)
|
||||
}
|
||||
} else {
|
||||
toExecute = {
|
||||
command: "inserttext",
|
||||
args: {
|
||||
text: keyOrText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toExecute) {
|
||||
var success = canon.exec(toExecute.command,
|
||||
{editor: this.$editor}, toExecute.args);
|
||||
env, "editor", toExecute.args);
|
||||
if (success) {
|
||||
return event.stopEvent(e);
|
||||
}
|
||||
|
|
@ -92,10 +98,8 @@ var KeyBinding = function(editor, config) {
|
|||
};
|
||||
|
||||
this.onCommandKey = function(e, hashId, keyCode) {
|
||||
key = (keyUtil[keyCode] ||
|
||||
String.fromCharCode(keyCode)).toLowerCase();
|
||||
|
||||
this.$callKeyboardHandler(e, hashId, key, keyCode);
|
||||
var keyString = keyUtil.keyCodeToString(keyCode);
|
||||
this.$callKeyboardHandler(e, hashId, keyString, keyCode);
|
||||
};
|
||||
|
||||
this.onTextInput = function(text) {
|
||||
|
|
|
|||
|
|
@ -80,13 +80,13 @@ StateHandler.prototype = {
|
|||
}
|
||||
|
||||
var keyArray = [];
|
||||
if (hashId & 1) keyArray.push("Ctrl");
|
||||
if (hashId & 8) keyArray.push("Command");
|
||||
if (hashId & 2) keyArray.push("Option");
|
||||
if (hashId & 4) keyArray.push("Shift");
|
||||
if (hashId & 1) keyArray.push("ctrl");
|
||||
if (hashId & 8) keyArray.push("command");
|
||||
if (hashId & 2) keyArray.push("option");
|
||||
if (hashId & 4) keyArray.push("shift");
|
||||
if (key) keyArray.push(key);
|
||||
|
||||
var symbolicName = keyArray.join("-").toLowerCase();
|
||||
var symbolicName = keyArray.join("-");
|
||||
var bufferToUse = data.buffer + symbolicName;
|
||||
|
||||
// Don't add the symbolic name to the key buffer if the alt_ key is
|
||||
|
|
@ -194,6 +194,13 @@ StateHandler.prototype = {
|
|||
* This function is called by keyBinding.
|
||||
*/
|
||||
handleKeyboard: function(data, hashId, key) {
|
||||
// If we pressed any command key but no other key, then ignore the input.
|
||||
// Otherwise "shift-" is added to the buffer, and later on "shift-g"
|
||||
// which results in "shift-shift-g" which doesn't make senese.
|
||||
if (hashId != 0 && (key == "" || String.fromCharCode(0))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Compute the current value of the keyboard input buffer.
|
||||
var r = this.$composeBuffer(data, hashId, key);
|
||||
var buffer = r.bufferToUse;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -38,14 +40,13 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var event = require("pilot/event");
|
||||
var useragent = require("pilot/useragent");
|
||||
var dom = require("pilot/dom");
|
||||
|
||||
var TextInput = function(parentNode, host) {
|
||||
|
||||
var text = document.createElement("textarea");
|
||||
var style = text.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-10000px";
|
||||
style.top = "-10000px";
|
||||
var text = dom.createElement("textarea");
|
||||
text.style.left = "-10000px";
|
||||
parentNode.appendChild(text);
|
||||
|
||||
var PLACEHOLDER = String.fromCharCode(0);
|
||||
|
|
@ -53,6 +54,7 @@ var TextInput = function(parentNode, host) {
|
|||
|
||||
var inCompostion = false;
|
||||
var copied = false;
|
||||
var tempStyle = '';
|
||||
|
||||
function sendText(valueToSend) {
|
||||
if (!copied) {
|
||||
|
|
@ -74,6 +76,7 @@ var TextInput = function(parentNode, host) {
|
|||
}
|
||||
|
||||
var onTextInput = function(e) {
|
||||
if (useragent.isIE && text.value.charCodeAt(0) > 128) return;
|
||||
setTimeout(function() {
|
||||
if (!inCompostion)
|
||||
sendText();
|
||||
|
|
@ -82,40 +85,67 @@ var TextInput = function(parentNode, host) {
|
|||
|
||||
var onCompositionStart = function(e) {
|
||||
inCompostion = true;
|
||||
sendText();
|
||||
text.value = "";
|
||||
if (!useragent.isIE) {
|
||||
sendText();
|
||||
text.value = "";
|
||||
};
|
||||
host.onCompositionStart();
|
||||
setTimeout(onCompositionUpdate, 0);
|
||||
if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0);
|
||||
};
|
||||
|
||||
var onCompositionUpdate = function() {
|
||||
if (!inCompostion) return;
|
||||
host.onCompositionUpdate(text.value);
|
||||
};
|
||||
|
||||
var onCompositionEnd = function() {
|
||||
inCompostion = false;
|
||||
host.onCompositionEnd();
|
||||
onTextInput();
|
||||
setTimeout(function () {
|
||||
sendText();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
var onCopy = function() {
|
||||
var onCopy = function(e) {
|
||||
copied = true;
|
||||
text.value = host.getCopyText();
|
||||
var copyText = host.getCopyText();
|
||||
if(copyText)
|
||||
text.value = copyText;
|
||||
else
|
||||
e.preventDefault();
|
||||
text.select();
|
||||
copied = true;
|
||||
setTimeout(sendText, 0);
|
||||
setTimeout(function () {
|
||||
sendText();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
var onCut = function() {
|
||||
var onCut = function(e) {
|
||||
copied = true;
|
||||
text.value = host.getCopyText();
|
||||
host.onCut();
|
||||
var copyText = host.getCopyText();
|
||||
if(copyText) {
|
||||
text.value = copyText;
|
||||
host.onCut();
|
||||
} else
|
||||
e.preventDefault();
|
||||
text.select();
|
||||
setTimeout(sendText, 0);
|
||||
setTimeout(function () {
|
||||
sendText();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
event.addCommandKeyListener(text, host.onCommandKey.bind(host));
|
||||
event.addListener(text, "keypress", onTextInput);
|
||||
if (useragent.isIE) {
|
||||
var keytable = { 13:1, 27:1 };
|
||||
event.addListener(text, "keyup", function (e) {
|
||||
if (inCompostion && (!text.value || keytable[e.keyCode]))
|
||||
setTimeout(onCompositionEnd, 0);
|
||||
if ((text.value.charCodeAt(0)|0) < 129) {
|
||||
return;
|
||||
};
|
||||
inCompostion ? onCompositionUpdate() : onCompositionStart();
|
||||
});
|
||||
};
|
||||
event.addListener(text, "textInput", onTextInput);
|
||||
event.addListener(text, "paste", function(e) {
|
||||
// Some browsers support the event.clipboardData API. Use this to get
|
||||
|
|
@ -130,13 +160,41 @@ var TextInput = function(parentNode, host) {
|
|||
onTextInput();
|
||||
}
|
||||
});
|
||||
event.addListener(text, "propertychange", onTextInput);
|
||||
if (!useragent.isIE) {
|
||||
event.addListener(text, "propertychange", onTextInput);
|
||||
};
|
||||
|
||||
event.addListener(text, "copy", onCopy);
|
||||
event.addListener(text, "cut", onCut);
|
||||
if (useragent.isIE) {
|
||||
event.addListener(text, "beforecopy", function(e) {
|
||||
var copyText = host.getCopyText();
|
||||
if(copyText)
|
||||
clipboardData.setData("Text", copyText);
|
||||
else
|
||||
e.preventDefault();
|
||||
});
|
||||
event.addListener(parentNode, "keydown", function(e) {
|
||||
if (e.ctrlKey && e.keyCode == 88) {
|
||||
var copyText = host.getCopyText();
|
||||
if (copyText) {
|
||||
clipboardData.setData("Text", copyText);
|
||||
host.onCut();
|
||||
}
|
||||
event.preventDefault(e)
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
event.addListener(text, "copy", onCopy);
|
||||
event.addListener(text, "cut", onCut);
|
||||
}
|
||||
|
||||
event.addListener(text, "compositionstart", onCompositionStart);
|
||||
event.addListener(text, "compositionupdate", onCompositionUpdate);
|
||||
if (useragent.isGecko) {
|
||||
event.addListener(text, "text", onCompositionUpdate);
|
||||
};
|
||||
if (useragent.isWebKit) {
|
||||
event.addListener(text, "keyup", onCompositionUpdate);
|
||||
};
|
||||
event.addListener(text, "compositionend", onCompositionEnd);
|
||||
|
||||
event.addListener(text, "blur", function() {
|
||||
|
|
@ -157,6 +215,32 @@ var TextInput = function(parentNode, host) {
|
|||
this.blur = function() {
|
||||
text.blur();
|
||||
};
|
||||
|
||||
this.getElement = function() {
|
||||
return text;
|
||||
};
|
||||
|
||||
this.onContextMenu = function(mousePos, isEmpty){
|
||||
if (mousePos) {
|
||||
if(!tempStyle)
|
||||
tempStyle = text.style.cssText;
|
||||
text.style.cssText = 'position:fixed; z-index:1000;' +
|
||||
'left:' + (mousePos.x - 2) + 'px; top:' + (mousePos.y - 2) + 'px;'
|
||||
|
||||
}
|
||||
if (isEmpty)
|
||||
text.value='';
|
||||
}
|
||||
|
||||
this.onContextMenuClose = function(){
|
||||
setTimeout(function () {
|
||||
if (tempStyle) {
|
||||
text.style.cssText = tempStyle;
|
||||
tempStyle = '';
|
||||
}
|
||||
sendText();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
exports.TextInput = TextInput;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -40,11 +42,11 @@ define(function(require, exports, module) {
|
|||
var dom = require("pilot/dom");
|
||||
|
||||
var Cursor = function(parentEl) {
|
||||
this.element = document.createElement("div");
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_layer ace_cursor-layer";
|
||||
parentEl.appendChild(this.element);
|
||||
|
||||
this.cursor = document.createElement("div");
|
||||
this.cursor = dom.createElement("div");
|
||||
this.cursor.className = "ace_cursor";
|
||||
|
||||
this.isVisible = false;
|
||||
|
|
@ -52,20 +54,8 @@ var Cursor = function(parentEl) {
|
|||
|
||||
(function() {
|
||||
|
||||
this.setDocument = function(doc) {
|
||||
this.doc = doc;
|
||||
};
|
||||
|
||||
this.setCursor = function(position, overwrite) {
|
||||
this.position = {
|
||||
row : position.row,
|
||||
column : this.doc.documentToScreenColumn(position.row, position.column)
|
||||
};
|
||||
if (overwrite) {
|
||||
dom.addCssClass(this.cursor, "ace_overwrite");
|
||||
} else {
|
||||
dom.removeCssClass(this.cursor, "ace_overwrite");
|
||||
}
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
||||
this.hideCursor = function() {
|
||||
|
|
@ -100,46 +90,46 @@ var Cursor = function(parentEl) {
|
|||
}, 1000);
|
||||
};
|
||||
|
||||
this.getPixelPosition = function() {
|
||||
if (!this.config || !this.position) {
|
||||
this.getPixelPosition = function(onScreen) {
|
||||
if (!this.config || !this.session) {
|
||||
return {
|
||||
left : 0,
|
||||
top : 0
|
||||
};
|
||||
}
|
||||
|
||||
var cursorLeft = Math.round(this.position.column * this.config.characterWidth);
|
||||
var cursorTop = this.position.row * this.config.lineHeight;
|
||||
var position = this.session.selection.getCursor();
|
||||
var pos = this.session.documentToScreenPosition(position);
|
||||
var cursorLeft = Math.round(pos.column * this.config.characterWidth);
|
||||
var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
|
||||
this.config.lineHeight;
|
||||
|
||||
return {
|
||||
return {
|
||||
left : cursorLeft,
|
||||
top : cursorTop
|
||||
};
|
||||
};
|
||||
|
||||
this.update = function(config) {
|
||||
if (!this.position)
|
||||
return;
|
||||
|
||||
this.config = config;
|
||||
|
||||
var cursorLeft = Math.round(this.position.column * config.characterWidth);
|
||||
var cursorTop = this.position.row * config.lineHeight;
|
||||
this.pixelPos = this.getPixelPosition(true);
|
||||
|
||||
this.pixelPos = {
|
||||
left : cursorLeft,
|
||||
top : cursorTop
|
||||
};
|
||||
|
||||
this.cursor.style.left = cursorLeft + "px";
|
||||
this.cursor.style.top = (cursorTop - (config.firstRow * config.lineHeight))
|
||||
+ "px";
|
||||
this.cursor.style.left = this.pixelPos.left + "px";
|
||||
this.cursor.style.top = this.pixelPos.top + "px";
|
||||
this.cursor.style.width = config.characterWidth + "px";
|
||||
this.cursor.style.height = config.lineHeight + "px";
|
||||
|
||||
if (this.isVisible) {
|
||||
this.element.appendChild(this.cursor);
|
||||
}
|
||||
|
||||
if (this.session.getOverwrite()) {
|
||||
dom.addCssClass(this.cursor, "ace_overwrite");
|
||||
} else {
|
||||
dom.removeCssClass(this.cursor, "ace_overwrite");
|
||||
}
|
||||
|
||||
this.restartTimer();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian DOT viereck AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -40,41 +42,78 @@ define(function(require, exports, module) {
|
|||
var dom = require("pilot/dom");
|
||||
|
||||
var Gutter = function(parentEl) {
|
||||
this.element = document.createElement("div");
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_layer ace_gutter-layer";
|
||||
parentEl.appendChild(this.element);
|
||||
|
||||
this.$breakpoints = [];
|
||||
this.$annotations = [];
|
||||
this.$decorations = [];
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
||||
this.addGutterDecoration = function(row, className){
|
||||
if (!this.$decorations[row])
|
||||
if (!this.$decorations[row])
|
||||
this.$decorations[row] = "";
|
||||
this.$decorations[row] += " ace_" + className;
|
||||
}
|
||||
|
||||
|
||||
this.removeGutterDecoration = function(row, className){
|
||||
this.$decorations[row] =
|
||||
this.$decorations[row].replace(" ace_" + className, "");
|
||||
}
|
||||
this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
|
||||
};
|
||||
|
||||
this.setBreakpoints = function(rows) {
|
||||
this.$breakpoints = rows.concat();
|
||||
};
|
||||
|
||||
this.setAnnotations = function(annotations) {
|
||||
// iterate over sparse array
|
||||
this.$annotations = [];
|
||||
for (var row in annotations) if (annotations.hasOwnProperty(row)) {
|
||||
var rowAnnotations = annotations[row];
|
||||
if (!rowAnnotations)
|
||||
continue;
|
||||
|
||||
var rowInfo = this.$annotations[row] = {
|
||||
text: []
|
||||
};
|
||||
for (var i=0; i<rowAnnotations.length; i++) {
|
||||
var annotation = rowAnnotations[i];
|
||||
rowInfo.text.push(annotation.text.replace(/"/g, """).replace(/'/g, "’").replace(/</, "<"));
|
||||
var type = annotation.type;
|
||||
if (type == "error")
|
||||
rowInfo.className = "ace_error";
|
||||
else if (type == "warning" && rowInfo.className != "ace_error")
|
||||
rowInfo.className = "ace_warning";
|
||||
else if (type == "info" && (!rowInfo.className))
|
||||
rowInfo.className = "ace_info";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.update = function(config) {
|
||||
this.$config = config;
|
||||
|
||||
var html = [];
|
||||
for ( var i = config.firstRow; i <= config.lastRow; i++) {
|
||||
var annotation = this.$annotations[i] || {
|
||||
className: "",
|
||||
text: []
|
||||
};
|
||||
html.push("<div class='ace_gutter-cell",
|
||||
this.$decorations[i] || "",
|
||||
this.$breakpoints[i] ? " ace_breakpoint" : "",
|
||||
"' style='height:", config.lineHeight, "px;'>", (i+1), "</div>");
|
||||
html.push("</div>");
|
||||
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
||||
annotation.className,
|
||||
"' title='", annotation.text.join("\n"),
|
||||
"' style='height:", this.session.getRowHeight(config, i), "px;'>", (i+1), "</div>");
|
||||
|
||||
|
||||
i = this.session.getRowFoldEnd(i);
|
||||
}
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
this.element.style.height = config.minHeight + "px";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -41,36 +43,19 @@ var Range = require("ace/range").Range;
|
|||
var dom = require("pilot/dom");
|
||||
|
||||
var Marker = function(parentEl) {
|
||||
this.element = document.createElement("div");
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_layer ace_marker-layer";
|
||||
parentEl.appendChild(this.element);
|
||||
|
||||
this.markers = {};
|
||||
this.$markerId = 1;
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
this.setDocument = function(doc) {
|
||||
this.doc = doc;
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
||||
this.addMarker = function(range, clazz, type) {
|
||||
var id = this.$markerId++;
|
||||
this.markers[id] = {
|
||||
range : range,
|
||||
type : type || "line",
|
||||
clazz : clazz
|
||||
};
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
this.removeMarker = function(markerId) {
|
||||
var marker = this.markers[markerId];
|
||||
if (marker) {
|
||||
delete (this.markers[markerId]);
|
||||
}
|
||||
|
||||
this.setMarkers = function(markers) {
|
||||
this.markers = markers;
|
||||
};
|
||||
|
||||
this.update = function(config) {
|
||||
|
|
@ -80,14 +65,21 @@ var Marker = function(parentEl) {
|
|||
|
||||
this.config = config;
|
||||
|
||||
var html = [];
|
||||
var html = [];
|
||||
for ( var key in this.markers) {
|
||||
var marker = this.markers[key];
|
||||
|
||||
var range = marker.range.clipRows(config.firstRow, config.lastRow);
|
||||
if (range.isEmpty()) continue;
|
||||
|
||||
if (range.isMultiLine()) {
|
||||
range = range.toScreenRange(this.session);
|
||||
|
||||
if (marker.renderer) {
|
||||
var top = this.$getTop(range.start.row, config);
|
||||
var left = Math.round(range.start.column * config.characterWidth);
|
||||
marker.renderer(html, range, left, top, config);
|
||||
}
|
||||
else if (range.isMultiLine()) {
|
||||
if (marker.type == "text") {
|
||||
this.drawTextMarker(html, range, marker.clazz, config);
|
||||
} else {
|
||||
|
|
@ -101,11 +93,16 @@ var Marker = function(parentEl) {
|
|||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
};
|
||||
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
this.$getTop = function(row, layerConfig) {
|
||||
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
|
||||
};
|
||||
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
// 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.getScreenLastRowColumn(row));
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||
|
||||
// selection end
|
||||
|
|
@ -116,18 +113,16 @@ 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.getScreenLastRowColumn(row);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||
}
|
||||
};
|
||||
|
||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
var range = range.toScreenRange(this.doc);
|
||||
|
||||
// from selection start to the end of the line
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
|
||||
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
||||
var top = this.$getTop(range.start.row, layerConfig);
|
||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||
|
||||
stringBuilder.push(
|
||||
|
|
@ -139,7 +134,7 @@ var Marker = function(parentEl) {
|
|||
);
|
||||
|
||||
// from start of the last line to the selection end
|
||||
var top = (range.end.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
||||
var top = this.$getTop(range.end.row, layerConfig);
|
||||
var width = Math.round(range.end.column * layerConfig.characterWidth);
|
||||
|
||||
stringBuilder.push(
|
||||
|
|
@ -153,7 +148,7 @@ var Marker = function(parentEl) {
|
|||
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
|
||||
if (height < 0)
|
||||
return;
|
||||
var top = (range.start.row + 1 - layerConfig.firstRow) * layerConfig.lineHeight;
|
||||
var top = this.$getTop(range.start.row + 1, layerConfig);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
|
|
@ -164,11 +159,9 @@ var Marker = function(parentEl) {
|
|||
};
|
||||
|
||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) {
|
||||
var range = range.toScreenRange(this.doc);
|
||||
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
|
||||
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
||||
var top = this.$getTop(range.start.row, layerConfig);
|
||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||
|
||||
stringBuilder.push(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian DOT viereck AT gmail DOT com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -40,14 +43,15 @@ define(function(require, exports, module) {
|
|||
var oop = require("pilot/oop");
|
||||
var dom = require("pilot/dom");
|
||||
var lang = require("pilot/lang");
|
||||
var useragent = require("pilot/useragent");
|
||||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
var Text = function(parentEl) {
|
||||
this.element = document.createElement("div");
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_layer ace_text-layer";
|
||||
parentEl.appendChild(this.element);
|
||||
|
||||
this.$characterSize = this.$measureSizes();
|
||||
this.$characterSize = this.$measureSizes() || {width: 0, height: 0};
|
||||
this.$pollSizeChanges();
|
||||
};
|
||||
|
||||
|
|
@ -60,10 +64,6 @@ var Text = function(parentEl) {
|
|||
this.TAB_CHAR = "→";
|
||||
this.SPACE_CHAR = "·";
|
||||
|
||||
this.setTokenizer = function(tokenizer) {
|
||||
this.tokenizer = tokenizer;
|
||||
};
|
||||
|
||||
this.getLineHeight = function() {
|
||||
return this.$characterSize.height || 1;
|
||||
};
|
||||
|
|
@ -72,14 +72,18 @@ var Text = function(parentEl) {
|
|||
return this.$characterSize.width || 1;
|
||||
};
|
||||
|
||||
this.checkForSizeChanges = function() {
|
||||
var size = this.$measureSizes();
|
||||
if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
|
||||
this.$characterSize = size;
|
||||
this._dispatchEvent("changeCharaterSize", {data: size});
|
||||
}
|
||||
};
|
||||
|
||||
this.$pollSizeChanges = function() {
|
||||
var self = this;
|
||||
setInterval(function() {
|
||||
var size = self.$measureSizes();
|
||||
if (self.$characterSize.width !== size.width || self.$characterSize.height !== size.height) {
|
||||
self.$characterSize = size;
|
||||
self._dispatchEvent("changeCharaterSize", {data: size});
|
||||
}
|
||||
self.checkForSizeChanges();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
|
|
@ -89,27 +93,36 @@ var Text = function(parentEl) {
|
|||
fontWeight : 1,
|
||||
fontStyle : 1,
|
||||
lineHeight : 1
|
||||
},
|
||||
};
|
||||
|
||||
this.$measureSizes = function() {
|
||||
var n = 1000;
|
||||
if (!this.$measureNode) {
|
||||
var measureNode = this.$measureNode = document.createElement("div");
|
||||
var style = measureNode.style;
|
||||
|
||||
style.width = style.height = "auto";
|
||||
style.left = style.top = "-1000px";
|
||||
|
||||
style.visibility = "hidden";
|
||||
style.position = "absolute";
|
||||
style.overflow = "visible";
|
||||
style.whiteSpace = "nowrap";
|
||||
|
||||
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
|
||||
// that's why we have to measure many characters
|
||||
// Note: characterWidth can be a float!
|
||||
measureNode.innerHTML = lang.stringRepeat("Xy", n);
|
||||
document.body.insertBefore(measureNode, document.body.firstChild);
|
||||
var measureNode = this.$measureNode = dom.createElement("div");
|
||||
var style = measureNode.style;
|
||||
|
||||
style.width = style.height = "auto";
|
||||
style.left = style.top = (-n * 40) + "px";
|
||||
|
||||
style.visibility = "hidden";
|
||||
style.position = "absolute";
|
||||
style.overflow = "visible";
|
||||
style.whiteSpace = "nowrap";
|
||||
|
||||
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
|
||||
// that's why we have to measure many characters
|
||||
// Note: characterWidth can be a float!
|
||||
measureNode.innerHTML = lang.stringRepeat("Xy", n);
|
||||
|
||||
if (document.body) {
|
||||
document.body.appendChild(measureNode);
|
||||
} else {
|
||||
var container = this.element.parentNode;
|
||||
while (!dom.hasCssClass(container, "ace_editor"))
|
||||
container = container.parentNode;
|
||||
container.appendChild(measureNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var style = this.$measureNode.style;
|
||||
|
|
@ -122,53 +135,86 @@ var Text = function(parentEl) {
|
|||
height: this.$measureNode.offsetHeight,
|
||||
width: this.$measureNode.offsetWidth / (n * 2)
|
||||
};
|
||||
|
||||
// Size and width can be null if the editor is not visible or
|
||||
// detached from the document
|
||||
if (size.width == 0 && size.height == 0)
|
||||
return null;
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
this.setDocument = function(doc) {
|
||||
this.doc = doc;
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
||||
this.showInvisibles = false;
|
||||
this.setShowInvisibles = function(showInvisibles) {
|
||||
if (this.showInvisibles == showInvisibles)
|
||||
return false;
|
||||
|
||||
|
||||
this.showInvisibles = showInvisibles;
|
||||
return true;
|
||||
};
|
||||
|
||||
this.$tabStrings = [];
|
||||
this.$computeTabString = function() {
|
||||
var tabSize = this.doc.getTabSize();
|
||||
if (this.showInvisibles) {
|
||||
var halfTab = (tabSize) / 2;
|
||||
this.$tabString = "<span class='ace_invisible'>"
|
||||
+ new Array(Math.floor(halfTab)).join(" ")
|
||||
+ this.TAB_CHAR
|
||||
+ new Array(Math.ceil(halfTab)+1).join(" ")
|
||||
+ "</span>";
|
||||
} else {
|
||||
this.$tabString = new Array(tabSize+1).join(" ");
|
||||
var tabSize = this.session.getTabSize();
|
||||
var tabStr = this.$tabStrings = [0];
|
||||
for (var i = 1; i < tabSize + 1; i++) {
|
||||
if (this.showInvisibles) {
|
||||
tabStr.push("<span class='ace_invisible'>"
|
||||
+ this.TAB_CHAR
|
||||
+ new Array(i).join(" ")
|
||||
+ "</span>");
|
||||
} else {
|
||||
tabStr.push(new Array(i+1).join(" "));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.updateLines = function(layerConfig, firstRow, lastRow) {
|
||||
this.updateLines = function(config, firstRow, lastRow) {
|
||||
this.$computeTabString();
|
||||
this.config = layerConfig;
|
||||
|
||||
var first = Math.max(firstRow, layerConfig.firstRow);
|
||||
var last = Math.min(lastRow, layerConfig.lastRow);
|
||||
// Due to wrap line changes there can be new lines if e.g.
|
||||
// the line to updated wrapped in the meantime.
|
||||
if (this.config.lastRow != config.lastRow ||
|
||||
this.config.firstRow != config.firstRow) {
|
||||
this.scrollLines(config);
|
||||
}
|
||||
this.config = config;
|
||||
|
||||
var first = Math.max(firstRow, config.firstRow);
|
||||
var last = Math.min(lastRow, config.lastRow);
|
||||
|
||||
var lineElements = this.element.childNodes,
|
||||
lineElementsIdx = 0;
|
||||
|
||||
for (var row = config.firstRow; row < first; row++) {
|
||||
var foldLine = this.session.getFoldLine(row);
|
||||
if (foldLine) {
|
||||
if (foldLine.containsRow(first)) {
|
||||
break;
|
||||
} else {
|
||||
row = foldLine.end.row;
|
||||
}
|
||||
}
|
||||
lineElementsIdx ++;
|
||||
}
|
||||
|
||||
var lineElements = this.element.childNodes;
|
||||
var tokens = this.tokenizer.getTokens(first, last);
|
||||
for (var i=first; i<=last; i++) {
|
||||
var lineElement = lineElements[i - layerConfig.firstRow];
|
||||
var lineElement = lineElements[lineElementsIdx++];
|
||||
if (!lineElement)
|
||||
continue;
|
||||
|
||||
var html = [];
|
||||
this.$renderLine(html, i, tokens[i-first].tokens);
|
||||
dom.setInnerHtml(lineElement, html.join(""));
|
||||
var tokens = this.session.getTokens(i, i);
|
||||
this.$renderLine(html, i, tokens[0].tokens);
|
||||
lineElement = dom.setInnerHtml(lineElement, html.join(""));
|
||||
lineElement.style.height =
|
||||
this.session.getRowHeight(config, i) + "px";
|
||||
|
||||
i = this.session.getRowFoldEnd(i);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -186,11 +232,11 @@ var Text = function(parentEl) {
|
|||
var el = this.element;
|
||||
|
||||
if (oldConfig.firstRow < config.firstRow)
|
||||
for (var row=oldConfig.firstRow; row<config.firstRow; row++)
|
||||
for (var row=oldConfig.firstRow; row<config.firstRow; row = this.session.getRowFoldEnd(row) + 1)
|
||||
el.removeChild(el.firstChild);
|
||||
|
||||
if (oldConfig.lastRow > config.lastRow)
|
||||
for (var row=config.lastRow+1; row<=oldConfig.lastRow; row++)
|
||||
for (var row=config.lastRow+1; row<=oldConfig.lastRow; row = this.session.getRowFoldEnd(row) + 1)
|
||||
el.removeChild(el.lastChild);
|
||||
|
||||
if (config.firstRow < oldConfig.firstRow) {
|
||||
|
|
@ -200,7 +246,7 @@ var Text = function(parentEl) {
|
|||
else
|
||||
el.appendChild(fragment);
|
||||
}
|
||||
|
||||
|
||||
if (config.lastRow > oldConfig.lastRow) {
|
||||
var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
|
||||
el.appendChild(fragment);
|
||||
|
|
@ -209,19 +255,28 @@ var Text = function(parentEl) {
|
|||
|
||||
this.$renderLinesFragment = function(config, firstRow, lastRow) {
|
||||
var fragment = document.createDocumentFragment();
|
||||
var tokens = this.tokenizer.getTokens(firstRow, lastRow);
|
||||
for (var row=firstRow; row<=lastRow; row++) {
|
||||
var lineEl = document.createElement("div");
|
||||
var lineEl = dom.createElement("div");
|
||||
|
||||
lineEl.className = "ace_line";
|
||||
var style = lineEl.style;
|
||||
style.height = this.$characterSize.height + "px";
|
||||
style.height = this.session.getRowHeight(config, row) + "px";
|
||||
style.width = config.width + "px";
|
||||
|
||||
var html = [];
|
||||
this.$renderLine(html, row, tokens[row-firstRow].tokens);
|
||||
// Get the tokens per line as there might be some lines in between
|
||||
// beeing folded.
|
||||
// OPTIMIZE: If there is a long block of unfolded lines, just make
|
||||
// this call once for that big block of unfolded lines.
|
||||
var tokens = this.session.getTokens(row, row);
|
||||
if (tokens.length == 1)
|
||||
this.$renderLine(html, row, tokens[0].tokens);
|
||||
|
||||
// don't use setInnerHtml since we are working with an empty DIV
|
||||
lineEl.innerHTML = html.join("");
|
||||
fragment.appendChild(lineEl);
|
||||
|
||||
row = this.session.getRowFoldEnd(row);
|
||||
}
|
||||
return fragment;
|
||||
};
|
||||
|
|
@ -231,14 +286,12 @@ var Text = function(parentEl) {
|
|||
this.config = config;
|
||||
|
||||
var html = [];
|
||||
var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow);
|
||||
for (var i=config.firstRow; i<=config.lastRow; i++) {
|
||||
html.push("<div class='ace_line' style='height:" + this.$characterSize.height + "px;", "width:",
|
||||
config.width, "px'>");
|
||||
this.$renderLine(html, i, tokens[i-config.firstRow].tokens), html.push("</div>");
|
||||
}
|
||||
var tokens = this.session.getTokens(config.firstRow, config.lastRow)
|
||||
var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow);
|
||||
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
// Clear the current content of the element and add the rendered fragment.
|
||||
this.element.innerHTML = "";
|
||||
this.element.appendChild(fragment);
|
||||
};
|
||||
|
||||
this.$textToken = {
|
||||
|
|
@ -247,45 +300,186 @@ var Text = function(parentEl) {
|
|||
"lparen": true
|
||||
};
|
||||
|
||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||
// if (this.showInvisibles) {
|
||||
// var self = this;
|
||||
// var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]+/g;
|
||||
// var spaceReplace = function(space) {
|
||||
// var space = new Array(space.length+1).join(self.SPACE_CHAR);
|
||||
// return "<span class='ace_invisible'>" + space + "</span>";
|
||||
// };
|
||||
// }
|
||||
// else {
|
||||
var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/g;
|
||||
var spaceReplace = " ";
|
||||
// }
|
||||
|
||||
for ( var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
var output = token.value
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(spaceRe, spaceReplace)
|
||||
.replace(/\t/g, this.$tabString);
|
||||
|
||||
if (!this.$textToken[token.type]) {
|
||||
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
||||
stringBuilder.push("<span class='", classes, "'>", output, "</span>");
|
||||
this.$renderToken = function(stringBuilder, screenColumn, token, value) {
|
||||
var self = this;
|
||||
var replaceReg = /\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g;
|
||||
var replaceFunc = function(c, a, b, tabIdx, idx4) {
|
||||
if (c.charCodeAt(0) == 32) {
|
||||
return new Array(c.length+1).join(" ");
|
||||
} else if (c == "\t") {
|
||||
var tabSize = self.session.
|
||||
getScreenTabSize(screenColumn + tabIdx);
|
||||
screenColumn += tabSize - 1;
|
||||
return self.$tabStrings[tabSize];
|
||||
} else if (c == "&") {
|
||||
if (useragent.isOldGecko)
|
||||
return "&";
|
||||
else
|
||||
return "&";
|
||||
} else if (c == "<") {
|
||||
return "<";
|
||||
} else if (c.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)) {
|
||||
if (self.showInvisibles) {
|
||||
var space = new Array(c.length+1).join(self.SPACE_CHAR);
|
||||
return "<span class='ace_invisible'>" + space + "</span>";
|
||||
} else {
|
||||
return " ";
|
||||
}
|
||||
} else {
|
||||
screenColumn += 1;
|
||||
return "<span class='ace_cjk' style='width:" + (
|
||||
self.config.characterWidth * 2) +
|
||||
"px'>" + c + "</span>";
|
||||
}
|
||||
else {
|
||||
stringBuilder.push(output);
|
||||
}
|
||||
|
||||
var output = value.replace(replaceReg, replaceFunc);
|
||||
|
||||
if (!this.$textToken[token.type]) {
|
||||
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
||||
stringBuilder.push("<span class='", classes, "'>", output, "</span>");
|
||||
}
|
||||
else {
|
||||
stringBuilder.push(output);
|
||||
}
|
||||
return value.length;
|
||||
}
|
||||
|
||||
this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits) {
|
||||
var chars = 0,
|
||||
split = 0,
|
||||
splitChars,
|
||||
characterWidth = this.config.characterWidth,
|
||||
screenColumn = 0,
|
||||
self = this;
|
||||
|
||||
function addToken(token, value) {
|
||||
screenColumn += self.$renderToken(
|
||||
stringBuilder, screenColumn, token, value);
|
||||
}
|
||||
|
||||
if (!splits || splits.length == 0) {
|
||||
splitChars = Number.MAX_VALUE;
|
||||
} else {
|
||||
splitChars = splits[0];
|
||||
}
|
||||
|
||||
stringBuilder.push("<div style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>");
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
var value = token.value;
|
||||
|
||||
if (chars + value.length < splitChars) {
|
||||
addToken(token, value);
|
||||
chars += value.length;
|
||||
} else {
|
||||
while (chars + value.length >= splitChars) {
|
||||
addToken(token, value.substring(0, splitChars - chars));
|
||||
value = value.substring(splitChars - chars);
|
||||
chars = splitChars;
|
||||
stringBuilder.push("</div>",
|
||||
"<div style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>");
|
||||
|
||||
split ++;
|
||||
screenColumn = 0;
|
||||
splitChars = splits[split] || Number.MAX_VALUE;
|
||||
}
|
||||
if (value.length != 0) {
|
||||
chars += value.length;
|
||||
addToken(token, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.showInvisibles) {
|
||||
if (row !== this.doc.getLength() - 1) {
|
||||
if (lastRow !== this.session.getLength() - 1) {
|
||||
stringBuilder.push("<span class='ace_invisible'>" + this.EOL_CHAR + "</span>");
|
||||
} else {
|
||||
stringBuilder.push("<span class='ace_invisible'>" + this.EOF_CHAR + "</span>");
|
||||
}
|
||||
}
|
||||
stringBuilder.push("</div>");
|
||||
}
|
||||
|
||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||
// Check if the line to render is folded or not. If not, things are
|
||||
// simple, otherwise, we need to fake some things...
|
||||
if (!this.session.isRowFolded(row)) {
|
||||
var splits = this.session.getRowSplitData(row);
|
||||
this.$renderLineCore(stringBuilder, row, tokens, splits)
|
||||
} else {
|
||||
this.$renderFoldLine(stringBuilder, row, tokens, splits);
|
||||
}
|
||||
};
|
||||
|
||||
this.$renderFoldLine = function(stringBuilder, row, tokens) {
|
||||
var session = this.session,
|
||||
foldLine = session.getFoldLine(row),
|
||||
renderTokens = [];
|
||||
|
||||
function addTokens(tokens, from, to) {
|
||||
var idx = 0, col = 0;
|
||||
while ((col + tokens[idx].value.length) < from) {
|
||||
col += tokens[idx].value.length
|
||||
idx++
|
||||
|
||||
if (idx == tokens.length) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (col != from) {
|
||||
var value = tokens[idx].value.substring(from - col);
|
||||
// Check if the token value is longer then the from...to spacing.
|
||||
if (value.length > (to - from)) {
|
||||
value = value.substring(0, to - from);
|
||||
}
|
||||
|
||||
renderTokens.push({
|
||||
type: tokens[idx].type,
|
||||
value: value
|
||||
});
|
||||
|
||||
col = from + value.length;
|
||||
idx += 1
|
||||
}
|
||||
|
||||
while (col < to) {
|
||||
var value = tokens[idx].value;
|
||||
if (value.length + col > to) {
|
||||
value = value.substring(0, to - col);
|
||||
}
|
||||
renderTokens.push({
|
||||
type: tokens[idx].type,
|
||||
value: value
|
||||
});
|
||||
col += value.length;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
|
||||
if (placeholder) {
|
||||
renderTokens.push({
|
||||
type: "fold",
|
||||
value: placeholder
|
||||
});
|
||||
} else {
|
||||
if (isNewRow) {
|
||||
tokens = this.session.getTokens(row, row)[0].tokens;
|
||||
}
|
||||
if (tokens.length != 0) {
|
||||
addTokens(tokens, lastColumn, column);
|
||||
}
|
||||
}
|
||||
}.bind(this), foldLine.end.row, this.session.getLine(foldLine.end.row).length);
|
||||
|
||||
// TODO: Build a fake splits array!
|
||||
var splits = this.session.$wrapData[row];
|
||||
this.$renderLineCore(stringBuilder, row, renderTokens, splits);
|
||||
};
|
||||
|
||||
}).call(Text.prototype);
|
||||
|
|
|
|||
128
lib/ace/mode/c_cpp.js
Normal file
128
lib/ace/mode/c_cpp.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Gastón Kleiman <gaston.kleiman AT gmail DOT com>
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var c_cppHighlightRules = require("ace/mode/c_cpp_highlight_rules").c_cppHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new c_cppHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)\/\//;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, "//");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
} else if (state == "doc-start") {
|
||||
if (endState == "start") {
|
||||
return "";
|
||||
}
|
||||
var match = line.match(/^\s*(\/?)\*/);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
indent += " ";
|
||||
}
|
||||
indent += "* ";
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
172
lib/ace/mode/c_cpp_highlight_rules.js
Normal file
172
lib/ace/mode/c_cpp_highlight_rules.js
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Gastón Kleiman <gaston.kleiman AT gmail DOT com>
|
||||
*
|
||||
* Based on Bespin's C/C++ Syntax Plugin by Marc McIntyre.
|
||||
*
|
||||
* 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 DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var c_cppHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("and|double|not_eq|throw|and_eq|dynamic_cast|operator|true|" +
|
||||
"asm|else|or|try|auto|enum|or_eq|typedef|bitand|explicit|private|" +
|
||||
"typeid|bitor|extern|protected|typename|bool|false|public|union|" +
|
||||
"break|float|register|unsigned|case|fro|reinterpret-cast|using|catch|" +
|
||||
"friend|return|virtual|char|goto|short|void|class|if|signed|volatile|" +
|
||||
"compl|inline|sizeof|wchar_t|const|int|static|while|const-cast|long|" +
|
||||
"static_cast|xor|continue|mutable|struct|xor_eq|default|namespace|" +
|
||||
"switch|delete|new|template|do|not|this|for").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("NULL").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant", // <CONSTANT>
|
||||
regex : "<[a-zA-Z0-9.]+>"
|
||||
}, {
|
||||
token : "keyword", // pre-compiler directivs
|
||||
regex : "(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
};
|
||||
|
||||
oop.inherits(c_cppHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.c_cppHighlightRules = c_cppHighlightRules;
|
||||
});
|
||||
123
lib/ace/mode/clojure.js
Normal file
123
lib/ace/mode/clojure.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>
|
||||
* Carin Meier
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var ClojureHighlightRules = require("ace/mode/clojure_highlight_rules").ClojureHighlightRules;
|
||||
var MatchingParensOutdent = require("ace/mode/matching_parens_outdent").MatchingParensOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new ClojureHighlightRules().getRules());
|
||||
this.$outdent = new MatchingParensOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)#/;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, ";");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var startingIndent = indent;
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/[\(\[]/);
|
||||
if (match) {
|
||||
indent += " ";
|
||||
}
|
||||
match = line.match(/[\)]/);
|
||||
if (match) {
|
||||
indent = "";
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
235
lib/ace/mode/clojure_highlight_rules.js
Normal file
235
lib/ace/mode/clojure_highlight_rules.js
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>
|
||||
* Carin Meier
|
||||
*
|
||||
* 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 TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
|
||||
|
||||
var ClojureHighlightRules = function() {
|
||||
|
||||
var builtinFunctions = lang.arrayToMap(
|
||||
('* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* ' +
|
||||
'*command-line-args* *compile-files* *compile-path* *e *err* *file* ' +
|
||||
'*flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* ' +
|
||||
'*print-dup* *print-length* *print-level* *print-meta* *print-readably* ' +
|
||||
'*read-eval* *source-path* *use-context-classloader* ' +
|
||||
'*warn-on-reflection* + - -> -> ->> ->> .. / < < <= <= = ' +
|
||||
'== > > >= >= accessor aclone ' +
|
||||
'add-classpath add-watch agent agent-errors aget alength alias all-ns ' +
|
||||
'alter alter-meta! alter-var-root amap ancestors and apply areduce ' +
|
||||
'array-map aset aset-boolean aset-byte aset-char aset-double aset-float ' +
|
||||
'aset-int aset-long aset-short assert assoc assoc! assoc-in associative? ' +
|
||||
'atom await await-for await1 bases bean bigdec bigint binding bit-and ' +
|
||||
'bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left ' +
|
||||
'bit-shift-right bit-test bit-xor boolean boolean-array booleans ' +
|
||||
'bound-fn bound-fn* butlast byte byte-array bytes cast char char-array ' +
|
||||
'char-escape-string char-name-string char? chars chunk chunk-append ' +
|
||||
'chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? ' +
|
||||
'class class? clear-agent-errors clojure-version coll? comment commute ' +
|
||||
'comp comparator compare compare-and-set! compile complement concat cond ' +
|
||||
'condp conj conj! cons constantly construct-proxy contains? count ' +
|
||||
'counted? create-ns create-struct cycle dec decimal? declare definline ' +
|
||||
'defmacro defmethod defmulti defn defn- defonce defstruct delay delay? ' +
|
||||
'deliver deref derive descendants destructure disj disj! dissoc dissoc! ' +
|
||||
'distinct distinct? doall doc dorun doseq dosync dotimes doto double ' +
|
||||
'double-array doubles drop drop-last drop-while empty empty? ensure ' +
|
||||
'enumeration-seq eval even? every? false? ffirst file-seq filter find ' +
|
||||
'find-doc find-ns find-var first float float-array float? floats flush ' +
|
||||
'fn fn? fnext for force format future future-call future-cancel ' +
|
||||
'future-cancelled? future-done? future? gen-class gen-interface gensym ' +
|
||||
'get get-in get-method get-proxy-class get-thread-bindings get-validator ' +
|
||||
'hash hash-map hash-set identical? identity if-let if-not ifn? import ' +
|
||||
'in-ns inc init-proxy instance? int int-array integer? interleave intern ' +
|
||||
'interpose into into-array ints io! isa? iterate iterator-seq juxt key ' +
|
||||
'keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list ' +
|
||||
'list* list? load load-file load-reader load-string loaded-libs locking ' +
|
||||
'long long-array longs loop macroexpand macroexpand-1 make-array ' +
|
||||
'make-hierarchy map map? mapcat max max-key memfn memoize merge ' +
|
||||
'merge-with meta method-sig methods min min-key mod name namespace neg? ' +
|
||||
'newline next nfirst nil? nnext not not-any? not-empty not-every? not= ' +
|
||||
'ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ' +
|
||||
'ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? ' +
|
||||
'or parents partial partition pcalls peek persistent! pmap pop pop! ' +
|
||||
'pop-thread-bindings pos? pr pr-str prefer-method prefers ' +
|
||||
'primitives-classnames print print-ctor print-doc print-dup print-method ' +
|
||||
'print-namespace-doc print-simple print-special-doc print-str printf ' +
|
||||
'println println-str prn prn-str promise proxy proxy-call-with-super ' +
|
||||
'proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot ' +
|
||||
'rand rand-int range ratio? rational? rationalize re-find re-groups ' +
|
||||
're-matcher re-matches re-pattern re-seq read read-line read-string ' +
|
||||
'reduce ref ref-history-count ref-max-history ref-min-history ref-set ' +
|
||||
'refer refer-clojure release-pending-sends rem remove remove-method ' +
|
||||
'remove-ns remove-watch repeat repeatedly replace replicate require ' +
|
||||
'reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq ' +
|
||||
'rsubseq second select-keys send send-off seq seq? seque sequence ' +
|
||||
'sequential? set set-validator! set? short short-array shorts ' +
|
||||
'shutdown-agents slurp some sort sort-by sorted-map sorted-map-by ' +
|
||||
'sorted-set sorted-set-by sorted? special-form-anchor special-symbol? ' +
|
||||
'split-at split-with str stream? string? struct struct-map subs subseq ' +
|
||||
'subvec supers swap! symbol symbol? sync syntax-symbol-anchor take ' +
|
||||
'take-last take-nth take-while test the-ns time to-array to-array-2d ' +
|
||||
'trampoline transient tree-seq true? type unchecked-add unchecked-dec ' +
|
||||
'unchecked-divide unchecked-inc unchecked-multiply unchecked-negate ' +
|
||||
'unchecked-remainder unchecked-subtract underive unquote ' +
|
||||
'unquote-splicing update-in update-proxy use val vals var-get var-set ' +
|
||||
'var? vary-meta vec vector vector? when when-first when-let when-not ' +
|
||||
'while with-bindings with-bindings* with-in-str with-loading-context ' +
|
||||
'with-local-vars with-meta with-open with-out-str with-precision xml-seq ' +
|
||||
'zero? zipmap ').split(" ")
|
||||
);
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("def do fn if let loop monitor-enter monitor-exit new quote recur set! ' +
|
||||
'throw try var").split(" ")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("true false nil").split(" ")
|
||||
);
|
||||
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
|
||||
{
|
||||
token : "comment",
|
||||
regex : ";.*$"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "^\=begin$",
|
||||
next : "comment"
|
||||
},
|
||||
{
|
||||
token : "keyword", //parens
|
||||
regex : "[\\(|\\)]"
|
||||
},
|
||||
{
|
||||
token : "keyword", //lists
|
||||
regex : "[\\'\\(]"
|
||||
},
|
||||
{
|
||||
token : "keyword", //vectors
|
||||
regex : "[\\[|\\]]"
|
||||
},
|
||||
{
|
||||
token : "keyword", //sets and maps
|
||||
regex : "[\\{|\\}|\\#\\{|\\#\\}]"
|
||||
},
|
||||
{
|
||||
token : "keyword", // ampersands
|
||||
regex : '[\\&]'
|
||||
},
|
||||
{
|
||||
token : "keyword", // metadata
|
||||
regex : '[\\#\\^\\{]'
|
||||
},
|
||||
{
|
||||
token : "keyword", // anonymous fn syntactic sugar
|
||||
regex : '[\\%]'
|
||||
},
|
||||
{
|
||||
token : "keyword", // deref reader macro
|
||||
regex : '[@]'
|
||||
},
|
||||
{
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
},
|
||||
{
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
},
|
||||
{
|
||||
token : "constant.language",
|
||||
regex : '[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]'
|
||||
},
|
||||
|
||||
{
|
||||
token : function(value) {
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
},
|
||||
{
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
},
|
||||
{
|
||||
token : "string", // symbol
|
||||
regex : "[:](?:[a-zA-Z]|\d)+"
|
||||
},
|
||||
{
|
||||
token : "string.regexp", //Regular Expressions
|
||||
regex : '/#"(?:\.|(\\\")|[^\""\n])*"/g'
|
||||
}
|
||||
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : "^\=end$",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(ClojureHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.ClojureHighlightRules = ClojureHighlightRules;
|
||||
});
|
||||
99
lib/ace/mode/coffee.js
Normal file
99
lib/ace/mode/coffee.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* ***** 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):
|
||||
* Satoshi Murakami <murky.satyr AT gmail DOT com>
|
||||
*
|
||||
* 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 Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var Rules = require("ace/mode/coffee_highlight_rules").CoffeeHighlightRules;
|
||||
var Outdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
var TextMode = require("ace/mode/text").Mode;
|
||||
var oop = require("pilot/oop")
|
||||
|
||||
function CoffeeMode() {
|
||||
this.$tokenizer = new Tokenizer(new Rules().getRules());
|
||||
this.$outdent = new Outdent();
|
||||
};
|
||||
|
||||
oop.inherits(CoffeeMode, TextMode);
|
||||
|
||||
var proto = CoffeeMode.prototype;
|
||||
var indenter = /(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/;
|
||||
var commentLine = /^(\s*)#/;
|
||||
var hereComment = /^\s*###(?!#)/;
|
||||
var indentation = /^\s*/;
|
||||
|
||||
proto.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
|
||||
|
||||
if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&
|
||||
state === 'start' && indenter.test(line))
|
||||
indent += tab;
|
||||
return indent;
|
||||
};
|
||||
|
||||
proto.toggleCommentLines = function(state, doc, startRow, endRow){
|
||||
console.log("toggle");
|
||||
var range = new Range(0, 0, 0, 0);
|
||||
for (var i = startRow; i <= endRow; ++i) {
|
||||
var line = doc.getLine(i);
|
||||
if (hereComment.test(line))
|
||||
continue;
|
||||
|
||||
if (commentLine.test(line))
|
||||
line = line.replace(commentLine, '$1');
|
||||
else
|
||||
line = line.replace(indentation, '$&#');
|
||||
|
||||
range.end.row = range.start.row = i;
|
||||
range.end.column = line.length + 1;
|
||||
doc.replace(range, line);
|
||||
}
|
||||
};
|
||||
|
||||
proto.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
proto.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
exports.Mode = CoffeeMode;
|
||||
|
||||
});
|
||||
182
lib/ace/mode/coffee_highlight_rules.js
Normal file
182
lib/ace/mode/coffee_highlight_rules.js
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* ***** 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):
|
||||
* Satoshi Murakami <murky.satyr AT gmail DOT com>
|
||||
*
|
||||
* 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) {
|
||||
|
||||
require("pilot/oop").inherits(
|
||||
CoffeeHighlightRules,
|
||||
require("ace/mode/text_highlight_rules").TextHighlightRules);
|
||||
|
||||
function CoffeeHighlightRules() {
|
||||
var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"
|
||||
, keywordend = "(?![$\\w]|\\s*:)"
|
||||
, stringfill = {token: "string", regex: ".+"}
|
||||
;
|
||||
this.$rules =
|
||||
{ start:
|
||||
[ { token: "identifier"
|
||||
, regex: "(?:@|(?:\\.|::)\\s*)" + identifier
|
||||
}
|
||||
, { token: "keyword"
|
||||
, regex: "(?:t(?:h(?:is|row|en)|ry|ypeof)|s(?:uper|witch)|return|b(?:reak|y)|c(?:ontinue|atch|lass)|i(?:n(?:stanceof)?|s(?:nt)?|f)|e(?:lse|xtends)|f(?:or (?:own)?|inally|unction)|wh(?:ile|en)|n(?:ew|ot?)|d(?:e(?:lete|bugger)|o)|loop|o(?:ff?|[rn])|un(?:less|til)|and|yes)" + keywordend
|
||||
}
|
||||
, { token: "constant.language"
|
||||
, regex: "(?:true|false|null|undefined)" + keywordend
|
||||
}
|
||||
, { token: "invalid.illegal"
|
||||
, regex: "(?:c(?:ase|onst)|default|function|v(?:ar|oid)|with|e(?:num|xport)|i(?:mplements|nterface)|let|p(?:ackage|r(?:ivate|otected)|ublic)|static|yield|__(?:hasProp|extends|slice|bind|indexOf))" + keywordend
|
||||
}
|
||||
, { token: "language.support.class"
|
||||
, regex: "(?:Array|Boolean|Date|Function|Number|Object|R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|TypeError|URIError)" + keywordend
|
||||
}
|
||||
, { token: "language.support.function"
|
||||
, regex: "(?:Math|JSON|is(?:NaN|Finite)|parse(?:Int|Float)|encodeURI(?:Component)?|decodeURI(?:Component)?)" + keywordend
|
||||
}
|
||||
, { token: "identifier"
|
||||
, regex: identifier
|
||||
}
|
||||
, { token: "constant.numeric"
|
||||
, regex: "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "'''"
|
||||
, next : "qdoc"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: '"""'
|
||||
, next : "qqdoc"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "'"
|
||||
, next : "qstring"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: '"'
|
||||
, next : "qqstring"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "`"
|
||||
, next : "js"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "///"
|
||||
, next : "heregex"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: "###(?!#)"
|
||||
, next : "comment"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: "#.*"
|
||||
}
|
||||
, { token: "lparen"
|
||||
, regex: "[({[]"
|
||||
}
|
||||
, { token: "rparen"
|
||||
, regex: "[\\]})]"
|
||||
}
|
||||
, { token: "keyword.operator"
|
||||
, regex: "\\S+"
|
||||
}
|
||||
, { token: "text"
|
||||
, regex: "\\s+"
|
||||
}
|
||||
]
|
||||
, qdoc:
|
||||
[ { token: "string"
|
||||
, regex: ".*?'''"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qqdoc:
|
||||
[ { token: "string"
|
||||
, regex: '.*?"""'
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qstring:
|
||||
[ { token: "string"
|
||||
, regex: "[^\\\\']*(?:\\\\.[^\\\\']*)*'"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qqstring:
|
||||
[ { token: "string"
|
||||
, regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"'
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, js:
|
||||
[ { token: "string"
|
||||
, regex: "[^\\\\`]*(?:\\\\.[^\\\\`]*)*`"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, heregex:
|
||||
[ { token: "string.regex"
|
||||
, regex: '.*?///[imgy]{0,4}'
|
||||
, next : "start"
|
||||
}
|
||||
, { token: "comment.regex"
|
||||
, regex: "\\s+(?:#.*)?"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "\\S+"
|
||||
}
|
||||
]
|
||||
, comment:
|
||||
[ { token: "comment"
|
||||
, regex: '.*?###'
|
||||
, next : "start"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exports.CoffeeHighlightRules = CoffeeHighlightRules;
|
||||
});
|
||||
54
lib/ace/mode/csharp.js
Normal file
54
lib/ace/mode/csharp.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var CSharpHighlightRules = require("ace/mode/csharp_highlight_rules").CSharpHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new CSharpHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
|
||||
this.createWorker = function(session) {
|
||||
return null;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
123
lib/ace/mode/csharp_highlight_rules.js
Normal file
123
lib/ace/mode/csharp_highlight_rules.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var CSharpHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
var keywords = lang.arrayToMap(
|
||||
("abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("null|true|false").split("|")
|
||||
);
|
||||
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
};
|
||||
|
||||
oop.inherits(CSharpHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.CSharpHighlightRules = CSharpHighlightRules;
|
||||
});
|
||||
|
|
@ -73,7 +73,7 @@ oop.inherits(Mode, TextMode);
|
|||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
return this.$outdent.autoOutdent(doc, row);
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
var CssHighlightRules = function() {
|
||||
|
||||
var properties = lang.arrayToMap(
|
||||
("azimuth|background-attachment|background-color|background-image|" +
|
||||
("-moz-box-sizing|-webkit-box-sizing|azimuth|background-attachment|background-color|background-image|" +
|
||||
"background-position|background-repeat|background|border-bottom-color|" +
|
||||
"border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
|
||||
"border-color|border-left-color|border-left-style|border-left-width|" +
|
||||
"border-left|border-right-color|border-right-style|border-right-width|" +
|
||||
"border-right|border-spacing|border-style|border-top-color|" +
|
||||
"border-top-style|border-top-width|border-top|border-width|border|" +
|
||||
"bottom|caption-side|clear|clip|color|content|counter-increment|" +
|
||||
"bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
|
||||
"counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
|
||||
"elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
|
||||
"font-stretch|font-style|font-variant|font-weight|font|height|left|" +
|
||||
|
|
@ -76,8 +76,8 @@ var CssHighlightRules = function() {
|
|||
|
||||
var constants = lang.arrayToMap(
|
||||
("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
|
||||
"block|bold|bolder|both|bottom|break-all|break-word|capitalize|center|" +
|
||||
"char|circle|cjk-ideographic|col-resize|collapse|crosshair|dashed|" +
|
||||
"block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
|
||||
"char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
|
||||
"decimal-leading-zero|decimal|default|disabled|disc|" +
|
||||
"distribute-all-lines|distribute-letter|distribute-space|" +
|
||||
"distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
|
||||
|
|
@ -198,16 +198,16 @@ var CssHighlightRules = function() {
|
|||
regex : "\}"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (properties[value.toLowerCase()]) {
|
||||
if (properties.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.type";
|
||||
}
|
||||
else if (functions[value.toLowerCase()]) {
|
||||
else if (functions.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.function";
|
||||
}
|
||||
else if (constants[value.toLowerCase()]) {
|
||||
else if (constants.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.constant";
|
||||
}
|
||||
else if (colors[value.toLowerCase()]) {
|
||||
else if (colors.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.constant.color";
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -35,22 +35,26 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
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");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.mode = new CssMode();
|
||||
},
|
||||
|
||||
"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,10 +74,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,12 +35,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var CssMode = require("ace/mode/css").Mode;
|
||||
var assert = require("../assertions");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.tokenizer = new CssMode().getTokenizer();
|
||||
},
|
||||
|
|
@ -84,11 +88,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test, "css tokenizer");
|
||||
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ oop.inherits(Mode, TextMode);
|
|||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
return this.$delegate("toggleCommentLines", arguments, function() {
|
||||
this.$delegate("toggleCommentLines", arguments, function() {
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
|
@ -74,7 +74,7 @@ oop.inherits(Mode, TextMode);
|
|||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
return this.$delegate("autoOutdent", arguments);
|
||||
this.$delegate("autoOutdent", arguments);
|
||||
};
|
||||
|
||||
this.$delegate = function(method, args, defaultHandler) {
|
||||
|
|
@ -91,7 +91,7 @@ oop.inherits(Mode, TextMode);
|
|||
args[0] = split[1];
|
||||
return this.$css[method].apply(this.$css, args);
|
||||
}
|
||||
|
||||
|
||||
return defaultHandler ? defaultHandler() : undefined;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,36 @@ var HtmlHighlightRules = function() {
|
|||
// regexp must not have capturing parentheses
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
function string(state) {
|
||||
return [
|
||||
{
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*$',
|
||||
next : state + "-qqstring"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*$",
|
||||
next : state + "-qstring"
|
||||
}]
|
||||
}
|
||||
|
||||
function multiLineString(quote, state) {
|
||||
return [{
|
||||
token : "string",
|
||||
regex : ".*" + quote,
|
||||
next : state
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}]
|
||||
}
|
||||
|
||||
this.$rules = {
|
||||
start : [ {
|
||||
token : "text",
|
||||
|
|
@ -89,13 +119,7 @@ var HtmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
}].concat(string("script")),
|
||||
|
||||
css : [ {
|
||||
token : "text",
|
||||
|
|
@ -107,13 +131,7 @@ var HtmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
}].concat(string("css")),
|
||||
|
||||
tag : [ {
|
||||
token : "text",
|
||||
|
|
@ -125,14 +143,15 @@ var HtmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
|
||||
}].concat(string("tag")),
|
||||
|
||||
"css-qstring": multiLineString("'", "css"),
|
||||
"css-qqstring": multiLineString('"', "css"),
|
||||
"script-qstring": multiLineString("'", "script"),
|
||||
"script-qqstring": multiLineString('"', "script"),
|
||||
"tag-qstring": multiLineString("'", "tag"),
|
||||
"tag-qqstring": multiLineString('"', "tag"),
|
||||
|
||||
cdata : [ {
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
|
|
|
|||
|
|
@ -35,24 +35,28 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
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");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.mode = new HtmlMode();
|
||||
},
|
||||
|
||||
"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,10 +66,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,12 +35,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var HtmlMode = require("ace/mode/html").Mode;
|
||||
var assert = require("../assertions");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.tokenizer = new HtmlMode().getTokenizer();
|
||||
},
|
||||
|
|
@ -62,13 +66,27 @@ var Test = {
|
|||
assert.equal("text", tokens[8].type);
|
||||
assert.equal("keyword", tokens[9].type);
|
||||
assert.equal("text", tokens[10].type);
|
||||
}
|
||||
},
|
||||
|
||||
"test: tokenize multiline attribute value with double quotes": function() {
|
||||
var line1 = this.tokenizer.getLineTokens('<a href="abc', "start");
|
||||
var t1 = line1.tokens;
|
||||
var t2 = this.tokenizer.getLineTokens('def">', line1.state).tokens;
|
||||
assert.equal(t1[t1.length-1].type, "string");
|
||||
assert.equal(t2[0].type, "string");
|
||||
},
|
||||
|
||||
"test: tokenize multiline attribute value with single quotes": function() {
|
||||
var line1 = this.tokenizer.getLineTokens('<a href=\'abc', "start");
|
||||
var t1 = line1.tokens;
|
||||
var t2 = this.tokenizer.getLineTokens('def\'>', line1.state).tokens;
|
||||
assert.equal(t1[t1.length-1].type, "string");
|
||||
assert.equal(t2[0].type, "string");
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
24
lib/ace/mode/java.js
Normal file
24
lib/ace/mode/java.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var JavaHighlightRules = require("ace/mode/java_highlight_rules").JavaHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new JavaHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, JavaScriptMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.createWorker = function(session) {
|
||||
return null;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
167
lib/ace/mode/java_highlight_rules.js
Normal file
167
lib/ace/mode/java_highlight_rules.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var JavaHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
|
||||
// taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
|
||||
var keywords = lang.arrayToMap(
|
||||
("abstract|continue|for|new|switch|" +
|
||||
"assert|default|goto|package|synchronized|" +
|
||||
"boolean|do|if|private|this|" +
|
||||
"break|double|implements|protected|throw|" +
|
||||
"byte|else|import|public|throws|" +
|
||||
"case|enum|instanceof|return|transient|" +
|
||||
"catch|extends|int|short|try|" +
|
||||
"char|final|interface|static|void|" +
|
||||
"class|finally|long|strictfp|volatile|" +
|
||||
"const|float|native|super|while").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("null|Infinity|NaN|undefined").split("|")
|
||||
);
|
||||
|
||||
var langClasses = lang.arrayToMap(
|
||||
("AbstractMethodError|AssertionError|ClassCircularityError|"+
|
||||
"ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
|
||||
"ExceptionInInitializerError|IllegalAccessError|"+
|
||||
"IllegalThreadStateException|InstantiationError|InternalError|"+
|
||||
"NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
|
||||
"ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
|
||||
"SuppressWarnings|TypeNotPresentException|UnknownError|"+
|
||||
"UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
|
||||
"InstantiationException|IndexOutOfBoundsException|"+
|
||||
"ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
|
||||
"NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
|
||||
"SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
|
||||
"InterruptedException|NoSuchMethodException|IllegalAccessException|"+
|
||||
"UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
|
||||
"Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
|
||||
"NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
|
||||
"NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
|
||||
"Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
|
||||
"Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
|
||||
"StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
|
||||
"ArrayStoreException|ClassCastException|LinkageError|"+
|
||||
"NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
|
||||
"Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
|
||||
"Cloneable|Class|CharSequence|Comparable|String|Object").split("|")
|
||||
);
|
||||
|
||||
var importClasses = lang.arrayToMap(
|
||||
("").split("|")
|
||||
);
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (langClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (importClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
};
|
||||
|
||||
oop.inherits(JavaHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.JavaHighlightRules = JavaHighlightRules;
|
||||
});
|
||||
|
|
@ -43,6 +43,7 @@ var Tokenizer = require("ace/tokenizer").Tokenizer;
|
|||
var JavaScriptHighlightRules = require("ace/mode/javascript_highlight_rules").JavaScriptHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
var WorkerClient = require("ace/worker/worker_client").WorkerClient;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());
|
||||
|
|
@ -68,16 +69,16 @@ oop.inherits(Mode, TextMode);
|
|||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i).replace(re, "$1");
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = line.length + 2;
|
||||
doc.replace(deleteRange, line);
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
else {
|
||||
return doc.indentRows(startRow, endRow, "//");
|
||||
doc.indentRows(startRow, endRow, "//");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -118,7 +119,48 @@ oop.inherits(Mode, TextMode);
|
|||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
return this.$outdent.autoOutdent(doc, row);
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
this.createWorker = function(session) {
|
||||
var doc = session.getDocument();
|
||||
var worker = new WorkerClient(["ace", "pilot"], "worker-javascript.js", "ace/mode/javascript_worker", "JavaScriptWorker");
|
||||
worker.call("setValue", [doc.getValue()]);
|
||||
|
||||
doc.on("change", function(e) {
|
||||
e.range = {
|
||||
start: e.data.range.start,
|
||||
end: e.data.range.end
|
||||
};
|
||||
worker.emit("change", e);
|
||||
});
|
||||
|
||||
worker.on("jslint", function(results) {
|
||||
var errors = [];
|
||||
for (var i=0; i<results.data.length; i++) {
|
||||
var error = results.data[i];
|
||||
if (error)
|
||||
errors.push({
|
||||
row: error.line-1,
|
||||
column: error.character-1,
|
||||
text: error.reason,
|
||||
type: "warning",
|
||||
lint: error
|
||||
})
|
||||
}
|
||||
|
||||
session.setAnnotations(errors)
|
||||
});
|
||||
|
||||
worker.on("narcissus", function(e) {
|
||||
session.setAnnotations([e.data]);
|
||||
});
|
||||
|
||||
worker.on("terminate", function() {
|
||||
session.clearAnnotations();
|
||||
});
|
||||
|
||||
return worker;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -42,22 +43,23 @@ var lang = require("pilot/lang");
|
|||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
JavaScriptHighlightRules = function() {
|
||||
var JavaScriptHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
|
||||
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("|")
|
||||
"if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|" +
|
||||
"const|yield|import|get|set").split("|")
|
||||
);
|
||||
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("null|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("|")
|
||||
("class|enum|extends|super|export|implements|private|" +
|
||||
"public|interface|package|protected|static").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
|
|
@ -65,102 +67,105 @@ JavaScriptHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords[value])
|
||||
return "keyword";
|
||||
else if (buildinConstants[value])
|
||||
return "constant.language";
|
||||
else if (futureReserved[value])
|
||||
return "invalid.illegal";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (futureReserved.hasOwnProperty(value))
|
||||
return "invalid.illegal";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: "^#!.*$"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,14 +35,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
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");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.mode = new JavaScriptMode();
|
||||
},
|
||||
|
|
@ -57,39 +61,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,22 +136,20 @@ 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);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,12 +35,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var assert = require("../assertions");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.tokenizer = new JavaScriptMode().getTokenizer();
|
||||
},
|
||||
|
|
@ -98,13 +102,16 @@ var Test = {
|
|||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("rparen", tokens[0].type);
|
||||
},
|
||||
|
||||
"test tokenize regular expressions": function() {
|
||||
var tokens = this.tokenizer.getLineTokens("a/b/c", "start").tokens;
|
||||
assert.equal(5, tokens.length);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
48
lib/ace/mode/javascript_worker.js
Normal file
48
lib/ace/mode/javascript_worker.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var Mirror = require("ace/worker/mirror").Mirror;
|
||||
//var lint = require("ace/worker/jslint").JSLINT;
|
||||
var lint = require("ace/worker/jshint").JSHINT;
|
||||
|
||||
var JavaScriptWorker = exports.JavaScriptWorker = function(sender) {
|
||||
Mirror.call(this, sender);
|
||||
this.setTimeout(500);
|
||||
};
|
||||
|
||||
oop.inherits(JavaScriptWorker, Mirror);
|
||||
|
||||
(function() {
|
||||
|
||||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
value = value.replace(/^#!.*\n/, "\n");
|
||||
|
||||
// var start = new Date();
|
||||
var parser = require("ace/narcissus/jsparse");
|
||||
try {
|
||||
parser.parse(value);
|
||||
} catch(e) {
|
||||
// console.log("narcissus")
|
||||
// console.log(e);
|
||||
this.sender.emit("narcissus", {
|
||||
row: e.lineno-1,
|
||||
column: null, // TODO convert e.cursor
|
||||
text: e.message,
|
||||
type: "error"
|
||||
});
|
||||
return;
|
||||
} finally {
|
||||
// console.log("parse time: " + (new Date() - start));
|
||||
}
|
||||
|
||||
// var start = new Date();
|
||||
// console.log("jslint")
|
||||
lint(value, {undef: false, onevar: false, passfail: false});
|
||||
this.sender.emit("jslint", lint.errors);
|
||||
// console.log("lint time: " + (new Date() - start));
|
||||
}
|
||||
|
||||
}).call(JavaScriptWorker.prototype);
|
||||
|
||||
});
|
||||
|
|
@ -35,56 +35,47 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
exports.bindings = {
|
||||
"save": "Ctrl-S",
|
||||
"saveas": "Ctrl-Shift-S",
|
||||
"selectall": "Ctrl-A",
|
||||
"removeline": "Ctrl-D",
|
||||
"gotoline": "Ctrl-L",
|
||||
"togglecomment": "Ctrl-7",
|
||||
"findnext": "Ctrl-K",
|
||||
"findprevious": "Ctrl-Shift-K",
|
||||
"find": "Ctrl-F",
|
||||
"replace": "Ctrl-R",
|
||||
"undo": "Ctrl-Z",
|
||||
"redo": "Ctrl-Shift-Z|Ctrl-Y",
|
||||
"overwrite": "Insert",
|
||||
"copylinesup": "Ctrl-Alt-Up",
|
||||
"movelinesup": "Alt-Up",
|
||||
"selecttostart": "Alt-Shift-Up",
|
||||
"gotostart": "Ctrl-Home|Ctrl-Up",
|
||||
"selectup": "Shift-Up",
|
||||
"golineup": "Up",
|
||||
"copylinesdown": "Ctrl-Alt-Down",
|
||||
"movelinesdown": "Alt-Down",
|
||||
"selecttoend": "Alt-Shift-Down",
|
||||
"gotoend": "Ctrl-End|Ctrl-Down",
|
||||
"selectdown": "Shift-Down",
|
||||
"golinedown": "Down",
|
||||
"selectwordleft": "Ctrl-Shift-Left",
|
||||
"gotowordleft": "Ctrl-Left",
|
||||
"selecttolinestart": "Alt-Shift-Left",
|
||||
"gotolinestart": "Alt-Left|Home",
|
||||
"selectleft": "Shift-Left",
|
||||
"gotoleft": "Left",
|
||||
"selectwordright": "Ctrl-Shift-Right",
|
||||
"gotowordright": "Ctrl-Right",
|
||||
"selecttolineend": "Alt-Shift-Right",
|
||||
"gotolineend": "Alt-Right|End",
|
||||
"selectright": "Shift-Right",
|
||||
"gotoright": "Right",
|
||||
"selectpagedown": "Shift-PageDown",
|
||||
"pagedown": "PageDown",
|
||||
"selectpageup": "Shift-PageUp",
|
||||
"pageup": "PageUp",
|
||||
"selectlinestart": "Shift-Home",
|
||||
"selectlineend": "Shift-End",
|
||||
"del": "Delete",
|
||||
"backspace": "Backspace",
|
||||
"outdent": "Shift-Tab",
|
||||
"indent": "Tab"
|
||||
var assert = require("ace/test/assertions");
|
||||
var JavaScriptWorker = require("ace/mode/javascript_worker").JavaScriptWorker;
|
||||
|
||||
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.sender = {
|
||||
on: function() {},
|
||||
callback: function(data, id) {
|
||||
this.data = data;
|
||||
},
|
||||
events: [],
|
||||
emit: function(type, e) {
|
||||
this.events.push([type, e])
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"test check for syntax error": function() {
|
||||
var worker = new JavaScriptWorker(this.sender);
|
||||
worker.setValue("Juhu Kinners");
|
||||
worker.deferredUpdate.call();
|
||||
assert.equal(this.sender.events[0][1].type, "error");
|
||||
},
|
||||
|
||||
"test check for narcissus bug": function() {
|
||||
var worker = new JavaScriptWorker(this.sender);
|
||||
worker.setValue("if('");
|
||||
worker.deferredUpdate.call();
|
||||
assert.equal(this.sender.events[0][1].type, "error");
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -63,8 +63,6 @@ var MatchingBraceOutdent = function() {};
|
|||
|
||||
var indent = this.$getIndent(doc.getLine(openBracePos.row));
|
||||
doc.replace(new Range(row, 0, row, column-1), indent);
|
||||
|
||||
return indent.length - (column-1);
|
||||
};
|
||||
|
||||
this.$getIndent = function(line) {
|
||||
|
|
|
|||
80
lib/ace/mode/matching_parens_outdent.js
Normal file
80
lib/ace/mode/matching_parens_outdent.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
*
|
||||
* 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 Range = require("ace/range").Range;
|
||||
|
||||
var MatchingParensOutdent = function() {};
|
||||
|
||||
(function() {
|
||||
|
||||
this.checkOutdent = function(line, input) {
|
||||
if (! /^\s+$/.test(line))
|
||||
return false;
|
||||
|
||||
return /^\s*\)/.test(input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(doc, row) {
|
||||
var line = doc.getLine(row);
|
||||
var match = line.match(/^(\s*\))/);
|
||||
|
||||
if (!match) return 0;
|
||||
|
||||
var column = match[1].length;
|
||||
var openBracePos = doc.findMatchingBracket({row: row, column: column});
|
||||
|
||||
if (!openBracePos || openBracePos.row == row) return 0;
|
||||
|
||||
var indent = this.$getIndent(doc.getLine(openBracePos.row));
|
||||
doc.replace(new Range(row, 0, row, column-1), indent);
|
||||
};
|
||||
|
||||
this.$getIndent = function(line) {
|
||||
var match = line.match(/^(\s+)/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
}).call(MatchingParensOutdent.prototype);
|
||||
|
||||
exports.MatchingParensOutdent = MatchingParensOutdent;
|
||||
});
|
||||
102
lib/ace/mode/ocaml.js
Normal file
102
lib/ace/mode/ocaml.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* ***** 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):
|
||||
* Sergi Mansilla <sergi AT ajax DOT org>
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var OcamlHighlightRules = require("ace/mode/ocaml_highlight_rules").OcamlHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new OcamlHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
var indenter = /(?:[({[=:]|[-=]>|\b(?:else|try|with))\s*$/;
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var i, line;
|
||||
var outdent = true;
|
||||
var re = /^\s*\(\*(.*)\*\)/;
|
||||
|
||||
for (i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var range = new Range(0, 0, 0, 0);
|
||||
for (i=startRow; i<= endRow; i++) {
|
||||
line = doc.getLine(i);
|
||||
range.start.row = i;
|
||||
range.end.row = i;
|
||||
range.end.column = line.length;
|
||||
|
||||
doc.replace(range, outdent ? line.match(re)[1] : "(*" + line + "*)");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
|
||||
|
||||
if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&
|
||||
state === 'start' && indenter.test(line))
|
||||
indent += tab;
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
|
||||
351
lib/ace/mode/ocaml_highlight_rules.js
Normal file
351
lib/ace/mode/ocaml_highlight_rules.js
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
/* ***** 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):
|
||||
* Sergi Mansilla <sergi AT ajax DOT org>
|
||||
*
|
||||
* 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 TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var OcamlHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap((
|
||||
"and|as|assert|begin|class|constraint|do|done|downto|else|end|" +
|
||||
"exception|external|for|fun|function|functor|if|in|include|" +
|
||||
"inherit|initializer|lazy|let|match|method|module|mutable|new|" +
|
||||
"object|of|open|or|private|rec|sig|struct|then|to|try|type|val|" +
|
||||
"virtual|when|while|with").split("|")
|
||||
);
|
||||
|
||||
var builtinConstants = lang.arrayToMap(
|
||||
("true|false").split("|")
|
||||
);
|
||||
|
||||
var builtinFunctions = lang.arrayToMap((
|
||||
"abs|abs_big_int|abs_float|abs_num|abstract_tag|accept|access|acos|add|" +
|
||||
"add_available_units|add_big_int|add_buffer|add_channel|add_char|" +
|
||||
"add_initializer|add_int_big_int|add_interfaces|add_num|add_string|" +
|
||||
"add_substitute|add_substring|alarm|allocated_bytes|allow_only|" +
|
||||
"allow_unsafe_modules|always|append|appname_get|appname_set|" +
|
||||
"approx_num_exp|approx_num_fix|arg|argv|arith_status|array|" +
|
||||
"array1_of_genarray|array2_of_genarray|array3_of_genarray|asin|asr|" +
|
||||
"assoc|assq|at_exit|atan|atan2|auto_synchronize|background|basename|" +
|
||||
"beginning_of_input|big_int_of_int|big_int_of_num|big_int_of_string|bind|" +
|
||||
"bind_class|bind_tag|bits|bits_of_float|black|blit|blit_image|blue|bool|" +
|
||||
"bool_of_string|bounded_full_split|bounded_split|bounded_split_delim|" +
|
||||
"bprintf|break|broadcast|bscanf|button_down|c_layout|capitalize|cardinal|" +
|
||||
"cardinal|catch|catch_break|ceil|ceiling_num|channel|char|char_of_int|" +
|
||||
"chdir|check|check_suffix|chmod|choose|chop_extension|chop_suffix|chown|" +
|
||||
"chown|chr|chroot|classify_float|clear|clear_available_units|" +
|
||||
"clear_close_on_exec|clear_graph|clear_nonblock|clear_parser|" +
|
||||
"close|close|closeTk|close_box|close_graph|close_in|close_in_noerr|" +
|
||||
"close_out|close_out_noerr|close_process|close_process|" +
|
||||
"close_process_full|close_process_in|close_process_out|close_subwindow|" +
|
||||
"close_tag|close_tbox|closedir|closedir|closure_tag|code|combine|" +
|
||||
"combine|combine|command|compact|compare|compare_big_int|compare_num|" +
|
||||
"complex32|complex64|concat|conj|connect|contains|contains_from|contents|" +
|
||||
"copy|cos|cosh|count|count|counters|create|create_alarm|create_image|" +
|
||||
"create_matrix|create_matrix|create_matrix|create_object|" +
|
||||
"create_object_and_run_initializers|create_object_opt|create_process|" +
|
||||
"create_process|create_process_env|create_process_env|create_table|" +
|
||||
"current|current_dir_name|current_point|current_x|current_y|curveto|" +
|
||||
"custom_tag|cyan|data_size|decr|decr_num|default_available_units|delay|" +
|
||||
"delete_alarm|descr_of_in_channel|descr_of_out_channel|destroy|diff|dim|" +
|
||||
"dim1|dim2|dim3|dims|dirname|display_mode|div|div_big_int|div_num|" +
|
||||
"double_array_tag|double_tag|draw_arc|draw_char|draw_circle|draw_ellipse|" +
|
||||
"draw_image|draw_poly|draw_poly_line|draw_rect|draw_segments|draw_string|" +
|
||||
"dummy_pos|dummy_table|dump_image|dup|dup2|elements|empty|end_of_input|" +
|
||||
"environment|eprintf|epsilon_float|eq_big_int|eq_num|equal|err_formatter|" +
|
||||
"error_message|escaped|establish_server|executable_name|execv|execve|execvp|" +
|
||||
"execvpe|exists|exists2|exit|exp|failwith|fast_sort|fchmod|fchown|field|" +
|
||||
"file|file_exists|fill|fill_arc|fill_circle|fill_ellipse|fill_poly|fill_rect|" +
|
||||
"filter|final_tag|finalise|find|find_all|first_chars|firstkey|flatten|" +
|
||||
"float|float32|float64|float_of_big_int|float_of_bits|float_of_int|" +
|
||||
"float_of_num|float_of_string|floor|floor_num|flush|flush_all|flush_input|" +
|
||||
"flush_str_formatter|fold|fold_left|fold_left2|fold_right|fold_right2|" +
|
||||
"for_all|for_all2|force|force_newline|force_val|foreground|fork|" +
|
||||
"format_of_string|formatter_of_buffer|formatter_of_out_channel|" +
|
||||
"fortran_layout|forward_tag|fprintf|frexp|from|from_channel|from_file|" +
|
||||
"from_file_bin|from_function|from_string|fscanf|fst|fstat|ftruncate|" +
|
||||
"full_init|full_major|full_split|gcd_big_int|ge_big_int|ge_num|" +
|
||||
"genarray_of_array1|genarray_of_array2|genarray_of_array3|get|" +
|
||||
"get_all_formatter_output_functions|get_approx_printing|get_copy|" +
|
||||
"get_ellipsis_text|get_error_when_null_denominator|get_floating_precision|" +
|
||||
"get_formatter_output_functions|get_formatter_tag_functions|get_image|" +
|
||||
"get_margin|get_mark_tags|get_max_boxes|get_max_indent|get_method|" +
|
||||
"get_method_label|get_normalize_ratio|get_normalize_ratio_when_printing|" +
|
||||
"get_print_tags|get_state|get_variable|getcwd|getegid|getegid|getenv|" +
|
||||
"getenv|getenv|geteuid|geteuid|getgid|getgid|getgrgid|getgrgid|getgrnam|" +
|
||||
"getgrnam|getgroups|gethostbyaddr|gethostbyname|gethostname|getitimer|" +
|
||||
"getlogin|getpeername|getpid|getppid|getprotobyname|getprotobynumber|" +
|
||||
"getpwnam|getpwuid|getservbyname|getservbyport|getsockname|getsockopt|" +
|
||||
"getsockopt_float|getsockopt_int|getsockopt_optint|gettimeofday|getuid|" +
|
||||
"global_replace|global_substitute|gmtime|green|grid|group_beginning|" +
|
||||
"group_end|gt_big_int|gt_num|guard|handle_unix_error|hash|hash_param|" +
|
||||
"hd|header_size|i|id|ignore|in_channel_length|in_channel_of_descr|incr|" +
|
||||
"incr_num|index|index_from|inet_addr_any|inet_addr_of_string|infinity|" +
|
||||
"infix_tag|init|init_class|input|input_binary_int|input_byte|input_char|" +
|
||||
"input_line|input_value|int|int16_signed|int16_unsigned|int32|int64|" +
|
||||
"int8_signed|int8_unsigned|int_of_big_int|int_of_char|int_of_float|" +
|
||||
"int_of_num|int_of_string|integer_num|inter|interactive|inv|invalid_arg|" +
|
||||
"is_block|is_empty|is_implicit|is_int|is_int_big_int|is_integer_num|" +
|
||||
"is_relative|iter|iter2|iteri|join|junk|key_pressed|kill|kind|kprintf|" +
|
||||
"kscanf|land|last_chars|layout|lazy_from_fun|lazy_from_val|lazy_is_val|" +
|
||||
"lazy_tag|ldexp|le_big_int|le_num|length|lexeme|lexeme_char|lexeme_end|" +
|
||||
"lexeme_end_p|lexeme_start|lexeme_start_p|lineto|link|list|listen|lnot|" +
|
||||
"loadfile|loadfile_private|localtime|lock|lockf|log|log10|logand|lognot|" +
|
||||
"logor|logxor|lor|lower_window|lowercase|lseek|lsl|lsr|lstat|lt_big_int|" +
|
||||
"lt_num|lxor|magenta|magic|mainLoop|major|major_slice|make|make_formatter|" +
|
||||
"make_image|make_lexer|make_matrix|make_self_init|map|map2|map_file|mapi|" +
|
||||
"marshal|match_beginning|match_end|matched_group|matched_string|max|" +
|
||||
"max_array_length|max_big_int|max_elt|max_float|max_int|max_num|" +
|
||||
"max_string_length|mem|mem_assoc|mem_assq|memq|merge|min|min_big_int|" +
|
||||
"min_elt|min_float|min_int|min_num|minor|minus_big_int|minus_num|" +
|
||||
"minus_one|mkdir|mkfifo|mktime|mod|mod_big_int|mod_float|mod_num|modf|" +
|
||||
"mouse_pos|moveto|mul|mult_big_int|mult_int_big_int|mult_num|nan|narrow|" +
|
||||
"nat_of_num|nativeint|neg|neg_infinity|new_block|new_channel|new_method|" +
|
||||
"new_variable|next|nextkey|nice|nice|no_scan_tag|norm|norm2|not|npeek|" +
|
||||
"nth|nth_dim|num_digits_big_int|num_dims|num_of_big_int|num_of_int|" +
|
||||
"num_of_nat|num_of_ratio|num_of_string|O|obj|object_tag|ocaml_version|" +
|
||||
"of_array|of_channel|of_float|of_int|of_int32|of_list|of_nativeint|" +
|
||||
"of_string|one|openTk|open_box|open_connection|open_graph|open_hbox|" +
|
||||
"open_hovbox|open_hvbox|open_in|open_in_bin|open_in_gen|open_out|" +
|
||||
"open_out_bin|open_out_gen|open_process|open_process_full|open_process_in|" +
|
||||
"open_process_out|open_subwindow|open_tag|open_tbox|open_temp_file|" +
|
||||
"open_vbox|opendbm|opendir|openfile|or|os_type|out_channel_length|" +
|
||||
"out_channel_of_descr|output|output_binary_int|output_buffer|output_byte|" +
|
||||
"output_char|output_string|output_value|over_max_boxes|pack|params|" +
|
||||
"parent_dir_name|parse|parse_argv|partition|pause|peek|pipe|pixels|" +
|
||||
"place|plot|plots|point_color|polar|poll|pop|pos_in|pos_out|pow|" +
|
||||
"power_big_int_positive_big_int|power_big_int_positive_int|" +
|
||||
"power_int_positive_big_int|power_int_positive_int|power_num|" +
|
||||
"pp_close_box|pp_close_tag|pp_close_tbox|pp_force_newline|" +
|
||||
"pp_get_all_formatter_output_functions|pp_get_ellipsis_text|" +
|
||||
"pp_get_formatter_output_functions|pp_get_formatter_tag_functions|" +
|
||||
"pp_get_margin|pp_get_mark_tags|pp_get_max_boxes|pp_get_max_indent|" +
|
||||
"pp_get_print_tags|pp_open_box|pp_open_hbox|pp_open_hovbox|pp_open_hvbox|" +
|
||||
"pp_open_tag|pp_open_tbox|pp_open_vbox|pp_over_max_boxes|pp_print_as|" +
|
||||
"pp_print_bool|pp_print_break|pp_print_char|pp_print_cut|pp_print_float|" +
|
||||
"pp_print_flush|pp_print_if_newline|pp_print_int|pp_print_newline|" +
|
||||
"pp_print_space|pp_print_string|pp_print_tab|pp_print_tbreak|" +
|
||||
"pp_set_all_formatter_output_functions|pp_set_ellipsis_text|" +
|
||||
"pp_set_formatter_out_channel|pp_set_formatter_output_functions|" +
|
||||
"pp_set_formatter_tag_functions|pp_set_margin|pp_set_mark_tags|" +
|
||||
"pp_set_max_boxes|pp_set_max_indent|pp_set_print_tags|pp_set_tab|" +
|
||||
"pp_set_tags|pred|pred_big_int|pred_num|prerr_char|prerr_endline|" +
|
||||
"prerr_float|prerr_int|prerr_newline|prerr_string|print|print_as|" +
|
||||
"print_bool|print_break|print_char|print_cut|print_endline|print_float|" +
|
||||
"print_flush|print_if_newline|print_int|print_newline|print_space|" +
|
||||
"print_stat|print_string|print_tab|print_tbreak|printf|prohibit|" +
|
||||
"public_method_label|push|putenv|quo_num|quomod_big_int|quote|raise|" +
|
||||
"raise_window|ratio_of_num|rcontains_from|read|read_float|read_int|" +
|
||||
"read_key|read_line|readdir|readdir|readlink|really_input|receive|recv|" +
|
||||
"recvfrom|red|ref|regexp|regexp_case_fold|regexp_string|" +
|
||||
"regexp_string_case_fold|register|register_exception|rem|remember_mode|" +
|
||||
"remove|remove_assoc|remove_assq|rename|replace|replace_first|" +
|
||||
"replace_matched|repr|reset|reshape|reshape_1|reshape_2|reshape_3|rev|" +
|
||||
"rev_append|rev_map|rev_map2|rewinddir|rgb|rhs_end|rhs_end_pos|rhs_start|" +
|
||||
"rhs_start_pos|rindex|rindex_from|rlineto|rmdir|rmoveto|round_num|" +
|
||||
"run_initializers|run_initializers_opt|scanf|search_backward|" +
|
||||
"search_forward|seek_in|seek_out|select|self|self_init|send|sendto|set|" +
|
||||
"set_all_formatter_output_functions|set_approx_printing|" +
|
||||
"set_binary_mode_in|set_binary_mode_out|set_close_on_exec|" +
|
||||
"set_close_on_exec|set_color|set_ellipsis_text|" +
|
||||
"set_error_when_null_denominator|set_field|set_floating_precision|" +
|
||||
"set_font|set_formatter_out_channel|set_formatter_output_functions|" +
|
||||
"set_formatter_tag_functions|set_line_width|set_margin|set_mark_tags|" +
|
||||
"set_max_boxes|set_max_indent|set_method|set_nonblock|set_nonblock|" +
|
||||
"set_normalize_ratio|set_normalize_ratio_when_printing|set_print_tags|" +
|
||||
"set_signal|set_state|set_tab|set_tag|set_tags|set_text_size|" +
|
||||
"set_window_title|setgid|setgid|setitimer|setitimer|setsid|setsid|" +
|
||||
"setsockopt|setsockopt|setsockopt_float|setsockopt_float|setsockopt_int|" +
|
||||
"setsockopt_int|setsockopt_optint|setsockopt_optint|setuid|setuid|" +
|
||||
"shift_left|shift_left|shift_left|shift_right|shift_right|shift_right|" +
|
||||
"shift_right_logical|shift_right_logical|shift_right_logical|show_buckets|" +
|
||||
"shutdown|shutdown|shutdown_connection|shutdown_connection|sigabrt|" +
|
||||
"sigalrm|sigchld|sigcont|sigfpe|sighup|sigill|sigint|sigkill|sign_big_int|" +
|
||||
"sign_num|signal|signal|sigpending|sigpending|sigpipe|sigprocmask|" +
|
||||
"sigprocmask|sigprof|sigquit|sigsegv|sigstop|sigsuspend|sigsuspend|" +
|
||||
"sigterm|sigtstp|sigttin|sigttou|sigusr1|sigusr2|sigvtalrm|sin|singleton|" +
|
||||
"sinh|size|size|size_x|size_y|sleep|sleep|sleep|slice_left|slice_left|" +
|
||||
"slice_left_1|slice_left_2|slice_right|slice_right|slice_right_1|" +
|
||||
"slice_right_2|snd|socket|socket|socket|socketpair|socketpair|sort|sound|" +
|
||||
"split|split_delim|sprintf|sprintf|sqrt|sqrt|sqrt_big_int|square_big_int|" +
|
||||
"square_num|sscanf|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|" +
|
||||
"stable_sort|stat|stat|stat|stat|stat|stats|stats|std_formatter|stdbuf|" +
|
||||
"stderr|stderr|stderr|stdib|stdin|stdin|stdin|stdout|stdout|stdout|" +
|
||||
"str_formatter|string|string_after|string_before|string_match|" +
|
||||
"string_of_big_int|string_of_bool|string_of_float|string_of_format|" +
|
||||
"string_of_inet_addr|string_of_inet_addr|string_of_int|string_of_num|" +
|
||||
"string_partial_match|string_tag|sub|sub|sub_big_int|sub_left|sub_num|" +
|
||||
"sub_right|subset|subset|substitute_first|substring|succ|succ|" +
|
||||
"succ|succ|succ_big_int|succ_num|symbol_end|symbol_end_pos|symbol_start|" +
|
||||
"symbol_start_pos|symlink|symlink|sync|synchronize|system|system|system|" +
|
||||
"tag|take|tan|tanh|tcdrain|tcdrain|tcflow|tcflow|tcflush|tcflush|" +
|
||||
"tcgetattr|tcgetattr|tcsendbreak|tcsendbreak|tcsetattr|tcsetattr|" +
|
||||
"temp_file|text_size|time|time|time|timed_read|timed_write|times|times|" +
|
||||
"tl|tl|tl|to_buffer|to_channel|to_float|to_hex|to_int|to_int32|to_list|" +
|
||||
"to_list|to_list|to_nativeint|to_string|to_string|to_string|to_string|" +
|
||||
"to_string|top|top|total_size|transfer|transp|truncate|truncate|truncate|" +
|
||||
"truncate|truncate|truncate|try_lock|umask|umask|uncapitalize|uncapitalize|" +
|
||||
"uncapitalize|union|union|unit_big_int|unlink|unlink|unlock|unmarshal|" +
|
||||
"unsafe_blit|unsafe_fill|unsafe_get|unsafe_get|unsafe_set|unsafe_set|" +
|
||||
"update|uppercase|uppercase|uppercase|uppercase|usage|utimes|utimes|wait|" +
|
||||
"wait|wait|wait|wait_next_event|wait_pid|wait_read|wait_signal|" +
|
||||
"wait_timed_read|wait_timed_write|wait_write|waitpid|white|" +
|
||||
"widen|window_id|word_size|wrap|wrap_abort|write|yellow|yield|zero|zero_big_int|" +
|
||||
|
||||
"Arg|Arith_status|Array|Array1|Array2|Array3|ArrayLabels|Big_int|Bigarray|" +
|
||||
"Buffer|Callback|CamlinternalOO|Char|Complex|Condition|Dbm|Digest|Dynlink|" +
|
||||
"Event|Filename|Format|Gc|Genarray|Genlex|Graphics|GraphicsX11|Hashtbl|" +
|
||||
"Int32|Int64|LargeFile|Lazy|Lexing|List|ListLabels|Make|Map|Marshal|" +
|
||||
"MoreLabels|Mutex|Nativeint|Num|Obj|Oo|Parsing|Pervasives|Printexc|" +
|
||||
"Printf|Queue|Random|Scanf|Scanning|Set|Sort|Stack|State|StdLabels|Str|" +
|
||||
"Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak")
|
||||
|
||||
.split("|"));
|
||||
|
||||
var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
|
||||
var octInteger = "(?:0[oO]?[0-7]+)";
|
||||
var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
|
||||
var binInteger = "(?:0[bB][01]+)";
|
||||
var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
|
||||
|
||||
var exponent = "(?:[eE][+-]?\\d+)";
|
||||
var fraction = "(?:\\.\\d+)";
|
||||
var intPart = "(?:\\d+)";
|
||||
var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
|
||||
var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + exponent + ")";
|
||||
var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : '\\(\\*.*?\\*\\)\\s*?$'
|
||||
},
|
||||
{
|
||||
token : "comment",
|
||||
regex : '\\(\\*.*',
|
||||
next : "comment"
|
||||
},
|
||||
{
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
},
|
||||
{
|
||||
token : "string", // single char
|
||||
regex : "'.'"
|
||||
},
|
||||
{
|
||||
token : "string", // " string
|
||||
regex : '"',
|
||||
next : "qstring"
|
||||
},
|
||||
{
|
||||
token : "constant.numeric", // imaginary
|
||||
regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
|
||||
},
|
||||
{
|
||||
token : "constant.numeric", // float
|
||||
regex : floatNumber
|
||||
},
|
||||
{
|
||||
token : "constant.numeric", // integer
|
||||
regex : integer + "\\b"
|
||||
},
|
||||
{
|
||||
token : function(value) {
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (builtinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
},
|
||||
{
|
||||
token : "keyword.operator",
|
||||
regex : "\\+\\.|\\-\\.|\\*\\.|\\/\\.|#|;;|\\+|\\-|\\*|\\*\\*\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|<-|="
|
||||
},
|
||||
{
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
},
|
||||
{
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
},
|
||||
{
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\)",
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(OcamlHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.OcamlHighlightRules = OcamlHighlightRules;
|
||||
});
|
||||
116
lib/ace/mode/perl.js
Normal file
116
lib/ace/mode/perl.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* ***** 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):
|
||||
* Panagiotis Astithas <pastith AT gmail DOT com>
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var PerlHighlightRules = require("ace/mode/perl_highlight_rules").PerlHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new PerlHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)#/;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, "#");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[\:]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
163
lib/ace/mode/perl_highlight_rules.js
Normal file
163
lib/ace/mode/perl_highlight_rules.js
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* ***** 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):
|
||||
* Panagiotis Astithas <pastith AT gmail DOT com>
|
||||
*
|
||||
* 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 TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var PerlHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|" +
|
||||
"no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("ARGV|ENV|INC|SIG").split("|")
|
||||
);
|
||||
|
||||
var builtinFunctions = lang.arrayToMap(
|
||||
("getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|" +
|
||||
"gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|" +
|
||||
"getpeername|setpriority|getprotoent|setprotoent|getpriority|" +
|
||||
"endprotoent|getservent|setservent|endservent|sethostent|socketpair|" +
|
||||
"getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|" +
|
||||
"localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|" +
|
||||
"closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|" +
|
||||
"shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|" +
|
||||
"dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|" +
|
||||
"setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|" +
|
||||
"lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|" +
|
||||
"waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|" +
|
||||
"chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|" +
|
||||
"unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|" +
|
||||
"length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|" +
|
||||
"undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|" +
|
||||
"sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|" +
|
||||
"BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|" +
|
||||
"join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|" +
|
||||
"keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|" +
|
||||
"eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|" +
|
||||
"map|die|uc|lc|do").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0x[0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(PerlHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.PerlHighlightRules = PerlHighlightRules;
|
||||
});
|
||||
|
|
@ -68,16 +68,16 @@ oop.inherits(Mode, TextMode);
|
|||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i).replace(re, "$1");
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = line.length + 2;
|
||||
doc.replace(deleteRange, line);
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
else {
|
||||
return doc.indentRows(startRow, endRow, "#");
|
||||
doc.indentRows(startRow, endRow, "#");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ oop.inherits(Mode, TextMode);
|
|||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
return this.$outdent.autoOutdent(doc, row);
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
* 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 *****
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
|
@ -43,7 +43,7 @@ var lang = require("pilot/lang");
|
|||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
PhpHighlightRules = function() {
|
||||
var PhpHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
|
||||
|
|
@ -443,18 +443,18 @@ PhpHighlightRules = function() {
|
|||
'include|include_once|global|goto|if|implements|interface|instanceof|namespace|new|old_function|or|' +
|
||||
'private|protected|public|return|require|require_once|static|switch|throw|try|use|var|while|xor').split('|')
|
||||
);
|
||||
|
||||
|
||||
var builtinConstants = lang.arrayToMap(
|
||||
('true|false|null|__FILE__|__LINE__|__METHOD__|__FUNCTION__|__CLASS__').split('|')
|
||||
);
|
||||
|
||||
|
||||
var builtinVariables = lang.arrayToMap(
|
||||
('$_GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|' +
|
||||
('$GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|' +
|
||||
'$http_response_header|$argc|$argv').split('|')
|
||||
);
|
||||
|
||||
|
||||
var futureReserved = lang.arrayToMap([]);
|
||||
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
|
|
@ -472,6 +472,10 @@ PhpHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
{
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
|
|
@ -503,13 +507,13 @@ PhpHighlightRules = function() {
|
|||
}, {
|
||||
token : "constant.language", // constants
|
||||
regex : "\\b(?:DEFAULT_INCLUDE_PATH|E_(?:ALL|CO(?:MPILE_(?:ERROR|WARNING)|RE_(?:ERROR|WARNING))|" +
|
||||
"ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|" +
|
||||
"HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|" +
|
||||
"ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|" +
|
||||
"HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|" +
|
||||
"L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|" +
|
||||
"VERSION))|__COMPILER_HALT_OFFSET__)\\b"
|
||||
}, {
|
||||
token : "constant.language", // constants
|
||||
regex : "\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|" +
|
||||
regex : "\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|" +
|
||||
"SSERT_(?:ACTIVE|BAIL|CALLBACK|QUIET_EVAL|WARNING))|C(?:ASE_(?:LOWER|UPPER)|HAR_MAX|" +
|
||||
"O(?:DESET|NNECTION_(?:ABORTED|NORMAL|TIMEOUT)|UNT_(?:NORMAL|RECURSIVE))|" +
|
||||
"R(?:EDITS_(?:ALL|DOCS|FULLPAGE|G(?:ENERAL|ROUP)|MODULES|QA|SAPI)|NCYSTR|" +
|
||||
|
|
@ -527,20 +531,20 @@ PhpHighlightRules = function() {
|
|||
"T(?:HOUS(?:ANDS_SEP|EP)|_FMT(?:_AMPM|))|YES(?:EXPR|STR)|STD(?:IN|OUT|ERR))\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (keywords[value])
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (builtinConstants[value])
|
||||
else if (builtinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinVariables[value])
|
||||
else if (builtinVariables.hasOwnProperty(value))
|
||||
return "variable.language";
|
||||
else if (futureReserved[value])
|
||||
else if (futureReserved.hasOwnProperty(value))
|
||||
return "invalid.illegal";
|
||||
else if (builtinFunctions[value])
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
if(value.match(/^(\$[a-zA-Z][a-zA-Z0-9_]*|self|parent)$/))
|
||||
if(value.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|self|parent)$/))
|
||||
return "variable";
|
||||
return "identifier";
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -68,16 +69,16 @@ oop.inherits(Mode, TextMode);
|
|||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i).replace(re, "$1");
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = line.length + 2;
|
||||
doc.replace(deleteRange, line);
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
else {
|
||||
return doc.indentRows(startRow, endRow, "#");
|
||||
doc.indentRows(startRow, endRow, "#");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ oop.inherits(Mode, TextMode);
|
|||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
return this.$outdent.autoOutdent(doc, row);
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -44,7 +45,7 @@ var oop = require("pilot/oop");
|
|||
var lang = require("pilot/lang");
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
PythonHighlightRules = function() {
|
||||
var PythonHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("and|as|assert|break|class|continue|def|del|elif|else|except|exec|" +
|
||||
|
|
@ -71,7 +72,7 @@ PythonHighlightRules = function() {
|
|||
("").split("|")
|
||||
);
|
||||
|
||||
var strPre = "(?:(?:[rubRUB])|(?:[ubUB][rR]))?";
|
||||
var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";
|
||||
|
||||
var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
|
||||
var octInteger = "(?:0[oO]?[0-7]+)";
|
||||
|
|
@ -92,24 +93,24 @@ PythonHighlightRules = function() {
|
|||
regex : "#.*$"
|
||||
}, {
|
||||
token : "string", // """ string
|
||||
regex : strPre + '"{3}(?:(?:.)|(?:^"{3}))*?"{3}'
|
||||
regex : strPre + '"{3}(?:[^\\\\]|\\\\.)*?"{3}'
|
||||
}, {
|
||||
token : "string", // multi line """ string start
|
||||
regex : strPre + '"{3}.*$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // " string
|
||||
regex : strPre + '"(?:(?:\\\\.)|(?:[^"\\\\]))*?"'
|
||||
regex : strPre + '"(?:[^\\\\]|\\\\.)*?"'
|
||||
}, {
|
||||
token : "string", // ''' string
|
||||
regex : strPre + "'{3}(?:(?:.)|(?:^'{3}))*?'{3}"
|
||||
regex : strPre + "'{3}(?:[^\\\\]|\\\\.)*?'{3}"
|
||||
}, {
|
||||
token : "string", // multi line ''' string start
|
||||
regex : strPre + "'{3}.*$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "string", // ' string
|
||||
regex : strPre + "'(?:(?:\\\\.)|(?:[^'\\\\]))*?'"
|
||||
regex : strPre + "'(?:[^\\\\]|\\\\.)*?'"
|
||||
}, {
|
||||
token : "constant.numeric", // imaginary
|
||||
regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
|
||||
|
|
@ -124,13 +125,13 @@ PythonHighlightRules = function() {
|
|||
regex : integer + "\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (keywords[value])
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (builtinConstants[value])
|
||||
else if (builtinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (futureReserved[value])
|
||||
else if (futureReserved.hasOwnProperty(value))
|
||||
return "invalid.illegal";
|
||||
else if (builtinFunctions[value])
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
|
|
@ -152,8 +153,8 @@ PythonHighlightRules = function() {
|
|||
regex : "\\s+"
|
||||
} ],
|
||||
"qqstring" : [ {
|
||||
token : "string", // multi line """ string end
|
||||
regex : '(?:^"{3})*?"{3}',
|
||||
token : "string", // multi line """ string end
|
||||
regex : '(?:[^\\\\]|\\\\.)*?"{3}',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
|
|
@ -161,7 +162,7 @@ PythonHighlightRules = function() {
|
|||
} ],
|
||||
"qstring" : [ {
|
||||
token : "string", // multi line ''' string end
|
||||
regex : "(?:^'{3})*?'{3}",
|
||||
regex : "(?:[^\\\\]|\\\\.)*?'{3}",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
|
|
|
|||
117
lib/ace/mode/ruby.js
Normal file
117
lib/ace/mode/ruby.js
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var RubyHighlightRules = require("ace/mode/ruby_highlight_rules").RubyHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new RubyHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)#/;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, "#");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
188
lib/ace/mode/ruby_highlight_rules.js
Normal file
188
lib/ace/mode/ruby_highlight_rules.js
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
* Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>
|
||||
*
|
||||
* 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 TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var RubyHighlightRules = function() {
|
||||
|
||||
var builtinFunctions = lang.arrayToMap(
|
||||
("abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|" +
|
||||
"assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|" +
|
||||
"assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|" +
|
||||
"assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|" +
|
||||
"assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|" +
|
||||
"assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|" +
|
||||
"attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|" +
|
||||
"caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|" +
|
||||
"exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|" +
|
||||
"gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|" +
|
||||
"link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|" +
|
||||
"p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|" +
|
||||
"raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|" +
|
||||
"set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|" +
|
||||
"throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|" +
|
||||
"render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|" +
|
||||
"content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|" +
|
||||
"fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|" +
|
||||
"time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|" +
|
||||
"select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|" +
|
||||
"file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|" +
|
||||
"protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|" +
|
||||
"send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|" +
|
||||
"validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|" +
|
||||
"validates_inclusion_of|validates_numericality_of|validates_with|validates_each|" +
|
||||
"authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|" +
|
||||
"filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|" +
|
||||
"translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|" +
|
||||
"cache|expire_fragment|expire_cache_for|observe|cache_sweeper|" +
|
||||
"has_many|has_one|belongs_to|has_and_belongs_to_many").split("|")
|
||||
);
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|" +
|
||||
"__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|" +
|
||||
"redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|" +
|
||||
"RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING").split("|")
|
||||
);
|
||||
|
||||
var builtinVariables = lang.arrayToMap(
|
||||
("\$DEBUG|\$defout|\$FILENAME|\$LOAD_PATH|\$SAFE|\$stdin|\$stdout|\$stderr|\$VERBOSE|" +
|
||||
"$!|root_url|flash|session|cookies|params|request|response|logger").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "^\=begin$",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // backtick string
|
||||
regex : "[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"
|
||||
}, {
|
||||
token : "variable.instancce", // instance variable
|
||||
regex : "@{1,2}(?:[a-zA-Z_]|\d)+"
|
||||
}, {
|
||||
token : "variable.class", // class name
|
||||
regex : "[A-Z](?:[a-zA-Z_]|\d)+"
|
||||
}, {
|
||||
token : "string", // symbol
|
||||
regex : "[:](?:[a-zA-Z]|\d)+"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "self")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinVariables.hasOwnProperty(value))
|
||||
return "variable.language";
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : "^\=end$",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(RubyHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.RubyHighlightRules = RubyHighlightRules;
|
||||
});
|
||||
|
|
@ -37,54 +37,57 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
exports.bindings = {
|
||||
"save": "Command-S",
|
||||
"saveas": "Command-Shift-S",
|
||||
"selectall": "Command-A",
|
||||
"removeline": "Command-D",
|
||||
"gotoline": "Command-L",
|
||||
"togglecomment": "Command-7",
|
||||
"findnext": "Command-K",
|
||||
"findprevious": "Command-Shift-K",
|
||||
"find": "Command-F",
|
||||
"replace": "Command-R",
|
||||
"undo": "Command-Z",
|
||||
"redo": "Command-Shift-Z|Command-Y",
|
||||
"overwrite": "Insert",
|
||||
"copylinesup": "Command-Option-Up",
|
||||
"movelinesup": "Option-Up",
|
||||
"selecttostart": "Command-Shift-Up",
|
||||
"gotostart": "Command-Home|Command-Up",
|
||||
"selectup": "Shift-Up",
|
||||
"golineup": "Up",
|
||||
"copylinesdown": "Command-Option-Down",
|
||||
"movelinesdown": "Option-Down",
|
||||
"selecttoend": "Command-Shift-Down",
|
||||
"gotoend": "Command-End|Command-Down",
|
||||
"selectdown": "Shift-Down",
|
||||
"golinedown": "Down",
|
||||
"selectwordleft": "Option-Shift-Left",
|
||||
"gotowordleft": "Option-Left",
|
||||
"selecttolinestart": "Command-Shift-Left",
|
||||
"gotolinestart": "Command-Left|Home",
|
||||
"selectleft": "Shift-Left",
|
||||
"gotoleft": "Left",
|
||||
"selectwordright": "Option-Shift-Right",
|
||||
"gotowordright": "Option-Right",
|
||||
"selecttolineend": "Command-Shift-Right",
|
||||
"gotolineend": "Command-Right|End",
|
||||
"selectright": "Shift-Right",
|
||||
"gotoright": "Right",
|
||||
"selectpagedown": "Shift-PageDown",
|
||||
"pagedown": "PageDown",
|
||||
"selectpageup": "Shift-PageUp",
|
||||
"pageup": "PageUp",
|
||||
"selectlinestart": "Shift-Home",
|
||||
"selectlineend": "Shift-End",
|
||||
"del": "Delete",
|
||||
"backspace": "Ctrl-Backspace|Command-Backspace|Option-Backspace|Backspace",
|
||||
"outdent": "Shift-Tab",
|
||||
"indent": "Tab"
|
||||
var oop = require("pilot/oop");
|
||||
var XmlMode = require("ace/mode/text").Mode;
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var SvgHighlightRules = require("ace/mode/svg_highlight_rules").SvgHighlightRules;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new SvgHighlightRules().getRules());
|
||||
this.$js = new JavaScriptMode();
|
||||
};
|
||||
|
||||
});
|
||||
oop.inherits(Mode, XmlMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
this.$delegate("toggleCommentLines", arguments, function() {
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var self = this;
|
||||
return this.$delegate("getNextLineIndent", arguments, function() {
|
||||
return self.$getIndent(line);
|
||||
});
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$delegate("checkOutdent", arguments, function() {
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$delegate("autoOutdent", arguments);
|
||||
};
|
||||
|
||||
this.$delegate = function(method, args, defaultHandler) {
|
||||
var state = args[0];
|
||||
var split = state.split("js-");
|
||||
|
||||
if (!split[0] && split[1]) {
|
||||
args[0] = split[1];
|
||||
return this.$js[method].apply(this.$js, args);
|
||||
}
|
||||
|
||||
return defaultHandler ? defaultHandler() : undefined;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
87
lib/ace/mode/svg_highlight_rules.js
Normal file
87
lib/ace/mode/svg_highlight_rules.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
*
|
||||
* 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 JavaScriptHighlightRules = require("ace/mode/javascript_highlight_rules").JavaScriptHighlightRules;
|
||||
var XmlHighlightRules = require("ace/mode/xml_highlight_rules").XmlHighlightRules;
|
||||
|
||||
var SvgHighlightRules = function() {
|
||||
XmlHighlightRules.call(this);
|
||||
|
||||
this.$rules.start.splice(3, 0, {
|
||||
token : "text",
|
||||
regex : "<(?=\s*script)",
|
||||
next : "script"
|
||||
});
|
||||
this.$rules.script = [{
|
||||
token : "text",
|
||||
regex : ">",
|
||||
next : "js-start"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "[-_a-zA-Z0-9:]+"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
}];
|
||||
|
||||
var jsRules = new JavaScriptHighlightRules().getRules();
|
||||
this.addRules(jsRules, "js-");
|
||||
this.$rules["js-start"].unshift({
|
||||
token: "comment",
|
||||
regex: "\\/\\/.*(?=<\\/script>)",
|
||||
next: "tag"
|
||||
}, {
|
||||
token: "text",
|
||||
regex: "<\\/(?=script)",
|
||||
next: "tag"
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
oop.inherits(SvgHighlightRules, XmlHighlightRules);
|
||||
|
||||
exports.SvgHighlightRules = SvgHighlightRules;
|
||||
});
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -51,7 +53,6 @@ var Mode = function() {
|
|||
};
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
|
|
@ -73,6 +74,72 @@ var Mode = function() {
|
|||
|
||||
return "";
|
||||
};
|
||||
|
||||
this.createWorker = function(session) {
|
||||
return null;
|
||||
};
|
||||
|
||||
this.highlightSelection = function(editor) {
|
||||
var session = editor.session;
|
||||
if (!session.$selectionOccurrences)
|
||||
session.$selectionOccurrences = [];
|
||||
|
||||
if (session.$selectionOccurrences.length)
|
||||
this.clearSelectionHighlight(editor);
|
||||
|
||||
var selection = editor.getSelectionRange();
|
||||
if (selection.isEmpty() || selection.isMultiLine())
|
||||
return;
|
||||
|
||||
var startOuter = selection.start.column - 1;
|
||||
var endOuter = selection.end.column + 1;
|
||||
var line = session.getLine(selection.start.row);
|
||||
var lineCols = line.length;
|
||||
var needle = line.substring(Math.max(startOuter, 0),
|
||||
Math.min(endOuter, lineCols));
|
||||
|
||||
// Make sure the outer characters are not part of the word.
|
||||
if ((startOuter >= 0 && /^[\w\d]/.test(needle)) ||
|
||||
(endOuter <= lineCols && /[\w\d]$/.test(needle)))
|
||||
return;
|
||||
|
||||
needle = line.substring(selection.start.column, selection.end.column);
|
||||
if (!/^[\w\d]+$/.test(needle))
|
||||
return;
|
||||
|
||||
var cursor = editor.getCursorPosition();
|
||||
|
||||
var newOptions = {
|
||||
wrap: true,
|
||||
wholeWord: true,
|
||||
caseSensitive: true,
|
||||
needle: needle
|
||||
};
|
||||
|
||||
var currentOptions = editor.$search.getOptions();
|
||||
editor.$search.set(newOptions);
|
||||
|
||||
var ranges = editor.$search.findAll(session);
|
||||
ranges.forEach(function(range) {
|
||||
if (!range.contains(cursor.row, cursor.column)) {
|
||||
var marker = session.addMarker(range, "ace_selected_word");
|
||||
session.$selectionOccurrences.push(marker);
|
||||
}
|
||||
});
|
||||
|
||||
editor.$search.set(currentOptions);
|
||||
};
|
||||
|
||||
this.clearSelectionHighlight = function(editor) {
|
||||
if (!editor.session.$selectionOccurrences)
|
||||
return;
|
||||
|
||||
editor.session.$selectionOccurrences.forEach(function(marker) {
|
||||
editor.session.removeMarker(marker);
|
||||
});
|
||||
|
||||
editor.session.$selectionOccurrences = [];
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ var TextHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
token : "empty_line",
|
||||
regex : '^$'
|
||||
}, {
|
||||
token : "text",
|
||||
regex : ".+"
|
||||
} ]
|
||||
|
|
|
|||
|
|
@ -35,22 +35,26 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
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");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.mode = new TextMode();
|
||||
},
|
||||
|
||||
"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,10 +63,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
76
lib/ace/mode/textile.js
Normal file
76
lib/ace/mode/textile.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* ***** 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):
|
||||
* Kelley van Evert <kelley.vanevert@gmail.com>
|
||||
*
|
||||
* 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var TextileHighlightRules = require("ace/mode/textile_highlight_rules").TextileHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Mode = function()
|
||||
{
|
||||
this.$tokenizer = new Tokenizer(new TextileHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function()
|
||||
{
|
||||
this.getNextLineIndent = function(state, line, tab)
|
||||
{
|
||||
if (state == "intag")
|
||||
return tab;
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
|
||||
});
|
||||
110
lib/ace/mode/textile_highlight_rules.js
Normal file
110
lib/ace/mode/textile_highlight_rules.js
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* ***** 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):
|
||||
* Kelley van Evert <kelley.vanevert@gmail.com>
|
||||
*
|
||||
* 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 TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var TextileHighlightRules = function()
|
||||
{
|
||||
/*
|
||||
var phraseModifiers = lang.arrayToMap(
|
||||
("_|*|__|**|??|-|+|^|%|@").split("|")
|
||||
);
|
||||
|
||||
var blockModifiers = lang.arrayToMap(
|
||||
("h1|h2|h3|h4|h5|h6|bq|p|bc|pre").split("|")
|
||||
);
|
||||
*/
|
||||
/*
|
||||
var punctuation = lang.arrayToMap(
|
||||
("-|--|(tm)|(r)|(c)").split("|")
|
||||
);
|
||||
*/
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "keyword", // start of block
|
||||
regex : "h1|h2|h3|h4|h5|h6|bq|p|bc|pre",
|
||||
next : "blocktag"
|
||||
},
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "[\\*]+|[#]+"
|
||||
},
|
||||
{
|
||||
token : "text",
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"blocktag" : [
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "\\. ",
|
||||
next : "start",
|
||||
},
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "\\(",
|
||||
next : "blocktagproperties"
|
||||
},
|
||||
],
|
||||
"blocktagproperties" : [
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "\\)",
|
||||
next : "blocktag"
|
||||
},
|
||||
{
|
||||
token : "string",
|
||||
regex : "[a-zA-Z0-9\\-_]+"
|
||||
},
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "#"
|
||||
},
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(TextileHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.TextileHighlightRules = TextileHighlightRules;
|
||||
|
||||
});
|
||||
|
|
@ -82,11 +82,37 @@ var XmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*$",
|
||||
next : "qstring"
|
||||
}],
|
||||
|
||||
qstring: [{
|
||||
token : "string",
|
||||
regex : ".*'",
|
||||
next : "tag"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}],
|
||||
|
||||
qqstring: [{
|
||||
token : "string",
|
||||
regex : ".*\"",
|
||||
next : "tag"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}],
|
||||
|
||||
cdata : [ {
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
|
|
@ -110,8 +136,6 @@ var XmlHighlightRules = function() {
|
|||
};
|
||||
};
|
||||
|
||||
/fd/g
|
||||
|
||||
oop.inherits(XmlHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.XmlHighlightRules = XmlHighlightRules;
|
||||
|
|
|
|||
|
|
@ -35,14 +35,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
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");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.mode = new XmlMode();
|
||||
},
|
||||
|
|
@ -57,10 +61,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,10 +74,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,13 +35,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var XmlMode = require("ace/mode/xml").Mode;
|
||||
var assert = require("../assertions");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.tokenizer = new XmlMode().getTokenizer();
|
||||
},
|
||||
|
|
@ -60,10 +63,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
289
lib/ace/mouse_handler.js
Normal file
289
lib/ace/mouse_handler.js
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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 <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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 event = require("pilot/event");
|
||||
var dom = require("pilot/dom");
|
||||
|
||||
var STATE_UNKNOWN = 0;
|
||||
var STATE_SELECT = 1;
|
||||
var STATE_DRAG = 2;
|
||||
|
||||
var DRAG_TIMER = 250; // milliseconds
|
||||
var DRAG_OFFSET = 5; // pixels
|
||||
|
||||
var MouseHandler = function(editor) {
|
||||
this.editor = editor;
|
||||
event.addListener(editor.container, "mousedown", function(e) {
|
||||
editor.focus();
|
||||
return event.preventDefault(e);
|
||||
});
|
||||
event.addListener(editor.container, "selectstart", function(e) {
|
||||
return event.preventDefault(e);
|
||||
});
|
||||
|
||||
var mouseTarget = editor.renderer.getMouseEventTarget();
|
||||
event.addListener(mouseTarget, "mousedown", this.onMouseDown.bind(this));
|
||||
event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseDoubleClick.bind(this));
|
||||
event.addMultiMouseDownListener(mouseTarget, 0, 3, 600, this.onMouseTripleClick.bind(this));
|
||||
event.addMultiMouseDownListener(mouseTarget, 0, 4, 600, this.onMouseQuadClick.bind(this));
|
||||
event.addMouseWheelListener(mouseTarget, this.onMouseWheel.bind(this));
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
this.$scrollSpeed = 1;
|
||||
this.setScrollSpeed = function(speed) {
|
||||
this.$scrollSpeed = speed;
|
||||
};
|
||||
|
||||
this.getScrollSpeed = function() {
|
||||
return this.$scrollSpeed;
|
||||
};
|
||||
|
||||
this.$getEventPosition = function(e) {
|
||||
var pageX = event.getDocumentX(e);
|
||||
var pageY = event.getDocumentY(e);
|
||||
var pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);
|
||||
pos.row = Math.max(0, Math.min(pos.row, this.editor.session.getLength()-1));
|
||||
return pos;
|
||||
};
|
||||
|
||||
this.$distance = function(ax, ay, bx, by) {
|
||||
return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
|
||||
};
|
||||
|
||||
this.onMouseDown = function(e) {
|
||||
var pageX = event.getDocumentX(e);
|
||||
var pageY = event.getDocumentY(e);
|
||||
var pos = this.$getEventPosition(e);
|
||||
var editor = this.editor;
|
||||
var self = this;
|
||||
var selectionRange = editor.getSelectionRange();
|
||||
var selectionEmpty = selectionRange.isEmpty();
|
||||
var state = STATE_UNKNOWN;
|
||||
var inSelection = false;
|
||||
|
||||
var button = event.getButton(e);
|
||||
if (button !== 0) {
|
||||
if (selectionEmpty) {
|
||||
editor.moveCursorToPosition(pos);
|
||||
}
|
||||
if(button == 2) {
|
||||
editor.textInput.onContextMenu({x: pageX, y: pageY}, selectionEmpty);
|
||||
event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
inSelection = !editor.getReadOnly()
|
||||
&& !selectionEmpty
|
||||
&& selectionRange.contains(pos.row, pos.column);
|
||||
}
|
||||
|
||||
if (!inSelection) {
|
||||
// Directly pick STATE_SELECT, since the user is not clicking inside
|
||||
// a selection.
|
||||
onStartSelect(pos);
|
||||
}
|
||||
|
||||
editor.renderer.scrollCursorIntoView();
|
||||
|
||||
var mousePageX, mousePageY;
|
||||
var overwrite = editor.getOverwrite();
|
||||
var mousedownTime = (new Date()).getTime();
|
||||
var dragCursor, dragRange;
|
||||
|
||||
var onMouseSelection = function(e) {
|
||||
mousePageX = event.getDocumentX(e);
|
||||
mousePageY = event.getDocumentY(e);
|
||||
};
|
||||
|
||||
var onMouseSelectionEnd = function() {
|
||||
clearInterval(timerId);
|
||||
if (state == STATE_UNKNOWN)
|
||||
onStartSelect(pos);
|
||||
else if (state == STATE_DRAG)
|
||||
onMouseDragSelectionEnd();
|
||||
|
||||
self.$clickSelection = null;
|
||||
state = STATE_UNKNOWN;
|
||||
};
|
||||
|
||||
var onMouseDragSelectionEnd = function() {
|
||||
dom.removeCssClass(editor.container, "ace_dragging");
|
||||
editor.session.removeMarker(dragSelectionMarker);
|
||||
|
||||
if (!self.$clickSelection) {
|
||||
if (!dragCursor) {
|
||||
editor.moveCursorToPosition(pos);
|
||||
editor.selection.clearSelection(pos.row, pos.column);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dragCursor)
|
||||
return;
|
||||
|
||||
if (dragRange.contains(dragCursor.row, dragCursor.column)) {
|
||||
dragCursor = null;
|
||||
return;
|
||||
}
|
||||
|
||||
editor.clearSelection();
|
||||
var newRange = editor.moveText(dragRange, dragCursor);
|
||||
if (!newRange) {
|
||||
dragCursor = null;
|
||||
return;
|
||||
}
|
||||
|
||||
editor.selection.setSelectionRange(newRange);
|
||||
};
|
||||
|
||||
var onSelectionInterval = function() {
|
||||
if (mousePageX === undefined || mousePageY === undefined)
|
||||
return;
|
||||
|
||||
if (state == STATE_UNKNOWN) {
|
||||
var distance = self.$distance(pageX, pageY, mousePageX, mousePageY);
|
||||
var time = (new Date()).getTime();
|
||||
|
||||
|
||||
if (distance > DRAG_OFFSET) {
|
||||
state = STATE_SELECT;
|
||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
||||
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
|
||||
onStartSelect(cursor);
|
||||
} else if ((time - mousedownTime) > DRAG_TIMER) {
|
||||
state = STATE_DRAG;
|
||||
dragRange = editor.getSelectionRange();
|
||||
var style = editor.getSelectionStyle();
|
||||
dragSelectionMarker = editor.session.addMarker(dragRange, "ace_selection", style);
|
||||
editor.clearSelection();
|
||||
dom.addCssClass(editor.container, "ace_dragging");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (state == STATE_DRAG)
|
||||
onDragSelectionInterval();
|
||||
else if (state == STATE_SELECT)
|
||||
onUpdateSelectionInterval();
|
||||
};
|
||||
|
||||
function onStartSelect(pos) {
|
||||
if (e.shiftKey)
|
||||
editor.selection.selectToPosition(pos)
|
||||
else {
|
||||
if (!self.$clickSelection) {
|
||||
editor.moveCursorToPosition(pos);
|
||||
editor.selection.clearSelection(pos.row, pos.column);
|
||||
}
|
||||
}
|
||||
state = STATE_SELECT;
|
||||
}
|
||||
|
||||
var onUpdateSelectionInterval = function() {
|
||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
||||
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
|
||||
|
||||
if (self.$clickSelection) {
|
||||
if (self.$clickSelection.contains(cursor.row, cursor.column)) {
|
||||
editor.selection.setSelectionRange(self.$clickSelection);
|
||||
} else {
|
||||
if (self.$clickSelection.compare(cursor.row, cursor.column) == -1) {
|
||||
var anchor = self.$clickSelection.end;
|
||||
} else {
|
||||
var anchor = self.$clickSelection.start;
|
||||
}
|
||||
editor.selection.setSelectionAnchor(anchor.row, anchor.column);
|
||||
editor.selection.selectToPosition(cursor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
editor.selection.selectToPosition(cursor);
|
||||
}
|
||||
|
||||
editor.renderer.scrollCursorIntoView();
|
||||
};
|
||||
|
||||
var onDragSelectionInterval = function() {
|
||||
dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
||||
dragCursor.row = Math.max(0, Math.min(dragCursor.row,
|
||||
editor.session.getLength() - 1));
|
||||
|
||||
editor.moveCursorToPosition(dragCursor);
|
||||
};
|
||||
|
||||
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
|
||||
var timerId = setInterval(onSelectionInterval, 20);
|
||||
|
||||
return event.preventDefault(e);
|
||||
};
|
||||
|
||||
this.onMouseDoubleClick = function(e) {
|
||||
var pos = this.$getEventPosition(e);
|
||||
this.editor.moveCursorToPosition(pos);
|
||||
this.editor.selection.selectWord();
|
||||
this.$clickSelection = this.editor.getSelectionRange();
|
||||
};
|
||||
|
||||
this.onMouseTripleClick = function(e) {
|
||||
var pos = this.$getEventPosition(e);
|
||||
this.editor.moveCursorToPosition(pos);
|
||||
this.editor.selection.selectLine();
|
||||
this.$clickSelection = this.editor.getSelectionRange();
|
||||
};
|
||||
|
||||
this.onMouseQuadClick = function(e) {
|
||||
this.editor.selectAll();
|
||||
this.$clickSelection = this.editor.getSelectionRange();
|
||||
};
|
||||
|
||||
this.onMouseWheel = function(e) {
|
||||
var speed = this.$scrollSpeed * 2;
|
||||
|
||||
this.editor.renderer.scrollBy(e.wheelX * speed, e.wheelY * speed);
|
||||
return event.preventDefault(e);
|
||||
};
|
||||
|
||||
|
||||
}).call(MouseHandler.prototype);
|
||||
|
||||
exports.MouseHandler = MouseHandler;
|
||||
});
|
||||
375
lib/ace/narcissus/jsdefs.js
Normal file
375
lib/ace/narcissus/jsdefs.js
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** 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 the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Well-known constants and lookup tables. Many consts are generated from the
|
||||
* tokens table via eval to minimize redundancy, so consumers must be compiled
|
||||
* separately to take advantage of the simple switch-case constant propagation
|
||||
* done by SpiderMonkey.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
exports.options = {
|
||||
version: 185,
|
||||
};
|
||||
|
||||
(function() {
|
||||
exports.hostGlobal = this
|
||||
})();
|
||||
|
||||
var tokens = [
|
||||
// End of source.
|
||||
"END",
|
||||
|
||||
// Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
|
||||
// and (UNARY_PLUS, UNARY_MINUS).
|
||||
"\n", ";",
|
||||
",",
|
||||
"=",
|
||||
"?", ":", "CONDITIONAL",
|
||||
"||",
|
||||
"&&",
|
||||
"|",
|
||||
"^",
|
||||
"&",
|
||||
"==", "!=", "===", "!==",
|
||||
"<", "<=", ">=", ">",
|
||||
"<<", ">>", ">>>",
|
||||
"+", "-",
|
||||
"*", "/", "%",
|
||||
"!", "~", "UNARY_PLUS", "UNARY_MINUS",
|
||||
"++", "--",
|
||||
".",
|
||||
"[", "]",
|
||||
"{", "}",
|
||||
"(", ")",
|
||||
|
||||
// Nonterminal tree node type codes.
|
||||
"SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
|
||||
"ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
|
||||
"GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
|
||||
|
||||
// Terminals.
|
||||
"IDENTIFIER", "NUMBER", "STRING", "REGEXP",
|
||||
|
||||
// Keywords.
|
||||
"break",
|
||||
"case", "catch", "const", "continue",
|
||||
"debugger", "default", "delete", "do",
|
||||
"else",
|
||||
"false", "finally", "for", "function",
|
||||
"if", "in", "instanceof",
|
||||
"let",
|
||||
"new", "null",
|
||||
"return",
|
||||
"switch",
|
||||
"this", "throw", "true", "try", "typeof",
|
||||
"var", "void",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
var statementStartTokens = [
|
||||
"break",
|
||||
"const", "continue",
|
||||
"debugger", "do",
|
||||
"for",
|
||||
"if",
|
||||
"return",
|
||||
"switch",
|
||||
"throw", "try",
|
||||
"var",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
// Operator and punctuator mapping from token to tree node type name.
|
||||
// NB: because the lexer doesn't backtrack, all token prefixes must themselves
|
||||
// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
|
||||
// tokens != and !).
|
||||
var opTypeNames = {
|
||||
'\n': "NEWLINE",
|
||||
';': "SEMICOLON",
|
||||
',': "COMMA",
|
||||
'?': "HOOK",
|
||||
':': "COLON",
|
||||
'||': "OR",
|
||||
'&&': "AND",
|
||||
'|': "BITWISE_OR",
|
||||
'^': "BITWISE_XOR",
|
||||
'&': "BITWISE_AND",
|
||||
'===': "STRICT_EQ",
|
||||
'==': "EQ",
|
||||
'=': "ASSIGN",
|
||||
'!==': "STRICT_NE",
|
||||
'!=': "NE",
|
||||
'<<': "LSH",
|
||||
'<=': "LE",
|
||||
'<': "LT",
|
||||
'>>>': "URSH",
|
||||
'>>': "RSH",
|
||||
'>=': "GE",
|
||||
'>': "GT",
|
||||
'++': "INCREMENT",
|
||||
'--': "DECREMENT",
|
||||
'+': "PLUS",
|
||||
'-': "MINUS",
|
||||
'*': "MUL",
|
||||
'/': "DIV",
|
||||
'%': "MOD",
|
||||
'!': "NOT",
|
||||
'~': "BITWISE_NOT",
|
||||
'.': "DOT",
|
||||
'[': "LEFT_BRACKET",
|
||||
']': "RIGHT_BRACKET",
|
||||
'{': "LEFT_CURLY",
|
||||
'}': "RIGHT_CURLY",
|
||||
'(': "LEFT_PAREN",
|
||||
')': "RIGHT_PAREN"
|
||||
};
|
||||
|
||||
// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
|
||||
// avoid toString, etc. namespace pollution.
|
||||
var keywords = {__proto__: null};
|
||||
|
||||
// Define const END, etc., based on the token names. Also map name to index.
|
||||
var tokenIds = {};
|
||||
|
||||
// Building up a string to be eval'd in different contexts.
|
||||
var consts = "const ";
|
||||
for (var i = 0, j = tokens.length; i < j; i++) {
|
||||
if (i > 0)
|
||||
consts += ", ";
|
||||
var t = tokens[i];
|
||||
var name;
|
||||
if (/^[a-z]/.test(t)) {
|
||||
name = t.toUpperCase();
|
||||
keywords[t] = i;
|
||||
} else {
|
||||
name = (/^\W/.test(t) ? opTypeNames[t] : t);
|
||||
}
|
||||
consts += name + " = " + i;
|
||||
tokenIds[name] = i;
|
||||
tokens[t] = i;
|
||||
}
|
||||
consts += ";";
|
||||
|
||||
var isStatementStartCode = {__proto__: null};
|
||||
for (i = 0, j = statementStartTokens.length; i < j; i++)
|
||||
isStatementStartCode[keywords[statementStartTokens[i]]] = true;
|
||||
|
||||
// Map assignment operators to their indexes in the tokens array.
|
||||
var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
|
||||
|
||||
for (i = 0, j = assignOps.length; i < j; i++) {
|
||||
t = assignOps[i];
|
||||
assignOps[t] = tokens[t];
|
||||
}
|
||||
|
||||
function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ get: fn, configurable: !dontDelete, enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ value: val, writable: !readOnly, configurable: !dontDelete,
|
||||
enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
// Returns true if fn is a native function. (Note: SpiderMonkey specific.)
|
||||
function isNativeCode(fn) {
|
||||
// Relies on the toString method to identify native code.
|
||||
return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
|
||||
}
|
||||
|
||||
function getPropertyDescriptor(obj, name) {
|
||||
while (obj) {
|
||||
if (({}).hasOwnProperty.call(obj, name))
|
||||
return Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function getOwnProperties(obj) {
|
||||
var map = {};
|
||||
for (var name in Object.getOwnPropertyNames(obj))
|
||||
map[name] = Object.getOwnPropertyDescriptor(obj, name);
|
||||
return map;
|
||||
}
|
||||
|
||||
function makePassthruHandler(obj) {
|
||||
// Handler copied from
|
||||
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||
return {
|
||||
getOwnPropertyDescriptor: function(name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getPropertyDescriptor: function(name) {
|
||||
var desc = getPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getOwnPropertyNames: function() {
|
||||
return Object.getOwnPropertyNames(obj);
|
||||
},
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(obj, name, desc);
|
||||
},
|
||||
"delete": function(name) { return delete obj[name]; },
|
||||
fix: function() {
|
||||
if (Object.isFrozen(obj)) {
|
||||
return getOwnProperties(obj);
|
||||
}
|
||||
|
||||
// As long as obj is not frozen, the proxy won't allow itself to be fixed.
|
||||
return undefined; // will cause a TypeError to be thrown
|
||||
},
|
||||
|
||||
has: function(name) { return name in obj; },
|
||||
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
||||
get: function(receiver, name) { return obj[name]; },
|
||||
|
||||
// bad behavior when set fails in non-strict mode
|
||||
set: function(receiver, name, val) { obj[name] = val; return true; },
|
||||
enumerate: function() {
|
||||
var result = [];
|
||||
for (name in obj) { result.push(name); };
|
||||
return result;
|
||||
},
|
||||
keys: function() { return Object.keys(obj); }
|
||||
};
|
||||
}
|
||||
|
||||
// default function used when looking for a property in the global object
|
||||
function noPropFound() { return undefined; }
|
||||
|
||||
var hasOwnProperty = ({}).hasOwnProperty;
|
||||
|
||||
function StringMap() {
|
||||
this.table = Object.create(null, {});
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
StringMap.prototype = {
|
||||
has: function(x) { return hasOwnProperty.call(this.table, x); },
|
||||
set: function(x, v) {
|
||||
if (!hasOwnProperty.call(this.table, x))
|
||||
this.size++;
|
||||
this.table[x] = v;
|
||||
},
|
||||
get: function(x) { return this.table[x]; },
|
||||
getDef: function(x, thunk) {
|
||||
if (!hasOwnProperty.call(this.table, x)) {
|
||||
this.size++;
|
||||
this.table[x] = thunk();
|
||||
}
|
||||
return this.table[x];
|
||||
},
|
||||
forEach: function(f) {
|
||||
var table = this.table;
|
||||
for (var key in table)
|
||||
f.call(this, key, table[key]);
|
||||
},
|
||||
toString: function() { return "[object StringMap]" }
|
||||
};
|
||||
|
||||
// non-destructive stack
|
||||
function Stack(elts) {
|
||||
this.elts = elts || null;
|
||||
}
|
||||
|
||||
Stack.prototype = {
|
||||
push: function(x) {
|
||||
return new Stack({ top: x, rest: this.elts });
|
||||
},
|
||||
top: function() {
|
||||
if (!this.elts)
|
||||
throw new Error("empty stack");
|
||||
return this.elts.top;
|
||||
},
|
||||
isEmpty: function() {
|
||||
return this.top === null;
|
||||
},
|
||||
find: function(test) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
if (test(elts.top))
|
||||
return elts.top;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
has: function(x) {
|
||||
return Boolean(this.find(function(elt) { return elt === x }));
|
||||
},
|
||||
forEach: function(f) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
f(elts.top);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.tokens = tokens;
|
||||
exports.opTypeNames = opTypeNames;
|
||||
exports.keywords = keywords;
|
||||
exports.isStatementStartCode = isStatementStartCode;
|
||||
exports.tokenIds = tokenIds;
|
||||
exports.consts = consts;
|
||||
exports.assignOps = assignOps;
|
||||
exports.defineGetter = defineGetter;
|
||||
exports.defineProperty = defineProperty;
|
||||
exports.isNativeCode = isNativeCode;
|
||||
exports.makePassthruHandler = makePassthruHandler;
|
||||
exports.noPropFound = noPropFound;
|
||||
exports.StringMap = StringMap;
|
||||
exports.Stack = Stack;
|
||||
|
||||
});
|
||||
462
lib/ace/narcissus/jslex.js
Normal file
462
lib/ace/narcissus/jslex.js
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** 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 the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Lexical scanner.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var definitions = require("ace/narcissus/jsdefs");
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(definitions.consts);
|
||||
|
||||
// Build up a trie of operator tokens.
|
||||
var opTokens = {};
|
||||
for (var op in definitions.opTypeNames) {
|
||||
if (op === '\n' || op === '.')
|
||||
continue;
|
||||
|
||||
var node = opTokens;
|
||||
for (var i = 0; i < op.length; i++) {
|
||||
var ch = op[i];
|
||||
if (!(ch in node))
|
||||
node[ch] = {};
|
||||
node = node[ch];
|
||||
node.op = op;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenizer :: (source, filename, line number) -> Tokenizer
|
||||
*/
|
||||
function Tokenizer(s, f, l) {
|
||||
this.cursor = 0;
|
||||
this.source = String(s);
|
||||
this.tokens = [];
|
||||
this.tokenIndex = 0;
|
||||
this.lookahead = 0;
|
||||
this.scanNewlines = false;
|
||||
this.unexpectedEOF = false;
|
||||
this.filename = f || "";
|
||||
this.lineno = l || 1;
|
||||
}
|
||||
|
||||
Tokenizer.prototype = {
|
||||
get done() {
|
||||
// We need to set scanOperand to true here because the first thing
|
||||
// might be a regexp.
|
||||
return this.peek(true) === END;
|
||||
},
|
||||
|
||||
get token() {
|
||||
return this.tokens[this.tokenIndex];
|
||||
},
|
||||
|
||||
match: function (tt, scanOperand) {
|
||||
return this.get(scanOperand) === tt || this.unget();
|
||||
},
|
||||
|
||||
mustMatch: function (tt) {
|
||||
if (!this.match(tt)) {
|
||||
throw this.newSyntaxError("Missing " +
|
||||
definitions.tokens[tt].toLowerCase());
|
||||
}
|
||||
return this.token;
|
||||
},
|
||||
|
||||
peek: function (scanOperand) {
|
||||
var tt, next;
|
||||
if (this.lookahead) {
|
||||
next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
|
||||
tt = (this.scanNewlines && next.lineno !== this.lineno)
|
||||
? NEWLINE
|
||||
: next.type;
|
||||
} else {
|
||||
tt = this.get(scanOperand);
|
||||
this.unget();
|
||||
}
|
||||
return tt;
|
||||
},
|
||||
|
||||
peekOnSameLine: function (scanOperand) {
|
||||
this.scanNewlines = true;
|
||||
var tt = this.peek(scanOperand);
|
||||
this.scanNewlines = false;
|
||||
return tt;
|
||||
},
|
||||
|
||||
// Eat comments and whitespace.
|
||||
skip: function () {
|
||||
var input = this.source;
|
||||
for (;;) {
|
||||
var ch = input[this.cursor++];
|
||||
var next = input[this.cursor];
|
||||
if (ch === '\n' && !this.scanNewlines) {
|
||||
this.lineno++;
|
||||
} else if (ch === '/' && next === '*') {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated comment");
|
||||
|
||||
if (ch === '*') {
|
||||
next = input[this.cursor];
|
||||
if (next === '/') {
|
||||
this.cursor++;
|
||||
break;
|
||||
}
|
||||
} else if (ch === '\n') {
|
||||
this.lineno++;
|
||||
}
|
||||
}
|
||||
} else if (ch === '/' && next === '/') {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
return;
|
||||
|
||||
if (ch === '\n') {
|
||||
this.lineno++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ch !== ' ' && ch !== '\t') {
|
||||
this.cursor--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Lex the exponential part of a number, if present. Return true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
var input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next === 'e' || next === 'E') {
|
||||
this.cursor++;
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else if (ch === 'x' || ch === 'X') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||
(ch >= 'A' && ch <= 'F'));
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else if (ch >= '0' && ch <= '7') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '7');
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else {
|
||||
this.cursor--;
|
||||
this.lexExponent(); // 0E1, &c.
|
||||
token.value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
lexNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
var floating = false;
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.' && !floating) {
|
||||
floating = true;
|
||||
ch = input[this.cursor++];
|
||||
}
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
var exponent = this.lexExponent();
|
||||
floating = floating || exponent;
|
||||
|
||||
var str = input.substring(token.start, this.cursor);
|
||||
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||
},
|
||||
|
||||
lexDot: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next >= '0' && next <= '9') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
|
||||
token.type = NUMBER;
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else {
|
||||
token.type = DOT;
|
||||
token.assignOp = null;
|
||||
token.value = '.';
|
||||
}
|
||||
},
|
||||
|
||||
lexString: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = STRING;
|
||||
|
||||
var hasEscapes = false;
|
||||
var delim = ch;
|
||||
if (input.length <= this.cursor)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
while ((ch = input[this.cursor++]) !== delim) {
|
||||
if (this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (ch === '\\') {
|
||||
hasEscapes = true;
|
||||
if (++this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
}
|
||||
}
|
||||
|
||||
token.value = hasEscapes
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
this.cursor++;
|
||||
} else if (ch === '[') {
|
||||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||
// for only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
var next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
}
|
||||
}
|
||||
|
||||
var op = node.op;
|
||||
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
token.type = ASSIGN;
|
||||
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
op += '=';
|
||||
} else {
|
||||
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
|
||||
token.value = op;
|
||||
},
|
||||
|
||||
// FIXME: Unicode escape sequences
|
||||
// FIXME: Unicode identifiers
|
||||
lexIdent: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') || ch === '$' || ch === '_');
|
||||
|
||||
this.cursor--; // Put the non-word character back.
|
||||
|
||||
var id = input.substring(token.start, this.cursor);
|
||||
token.type = definitions.keywords[id] || IDENTIFIER;
|
||||
token.value = id;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.get :: void -> token type
|
||||
*
|
||||
* Consume input *only* if there is no lookahead.
|
||||
* Dispatch to the appropriate lexing function depending on the input.
|
||||
*/
|
||||
get: function (scanOperand) {
|
||||
var token;
|
||||
while (this.lookahead) {
|
||||
--this.lookahead;
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (token.type !== NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
|
||||
this.skip();
|
||||
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
|
||||
var input = this.source;
|
||||
if (this.cursor === input.length)
|
||||
return token.type = END;
|
||||
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
|
||||
var ch = input[this.cursor++];
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_') {
|
||||
this.lexIdent(ch);
|
||||
} else if (scanOperand && ch === '/') {
|
||||
this.lexRegExp(ch);
|
||||
} else if (ch in opTokens) {
|
||||
this.lexOp(ch);
|
||||
} else if (ch === '.') {
|
||||
this.lexDot(ch);
|
||||
} else if (ch >= '1' && ch <= '9') {
|
||||
this.lexNumber(ch);
|
||||
} else if (ch === '0') {
|
||||
this.lexZeroNumber(ch);
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
this.lexString(ch);
|
||||
} else if (this.scanNewlines && ch === '\n') {
|
||||
token.type = NEWLINE;
|
||||
token.value = '\n';
|
||||
this.lineno++;
|
||||
} else {
|
||||
throw this.newSyntaxError("Illegal token");
|
||||
}
|
||||
|
||||
token.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
* Match depends on unget returning undefined.
|
||||
*/
|
||||
unget: function () {
|
||||
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
|
||||
newSyntaxError: function (m) {
|
||||
var e = new SyntaxError(m, this.filename, this.lineno);
|
||||
e.source = this.source;
|
||||
e.lineno = this.lineno;
|
||||
e.cursor = this.lookahead
|
||||
? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
|
||||
: this.cursor;
|
||||
return e;
|
||||
},
|
||||
};
|
||||
|
||||
exports.Tokenizer = Tokenizer;
|
||||
|
||||
});
|
||||
1432
lib/ace/narcissus/jsparse.js
Normal file
1432
lib/ace/narcissus/jsparse.js
Normal file
File diff suppressed because it is too large
Load diff
152
lib/ace/range.js
152
lib/ace/range.js
|
|
@ -60,6 +60,114 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
return this.compare(row, column) == 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares this range (A) with another range (B), where B is the passed in
|
||||
* range.
|
||||
*
|
||||
* Return values:
|
||||
* -2: (B) is infront of (A) and doesn't intersect with (A)
|
||||
* -1: (B) begins before (A) but ends inside of (A)
|
||||
* 0: (B) is completly inside of (A) OR (A) is complety inside of (B)
|
||||
* +1: (B) begins inside of (A) but ends outside of (A)
|
||||
* +2: (B) is after (A) and doesn't intersect with (A)
|
||||
*
|
||||
* 42: FTW state: (B) ends in (A) but starts outside of (A)
|
||||
*/
|
||||
this.compareRange = function(range) {
|
||||
var cmp,
|
||||
end = range.end,
|
||||
start = range.start;
|
||||
|
||||
cmp = this.compare(end.row, end.column);
|
||||
if (cmp == 1) {
|
||||
cmp = this.compare(start.row, start.column);
|
||||
if (cmp == 1) {
|
||||
return 2;
|
||||
} else if (cmp == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (cmp == -1) {
|
||||
return -2;
|
||||
} else {
|
||||
cmp = this.compare(start.row, start.column);
|
||||
if (cmp == -1) {
|
||||
return -1;
|
||||
} else if (cmp == 1) {
|
||||
return 42;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.containsRange = function(range) {
|
||||
var cmp = this.compareRange(range);
|
||||
return (cmp == -1 || cmp == 0 || cmp == 1);
|
||||
}
|
||||
|
||||
this.isEnd = function(row, column) {
|
||||
return this.end.row == row && this.end.column == column;
|
||||
}
|
||||
|
||||
this.isStart = function(row, column) {
|
||||
return this.start.row == row && this.start.column == column;
|
||||
}
|
||||
|
||||
this.setStart = function(row, column) {
|
||||
if (typeof row == "object") {
|
||||
this.start.column = row.column;
|
||||
this.start.row = row.row;
|
||||
} else {
|
||||
this.start.row = row;
|
||||
this.start.column = column;
|
||||
}
|
||||
}
|
||||
|
||||
this.setEnd = function(row, column) {
|
||||
if (typeof row == "object") {
|
||||
this.end.column = row.column;
|
||||
this.end.row = row.row;
|
||||
} else {
|
||||
this.end.row = row;
|
||||
this.end.column = column;
|
||||
}
|
||||
}
|
||||
|
||||
this.inside = function(row, column) {
|
||||
if (this.compare(row, column) == 0) {
|
||||
if (this.isEnd(row, column) || this.isStart(row, column)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.insideStart = function(row, column) {
|
||||
if (this.compare(row, column) == 0) {
|
||||
if (this.isEnd(row, column)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.insideEnd = function(row, column) {
|
||||
if (this.compare(row, column) == 0) {
|
||||
if (this.isStart(row, column)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.compare = function(row, column) {
|
||||
if (!this.isMultiLine()) {
|
||||
if (row === this.start.row) {
|
||||
|
|
@ -82,6 +190,38 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Like .compare(), but if isStart is true, return -1;
|
||||
*/
|
||||
this.compareStart = function(row, column) {
|
||||
if (this.start.row == row && this.start.column == column) {
|
||||
return -1;
|
||||
} else {
|
||||
return this.compare(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Like .compare(), but if isEnd is true, return 1;
|
||||
*/
|
||||
this.compareEnd = function(row, column) {
|
||||
if (this.end.row == row && this.end.column == column) {
|
||||
return 1;
|
||||
} else {
|
||||
return this.compare(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
this.compareInside = function(row, column) {
|
||||
if (this.end.row == row && this.end.column == column) {
|
||||
return 1;
|
||||
} else if (this.start.row == row && this.start.column == column) {
|
||||
return -1;
|
||||
} else {
|
||||
return this.compare(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
this.clipRows = function(firstRow, lastRow) {
|
||||
if (this.end.row > lastRow) {
|
||||
var end = {
|
||||
|
|
@ -137,7 +277,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
this.clone = function() {
|
||||
return Range.fromPoints(this.start, this.end);
|
||||
};
|
||||
|
||||
|
||||
this.collapseRows = function() {
|
||||
if (this.end.column == 0)
|
||||
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
|
||||
|
|
@ -145,10 +285,14 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
return new Range(this.start.row, 0, this.end.row, 0)
|
||||
};
|
||||
|
||||
this.toScreenRange = function(doc) {
|
||||
this.toScreenRange = function(session) {
|
||||
var screenPosStart =
|
||||
session.documentToScreenPosition(this.start);
|
||||
var screenPosEnd =
|
||||
session.documentToScreenPosition(this.end);
|
||||
return new Range(
|
||||
this.start.row, doc.documentToScreenColumn(this.start.row, this.start.column),
|
||||
this.end.row, doc.documentToScreenColumn(this.end.row, this.end.column)
|
||||
screenPosStart.row, screenPosStart.column,
|
||||
screenPosEnd.row, screenPosEnd.column
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,12 +35,19 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Range = require("../range").Range,
|
||||
assert = require("./assertions");
|
||||
var Range = require("ace/range").Range;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
|
||||
name: "ACE range.js",
|
||||
|
||||
"test: create range": function() {
|
||||
var range = new Range(1,2,3,4);
|
||||
|
||||
|
|
@ -132,39 +139,37 @@ var Test = {
|
|||
|
||||
var range = range.extend(2, 5);
|
||||
assert.range(range, 2, 5, 2, 30);
|
||||
|
||||
|
||||
var range = range.extend(2, 35);
|
||||
assert.range(range, 2, 5, 2, 35);
|
||||
|
||||
|
||||
var range = range.extend(2, 15);
|
||||
assert.range(range, 2, 5, 2, 35);
|
||||
|
||||
|
||||
var range = range.extend(1, 4);
|
||||
assert.range(range, 1, 4, 2, 35);
|
||||
|
||||
|
||||
var range = range.extend(6, 10);
|
||||
assert.range(range, 1, 4, 6, 10);
|
||||
},
|
||||
|
||||
|
||||
"test: collapse rows" : function() {
|
||||
var range = new Range(0, 2, 1, 2);
|
||||
assert.range(range.collapseRows(), 0, 0, 1, 0);
|
||||
assert.range(range.collapseRows(), 0, 0, 1, 0);
|
||||
|
||||
var range = new Range(2, 2, 3, 1);
|
||||
assert.range(range.collapseRows(), 2, 0, 3, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 3, 0);
|
||||
|
||||
var range = new Range(2, 2, 3, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 2, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 2, 0);
|
||||
|
||||
var range = new Range(2, 0, 2, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 2, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 2, 0);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -43,16 +43,16 @@ var event = require("pilot/event");
|
|||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
var ScrollBar = function(parent) {
|
||||
this.element = document.createElement("div");
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_sb";
|
||||
|
||||
this.inner = document.createElement("div");
|
||||
this.inner = dom.createElement("div");
|
||||
this.element.appendChild(this.inner);
|
||||
|
||||
parent.appendChild(this.element);
|
||||
|
||||
this.width = dom.scrollbarWidth();
|
||||
this.element.style.width = this.width;
|
||||
this.element.style.width = this.width + "px";
|
||||
|
||||
event.addListener(this.element, "scroll", this.onScroll.bind(this));
|
||||
};
|
||||
|
|
@ -69,7 +69,7 @@ var ScrollBar = function(parent) {
|
|||
};
|
||||
|
||||
this.setHeight = function(height) {
|
||||
this.element.style.height = Math.max(0, height - this.width) + "px";
|
||||
this.element.style.height = height + "px";
|
||||
};
|
||||
|
||||
this.setInnerHeight = function(height) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -67,14 +69,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 +88,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 +120,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 +154,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,23 +210,27 @@ 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;
|
||||
var inWrap = false;
|
||||
|
||||
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);
|
||||
}
|
||||
if (inWrap && row == start.row) {
|
||||
line = line.substring(0, start.column);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
|
|
@ -236,6 +242,7 @@ Search.SELECTION = 2;
|
|||
var startIndex = start.column;
|
||||
|
||||
var stop = false;
|
||||
inWrap = false;
|
||||
|
||||
while (!callback(line, startIndex, row)) {
|
||||
|
||||
|
|
@ -250,6 +257,7 @@ Search.SELECTION = 2;
|
|||
if (wrap) {
|
||||
row = firstRow;
|
||||
startIndex = firstColumn;
|
||||
inWrap = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -264,15 +272,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,9 +288,10 @@ 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;
|
||||
var inWrap = false;
|
||||
|
||||
while (!callback(line, startIndex, row)) {
|
||||
|
||||
|
|
@ -295,6 +304,7 @@ Search.SELECTION = 2;
|
|||
if (row < firstRow) {
|
||||
if (wrap) {
|
||||
row = lastRow;
|
||||
inWrap = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -303,13 +313,16 @@ Search.SELECTION = 2;
|
|||
if (row == start.row)
|
||||
stop = true;
|
||||
|
||||
line = doc.getLine(row);
|
||||
line = session.getLine(row);
|
||||
if (searchSelection) {
|
||||
if (row == firstRow)
|
||||
startIndex = firstColumn;
|
||||
else if (row == lastRow)
|
||||
line = line.substring(0, range.end.column);
|
||||
}
|
||||
|
||||
if (inWrap && row == start.row)
|
||||
startIndex = start.column;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -35,13 +36,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("../document").Document,
|
||||
Search = require("../search").Search,
|
||||
assert = require("./assertions");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Search = require("ace/search").Search;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
"test: configure the search object" : function() {
|
||||
var search = new Search();
|
||||
search.set({
|
||||
|
|
@ -51,128 +56,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 +185,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 +207,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 +244,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 +273,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", " <h1 abc"]);
|
||||
var session = new EditSession([" ab: 12px", " <h1 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, 6);
|
||||
assert.position(range.end, 0, 8);
|
||||
},
|
||||
|
||||
"test: find all matches 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: "uh",
|
||||
|
|
@ -295,10 +300,10 @@ 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 ranges = search.findAll(doc);
|
||||
var ranges = search.findAll(session);
|
||||
|
||||
assert.equal(ranges.length, 2);
|
||||
assert.position(ranges[0].start, 1, 1);
|
||||
|
|
@ -341,13 +346,56 @@ var Test = {
|
|||
assert.equal(search.replace("ab12", "cd$1"), "cd12");
|
||||
assert.equal(search.replace("ab12", "-$&-"), "-ab12-");
|
||||
assert.equal(search.replace("ab12", "$$"), "$");
|
||||
}
|
||||
},
|
||||
|
||||
"test: find all matches in a line" : function() {
|
||||
var session = new EditSession("foo bar foo baz foobar foo");
|
||||
|
||||
var search = new Search().set({
|
||||
needle: "foo",
|
||||
wrap: true,
|
||||
wholeWord: true,
|
||||
});
|
||||
|
||||
session.getSelection().moveCursorTo(0, 4);
|
||||
|
||||
var ranges = search.findAll(session);
|
||||
|
||||
assert.equal(ranges.length, 3);
|
||||
assert.position(ranges[0].start, 0, 8);
|
||||
assert.position(ranges[0].end, 0, 11);
|
||||
assert.position(ranges[1].start, 0, 23);
|
||||
assert.position(ranges[1].end, 0, 26);
|
||||
assert.position(ranges[2].start, 0, 0);
|
||||
assert.position(ranges[2].end, 0, 3);
|
||||
},
|
||||
|
||||
"test: find all matches in a line backwards" : function() {
|
||||
var session = new EditSession("foo bar foo baz foobar foo");
|
||||
|
||||
var search = new Search().set({
|
||||
needle: "foo",
|
||||
wrap: true,
|
||||
wholeWord: true,
|
||||
backwards: true,
|
||||
});
|
||||
|
||||
session.getSelection().moveCursorTo(0, 13);
|
||||
|
||||
var ranges = search.findAll(session);
|
||||
|
||||
assert.equal(ranges.length, 3);
|
||||
assert.position(ranges[0].start, 0, 8);
|
||||
assert.position(ranges[0].end, 0, 11);
|
||||
assert.position(ranges[1].start, 0, 0);
|
||||
assert.position(ranges[1].end, 0, 3);
|
||||
assert.position(ranges[2].start, 0, 23);
|
||||
assert.position(ranges[2].end, 0, 26);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test)
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -42,14 +43,27 @@ var lang = require("pilot/lang");
|
|||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
var Selection = function(doc) {
|
||||
this.doc = doc;
|
||||
var Selection = function(session) {
|
||||
this.session = session;
|
||||
this.doc = session.getDocument();
|
||||
|
||||
this.clearSelection();
|
||||
this.selectionLead = {
|
||||
row: 0,
|
||||
column: 0
|
||||
};
|
||||
this.selectionLead = this.doc.createAnchor(0, 0);
|
||||
this.selectionAnchor = this.doc.createAnchor(0, 0);
|
||||
|
||||
var _self = this;
|
||||
this.selectionLead.on("change", function(e) {
|
||||
_self._dispatchEvent("changeCursor");
|
||||
if (!_self.$isEmpty)
|
||||
_self._dispatchEvent("changeSelection");
|
||||
if (e.old.row == e.value.row)
|
||||
_self.$updateDesiredColumn();
|
||||
});
|
||||
|
||||
this.selectionAnchor.on("change", function() {
|
||||
if (!_self.$isEmpty)
|
||||
_self._dispatchEvent("changeSelection");
|
||||
});
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
|
@ -57,9 +71,10 @@ var Selection = function(doc) {
|
|||
oop.implement(this, EventEmitter);
|
||||
|
||||
this.isEmpty = function() {
|
||||
return (!this.selectionAnchor ||
|
||||
(this.selectionAnchor.row == this.selectionLead.row &&
|
||||
this.selectionAnchor.column == this.selectionLead.column));
|
||||
return (this.$isEmpty || (
|
||||
this.selectionAnchor.row == this.selectionLead.row &&
|
||||
this.selectionAnchor.column == this.selectionLead.column
|
||||
));
|
||||
};
|
||||
|
||||
this.isMultiLine = function() {
|
||||
|
|
@ -71,37 +86,31 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.getCursor = function() {
|
||||
return this.selectionLead;
|
||||
return this.selectionLead.getPosition();
|
||||
};
|
||||
|
||||
this.setSelectionAnchor = function(row, column) {
|
||||
var anchor = this.$clipPositionToDocument(row, column);
|
||||
this.selectionAnchor.setPosition(row, column);
|
||||
|
||||
if (!this.selectionAnchor) {
|
||||
this.selectionAnchor = anchor;
|
||||
this._dispatchEvent("changeSelection", {});
|
||||
if (this.$isEmpty) {
|
||||
this.$isEmpty = false;
|
||||
this._dispatchEvent("changeSelection");
|
||||
}
|
||||
else if (this.selectionAnchor.row !== anchor.row || this.selectionAnchor.column !== anchor.column) {
|
||||
this.selectionAnchor = anchor;
|
||||
this._dispatchEvent("changeSelection", {});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.getSelectionAnchor = function() {
|
||||
if (this.selectionAnchor) {
|
||||
return this.$clone(this.selectionAnchor);
|
||||
} else {
|
||||
return this.$clone(this.selectionLead);
|
||||
}
|
||||
if (this.$isEmpty)
|
||||
return this.getSelectionLead()
|
||||
else
|
||||
return this.selectionAnchor.getPosition();
|
||||
};
|
||||
|
||||
this.getSelectionLead = function() {
|
||||
return this.$clone(this.selectionLead);
|
||||
return this.selectionLead.getPosition();
|
||||
};
|
||||
|
||||
this.shiftSelection = function(columns) {
|
||||
if (this.isEmpty()) {
|
||||
if (this.$isEmpty) {
|
||||
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
|
||||
return;
|
||||
};
|
||||
|
|
@ -122,15 +131,18 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.isBackwards = function() {
|
||||
var anchor = this.selectionAnchor || this.selectionLead;
|
||||
var anchor = this.selectionAnchor;
|
||||
var lead = this.selectionLead;
|
||||
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
|
||||
};
|
||||
|
||||
this.getRange = function() {
|
||||
var anchor = this.selectionAnchor || this.selectionLead;
|
||||
var anchor = this.selectionAnchor;
|
||||
var lead = this.selectionLead;
|
||||
|
||||
if (this.isEmpty())
|
||||
return Range.fromPoints(lead, lead);
|
||||
|
||||
if (this.isBackwards()) {
|
||||
return Range.fromPoints(lead, anchor);
|
||||
}
|
||||
|
|
@ -140,55 +152,40 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.clearSelection = function() {
|
||||
if (this.selectionAnchor) {
|
||||
this.selectionAnchor = null;
|
||||
this._dispatchEvent("changeSelection", {});
|
||||
if (!this.$isEmpty) {
|
||||
this.$isEmpty = true;
|
||||
this._dispatchEvent("changeSelection");
|
||||
}
|
||||
};
|
||||
|
||||
this.selectAll = function() {
|
||||
var lastRow = this.doc.getLength() - 1;
|
||||
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
|
||||
|
||||
if (!this.selectionAnchor) {
|
||||
this.selectionAnchor = this.$clone(this.selectionLead);
|
||||
}
|
||||
|
||||
var cursor = {row:0, column:0};
|
||||
// only dispatch change if the cursor actually changed
|
||||
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
|
||||
this.selectionLead = cursor;
|
||||
this._dispatchEvent("changeSelection", {blockScrolling: true});
|
||||
}
|
||||
this.moveCursorTo(0, 0);
|
||||
};
|
||||
|
||||
this.setSelectionRange = function(range, reverse) {
|
||||
if (reverse) {
|
||||
this.setSelectionAnchor(range.end.row, range.end.column);
|
||||
this.selectTo(range.start.row, range.start.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.$updateDesiredColumn();
|
||||
};
|
||||
|
||||
this.$updateDesiredColumn = function() {
|
||||
var cursor = this.getCursor();
|
||||
this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column);
|
||||
};
|
||||
|
||||
this.$moveSelection = function(mover) {
|
||||
var changed = false;
|
||||
var lead = this.selectionLead;
|
||||
if (this.$isEmpty)
|
||||
this.setSelectionAnchor(lead.row, lead.column);
|
||||
|
||||
if (!this.selectionAnchor) {
|
||||
changed = true;
|
||||
this.selectionAnchor = this.$clone(this.selectionLead);
|
||||
}
|
||||
|
||||
var cursor = this.$clone(this.selectionLead);
|
||||
mover.call(this);
|
||||
|
||||
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
this._dispatchEvent("changeSelection", {});
|
||||
};
|
||||
|
||||
this.selectTo = function(row, column) {
|
||||
|
|
@ -244,21 +241,25 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.selectWord = function() {
|
||||
var cursor = this.selectionLead;
|
||||
var column = cursor.column;
|
||||
var range = this.doc.getWordRange(cursor.row, column);
|
||||
var cursor = this.getCursor();
|
||||
var range = this.session.getWordRange(cursor.row, cursor.column);
|
||||
this.setSelectionRange(range);
|
||||
|
||||
/*this.setSelectionAnchor(cursor.row, start);
|
||||
this.$moveSelection(function() {
|
||||
this.moveCursorTo(cursor.row, end);
|
||||
});*/
|
||||
};
|
||||
|
||||
this.selectLine = function() {
|
||||
this.setSelectionAnchor(this.selectionLead.row, 0);
|
||||
var rowStart = this.selectionLead.row;
|
||||
var rowEnd;
|
||||
|
||||
var foldLine = this.session.getFoldLine(rowStart);
|
||||
if (foldLine) {
|
||||
rowStart = foldLine.start.row;
|
||||
rowEnd = foldLine.end.row;
|
||||
} else {
|
||||
rowEnd = rowStart;
|
||||
}
|
||||
this.setSelectionAnchor(rowStart, 0);
|
||||
this.$moveSelection(function() {
|
||||
this.moveCursorTo(this.selectionLead.row + 1, 0);
|
||||
this.moveCursorTo(rowEnd + 1, 0);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -271,18 +272,20 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.moveCursorLeft = function() {
|
||||
if (this.selectionLead.column == 0) {
|
||||
// cursor is a line start
|
||||
if (this.selectionLead.row > 0) {
|
||||
this.moveCursorTo(this.selectionLead.row - 1, this.doc
|
||||
.getLine(this.selectionLead.row - 1).length);
|
||||
var cursor = this.selectionLead.getPosition(),
|
||||
fold;
|
||||
|
||||
if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {
|
||||
this.moveCursorTo(fold.start.row, fold.start.column);
|
||||
} else if (cursor.column == 0) {
|
||||
// cursor is a line (start
|
||||
if (cursor.row > 0) {
|
||||
this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var doc = this.doc;
|
||||
var tabSize = doc.getTabSize();
|
||||
var cursor = this.selectionLead;
|
||||
if (doc.isTabStop(cursor) && doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize)
|
||||
var tabSize = this.session.getTabSize();
|
||||
if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize)
|
||||
this.moveCursorBy(0, -tabSize);
|
||||
else
|
||||
this.moveCursorBy(0, -1);
|
||||
|
|
@ -290,16 +293,19 @@ var Selection = function(doc) {
|
|||
};
|
||||
|
||||
this.moveCursorRight = function() {
|
||||
if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
|
||||
var cursor = this.selectionLead.getPosition(),
|
||||
fold;
|
||||
if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
|
||||
this.moveCursorTo(fold.end.row, fold.end.column);
|
||||
} else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
|
||||
if (this.selectionLead.row < this.doc.getLength() - 1) {
|
||||
this.moveCursorTo(this.selectionLead.row + 1, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var doc = this.doc;
|
||||
var tabSize = doc.getTabSize();
|
||||
var tabSize = this.session.getTabSize();
|
||||
var cursor = this.selectionLead;
|
||||
if (doc.isTabStop(cursor) && doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize)
|
||||
if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize)
|
||||
this.moveCursorBy(0, tabSize);
|
||||
else
|
||||
this.moveCursorBy(0, 1);
|
||||
|
|
@ -309,19 +315,39 @@ var Selection = function(doc) {
|
|||
this.moveCursorLineStart = function() {
|
||||
var row = this.selectionLead.row;
|
||||
var column = this.selectionLead.column;
|
||||
var beforeCursor = this.doc.getLine(row).slice(0, column);
|
||||
var screenRow = this.session.documentToScreenRow(row, column);
|
||||
|
||||
// Determ the doc-position of the first character at the screen line.
|
||||
var firstColumnPosition =
|
||||
this.session.screenToDocumentPosition(screenRow, 0);
|
||||
|
||||
// Determ the string "before" the cursor.
|
||||
var beforeCursor = this.session.getDisplayLine(
|
||||
row, column,
|
||||
firstColumnPosition.row, firstColumnPosition.column);
|
||||
|
||||
//
|
||||
var leadingSpace = beforeCursor.match(/^\s*/);
|
||||
if (leadingSpace[0].length == 0)
|
||||
this.moveCursorTo(row, this.doc.getLine(row).match(/^\s*/)[0].length);
|
||||
else if (leadingSpace[0].length >= column)
|
||||
this.moveCursorTo(row, 0);
|
||||
else
|
||||
this.moveCursorTo(row, leadingSpace[0].length);
|
||||
if (leadingSpace[0].length == 0
|
||||
|| leadingSpace[0].length >= column - firstColumnPosition.column)
|
||||
{
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row, firstColumnPosition.column);
|
||||
} else {
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row,
|
||||
firstColumnPosition.column + leadingSpace[0].length);
|
||||
}
|
||||
};
|
||||
|
||||
this.moveCursorLineEnd = function() {
|
||||
this.moveCursorTo(this.selectionLead.row,
|
||||
this.doc.getLine(this.selectionLead.row).length);
|
||||
var lead = this.selectionLead;
|
||||
var lastRowColumnPosition =
|
||||
this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
|
||||
this.moveCursorTo(
|
||||
lastRowColumnPosition.row,
|
||||
lastRowColumnPosition.column
|
||||
);
|
||||
};
|
||||
|
||||
this.moveCursorFileEnd = function() {
|
||||
|
|
@ -341,20 +367,24 @@ var Selection = function(doc) {
|
|||
var rightOfCursor = line.substring(column);
|
||||
|
||||
var match;
|
||||
this.doc.nonTokenRe.lastIndex = 0;
|
||||
this.doc.tokenRe.lastIndex = 0;
|
||||
this.session.nonTokenRe.lastIndex = 0;
|
||||
this.session.tokenRe.lastIndex = 0;
|
||||
|
||||
if (column == line.length) {
|
||||
var fold;
|
||||
if (fold = this.session.getFoldAt(row, column, 1)) {
|
||||
this.moveCursorTo(fold.end.row, fold.end.column);
|
||||
return;
|
||||
} else if (column == line.length) {
|
||||
this.moveCursorRight();
|
||||
return;
|
||||
}
|
||||
else if (match = this.doc.nonTokenRe.exec(rightOfCursor)) {
|
||||
column += this.doc.nonTokenRe.lastIndex;
|
||||
this.doc.nonTokenRe.lastIndex = 0;
|
||||
else if (match = this.session.nonTokenRe.exec(rightOfCursor)) {
|
||||
column += this.session.nonTokenRe.lastIndex;
|
||||
this.session.nonTokenRe.lastIndex = 0;
|
||||
}
|
||||
else if (match = this.doc.tokenRe.exec(rightOfCursor)) {
|
||||
column += this.doc.tokenRe.lastIndex;
|
||||
this.doc.tokenRe.lastIndex = 0;
|
||||
else if (match = this.session.tokenRe.exec(rightOfCursor)) {
|
||||
column += this.session.tokenRe.lastIndex;
|
||||
this.session.tokenRe.lastIndex = 0;
|
||||
}
|
||||
|
||||
this.moveCursorTo(row, column);
|
||||
|
|
@ -363,76 +393,72 @@ var Selection = function(doc) {
|
|||
this.moveCursorWordLeft = function() {
|
||||
var row = this.selectionLead.row;
|
||||
var column = this.selectionLead.column;
|
||||
var line = this.doc.getLine(row);
|
||||
var leftOfCursor = lang.stringReverse(line.substring(0, column));
|
||||
|
||||
var match;
|
||||
this.doc.nonTokenRe.lastIndex = 0;
|
||||
this.doc.tokenRe.lastIndex = 0;
|
||||
var fold;
|
||||
if (fold = this.session.getFoldAt(row, column, -1)) {
|
||||
this.moveCursorTo(fold.start.row, fold.start.column);
|
||||
return;
|
||||
}
|
||||
|
||||
if (column == 0) {
|
||||
this.moveCursorLeft();
|
||||
return;
|
||||
}
|
||||
else if (match = this.doc.nonTokenRe.exec(leftOfCursor)) {
|
||||
column -= this.doc.nonTokenRe.lastIndex;
|
||||
this.doc.nonTokenRe.lastIndex = 0;
|
||||
|
||||
var str = this.session.getFoldStringAt(row, column, -1);
|
||||
if (str == null) {
|
||||
str = this.doc.getLine(row).substring(0, column)
|
||||
}
|
||||
else if (match = this.doc.tokenRe.exec(leftOfCursor)) {
|
||||
column -= this.doc.tokenRe.lastIndex;
|
||||
this.doc.tokenRe.lastIndex = 0;
|
||||
var leftOfCursor = lang.stringReverse(str);
|
||||
|
||||
var match;
|
||||
this.session.nonTokenRe.lastIndex = 0;
|
||||
this.session.tokenRe.lastIndex = 0;
|
||||
|
||||
if (match = this.session.nonTokenRe.exec(leftOfCursor)) {
|
||||
column -= this.session.nonTokenRe.lastIndex;
|
||||
this.session.nonTokenRe.lastIndex = 0;
|
||||
}
|
||||
else if (match = this.session.tokenRe.exec(leftOfCursor)) {
|
||||
column -= this.session.tokenRe.lastIndex;
|
||||
this.session.tokenRe.lastIndex = 0;
|
||||
}
|
||||
|
||||
this.moveCursorTo(row, column);
|
||||
};
|
||||
|
||||
this.moveCursorBy = function(rows, chars) {
|
||||
this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars);
|
||||
};
|
||||
var screenPos = this.session.documentToScreenPosition(
|
||||
this.selectionLead.row,
|
||||
this.selectionLead.column
|
||||
);
|
||||
var screenCol = (chars == 0 && this.$desiredColumn) || screenPos.column;
|
||||
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
|
||||
|
||||
this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
|
||||
};
|
||||
|
||||
this.moveCursorToPosition = function(position) {
|
||||
this.moveCursorTo(position.row, position.column);
|
||||
};
|
||||
|
||||
this.moveCursorTo = function(row, column) {
|
||||
var cursor = this.$clipPositionToDocument(row, column);
|
||||
|
||||
// only dispatch change if the cursor actually changed
|
||||
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
|
||||
this.selectionLead = cursor;
|
||||
this._dispatchEvent("changeCursor", { data: this.getCursor() });
|
||||
this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) {
|
||||
// Ensure the row/column is not inside of a fold.
|
||||
var fold = this.session.getFoldAt(row, column, 1);
|
||||
if (fold) {
|
||||
row = fold.start.row;
|
||||
column = fold.start.column;
|
||||
}
|
||||
this.selectionLead.setPosition(row, column);
|
||||
if (!preventUpdateDesiredColumn)
|
||||
this.$updateDesiredColumn(this.selectionLead.column);
|
||||
};
|
||||
|
||||
this.moveCursorUp = function() {
|
||||
this.moveCursorBy(-1, 0);
|
||||
};
|
||||
|
||||
this.$clipPositionToDocument = function(row, column) {
|
||||
var pos = {};
|
||||
|
||||
if (row >= this.doc.getLength()) {
|
||||
pos.row = Math.max(0, this.doc.getLength() - 1);
|
||||
pos.column = this.doc.getLine(pos.row).length;
|
||||
}
|
||||
else if (row < 0) {
|
||||
pos.row = 0;
|
||||
pos.column = 0;
|
||||
}
|
||||
else {
|
||||
pos.row = row;
|
||||
pos.column = Math.min(this.doc.getLine(pos.row).length,
|
||||
Math.max(0, column));
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
this.$clone = function(pos) {
|
||||
return {
|
||||
row: pos.row,
|
||||
column: pos.column
|
||||
};
|
||||
this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
|
||||
var pos = this.session.screenToDocumentPosition(row, column);
|
||||
row = pos.row;
|
||||
column = pos.column;
|
||||
this.moveCursorTo(row, column, preventUpdateDesiredColumn);
|
||||
};
|
||||
|
||||
}).call(Selection.prototype);
|
||||
|
|
|
|||
|
|
@ -35,37 +35,41 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("../document").Document,
|
||||
assert = require("./assertions");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
createTextDocument : function(rows, cols) {
|
||||
module.exports = {
|
||||
createSession : 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: 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();
|
||||
var session = this.createSession(200, 10);
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorFileEnd();
|
||||
assert.position(selection.getCursor(), 199, 10);
|
||||
},
|
||||
|
||||
"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();
|
||||
var session = this.createSession(200, 10);
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorFileStart();
|
||||
assert.position(selection.getCursor(), 0, 0);
|
||||
},
|
||||
|
||||
"test: move selection lead to end of file" : function() {
|
||||
var doc = this.createTextDocument(200, 10);
|
||||
var selection = doc.getSelection();
|
||||
var session = this.createSession(200, 10);
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(100, 5);
|
||||
selection.selectFileEnd();
|
||||
|
|
@ -77,8 +81,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: move selection lead to start of file" : function() {
|
||||
var doc = this.createTextDocument(200, 10);
|
||||
var selection = doc.getSelection();
|
||||
var session = this.createSession(200, 10);
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(100, 5);
|
||||
selection.selectFileStart();
|
||||
|
|
@ -90,9 +94,9 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: move cursor word right" : function() {
|
||||
var doc = new Document( ["ab",
|
||||
var session = new EditSession( ["ab",
|
||||
" Juhu Kinners (abc, 12)", " cde"].join("\n"));
|
||||
var selection = doc.getSelection();
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorDown();
|
||||
assert.position(selection.getCursor(), 1, 0);
|
||||
|
|
@ -130,8 +134,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word right if cursor in word" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 2);
|
||||
selection.moveCursorWordRight();
|
||||
|
|
@ -140,9 +144,9 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: moveCursor word left" : function() {
|
||||
var doc = new Document( ["ab",
|
||||
var session = new EditSession( ["ab",
|
||||
" Juhu Kinners (abc, 12)", " cde"].join("\n"));
|
||||
var selection = doc.getSelection();
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorDown();
|
||||
selection.moveCursorLineEnd();
|
||||
|
|
@ -181,8 +185,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word left if cursor in word" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 8);
|
||||
|
||||
|
|
@ -191,8 +195,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word right and select" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 0);
|
||||
selection.selectWordRight();
|
||||
|
|
@ -204,8 +208,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word left and select" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 3);
|
||||
selection.selectWordLeft();
|
||||
|
|
@ -217,8 +221,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word with cursor in word should select the word" : function() {
|
||||
var doc = new Document("Juhu Kinners 123");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners 123");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 8);
|
||||
selection.selectWord();
|
||||
|
|
@ -229,8 +233,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"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();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 4);
|
||||
selection.selectWord();
|
||||
|
|
@ -248,8 +252,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: select word with cursor in white space should select white space" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 5);
|
||||
selection.selectWord();
|
||||
|
|
@ -260,8 +264,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: moving cursor should fire a 'changeCursor' event" : function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 5);
|
||||
|
||||
|
|
@ -275,8 +279,8 @@ var Test = {
|
|||
},
|
||||
|
||||
"test: calling setCursor with the same position should not fire an event": function() {
|
||||
var doc = new Document("Juhu Kinners");
|
||||
var selection = doc.getSelection();
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 5);
|
||||
|
||||
|
|
@ -287,13 +291,47 @@ var Test = {
|
|||
|
||||
selection.moveCursorTo(0, 5);
|
||||
assert.notOk(called);
|
||||
},
|
||||
|
||||
"test: moveWordLeft should move past || and [": function() {
|
||||
var session = new EditSession("||foo[");
|
||||
var selection = session.getSelection();
|
||||
|
||||
// Move behind ||
|
||||
selection.moveCursorWordRight();
|
||||
assert.position(selection.getCursor(), 0, 2);
|
||||
|
||||
// Move beind foo
|
||||
selection.moveCursorWordRight();
|
||||
assert.position(selection.getCursor(), 0, 5);
|
||||
|
||||
// Move behind [
|
||||
selection.moveCursorWordRight();
|
||||
assert.position(selection.getCursor(), 0, 6);
|
||||
},
|
||||
|
||||
"test: moveWordRight should move past || and [": function() {
|
||||
var session = new EditSession("||foo[");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 6);
|
||||
|
||||
// Move behind [
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 5);
|
||||
|
||||
// Move beind foo
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 2);
|
||||
|
||||
// Move behind ||
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
97
lib/ace/settings/default-settings.js
Normal file
97
lib/ace/settings/default-settings.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** 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):
|
||||
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
||||
*
|
||||
* 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 types = require('pilot/types')
|
||||
var SelectionType = require('pilot/types/basic').SelectionType
|
||||
|
||||
var env
|
||||
|
||||
var settingTypes = {
|
||||
selectionStyle: new SelectionType({
|
||||
data: [ 'line', 'text' ]
|
||||
})
|
||||
}
|
||||
|
||||
var settings = {
|
||||
printMargin: {
|
||||
description: 'Position of the print margin column.',
|
||||
type: 'number',
|
||||
defaultValue: 80,
|
||||
onChange: function onChange(event) {
|
||||
if (env.editor) env.editor.setPrintMarginColumn(event.value)
|
||||
}
|
||||
},
|
||||
showIvisibles: {
|
||||
description: 'Whether or not to show invisible characters.',
|
||||
type: 'bool',
|
||||
defaultValue: false,
|
||||
onChange: function onChange(event) {
|
||||
if (env.editor) env.editor.setShowInvisibles(event.value)
|
||||
}
|
||||
},
|
||||
highlightActiveLine: {
|
||||
description: 'Whether or not highlight active line.',
|
||||
type: 'bool',
|
||||
defaultValue: true,
|
||||
onChange: function onChange(event) {
|
||||
if (env.editor) env.editor.setHighlightActiveLine(event.value)
|
||||
}
|
||||
},
|
||||
selectionStyle: {
|
||||
description: 'Type of text selection.',
|
||||
type: 'selectionStyle',
|
||||
defaultValue: 'line',
|
||||
onChange: function onChange(event) {
|
||||
if (env.editor) env.editor.setSelectionStyle(event.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.startup = function startup(data, reason) {
|
||||
env = data.env
|
||||
types.registerTypes(settingTypes)
|
||||
data.env.settings.addSettings(settings)
|
||||
}
|
||||
|
||||
exports.shutdown = function shutdown(data, reason) {
|
||||
data.env.settings.removeSettings(settings)
|
||||
}
|
||||
|
||||
})
|
||||
|
|
@ -37,24 +37,5 @@
|
|||
|
||||
require("../../../support/paths");
|
||||
|
||||
var async = require("async");
|
||||
|
||||
async.concat(
|
||||
require("./change_document_test"),
|
||||
require("./document_test"),
|
||||
require("./event_emitter_test"),
|
||||
require("./navigation_test"),
|
||||
require("./range_test"),
|
||||
require("./search_test"),
|
||||
require("./selection_test"),
|
||||
require("./text_edit_test"),
|
||||
require("./mode/css_test"),
|
||||
require("./mode/css_tokenizer_test"),
|
||||
require("./mode/html_test"),
|
||||
require("./mode/html_tokenizer_test"),
|
||||
require("./mode/javascript_test"),
|
||||
require("./mode/javascript_tokenizer_test"),
|
||||
require("./mode/text_test"),
|
||||
require("./mode/xml_test"),
|
||||
require("./mode/xml_tokenizer_test")
|
||||
).exec();
|
||||
var test = require("asyncjs").test;
|
||||
test.walkTestCases(__dirname + "/..").exec()
|
||||
89
lib/ace/test/all_browser.js
Normal file
89
lib/ace/test/all_browser.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
require("pilot/fixoldbrowsers");
|
||||
var AsyncTest = require("asyncjs/test");
|
||||
var async = require("asyncjs");
|
||||
var dom = require("pilot/dom");
|
||||
|
||||
var passed = 0
|
||||
var failed = 0
|
||||
var log = document.getElementById("log")
|
||||
|
||||
var tests = [
|
||||
require("ace/editor_change_document_test"),
|
||||
require("ace/editor_navigation_test"),
|
||||
require("ace/editor_highlight_selected_word_test"),
|
||||
require("ace/editor_text_edit_test"),
|
||||
require("ace/document_test"),
|
||||
require("ace/edit_session_test"),
|
||||
require("ace/test/event_emitter_test"),
|
||||
require("ace/range_test"),
|
||||
require("ace/search_test"),
|
||||
require("ace/selection_test"),
|
||||
require("ace/virtual_renderer_test"),
|
||||
require("ace/anchor_test"),
|
||||
require("ace/mode/css_test"),
|
||||
require("ace/mode/css_tokenizer_test"),
|
||||
require("ace/mode/html_test"),
|
||||
require("ace/mode/html_tokenizer_test"),
|
||||
require("ace/mode/javascript_test"),
|
||||
require("ace/mode/javascript_tokenizer_test"),
|
||||
require("ace/mode/text_test"),
|
||||
require("ace/mode/xml_test"),
|
||||
require("ace/mode/xml_tokenizer_test")
|
||||
]
|
||||
|
||||
async.list(tests)
|
||||
.expand(function(test) {
|
||||
return AsyncTest.testcase(test)
|
||||
}, AsyncTest.TestGenerator)
|
||||
.run()
|
||||
.each(function(test, next) {
|
||||
var node = document.createElement("div");
|
||||
node.className = test.passed ? "passed" : "failed";
|
||||
|
||||
var name = test.name
|
||||
if (test.suiteName)
|
||||
name = test.suiteName + ": " + test.name
|
||||
|
||||
var msg = "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL")
|
||||
if (!test.passed) {
|
||||
if (test.err.stack)
|
||||
var err = test.err.stack
|
||||
else
|
||||
var err = test.err
|
||||
|
||||
console.error(msg);
|
||||
console.error(err);
|
||||
msg += "<pre class='error'>" + err + "</pre>";
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
|
||||
node.innerHTML = msg;
|
||||
log.appendChild(node);
|
||||
|
||||
next()
|
||||
})
|
||||
.each(function(test) {
|
||||
if (test.passed)
|
||||
passed += 1
|
||||
else
|
||||
failed += 1
|
||||
})
|
||||
.end(function() {
|
||||
log.innerHTML += [
|
||||
"<div class='summary'>",
|
||||
"<br>",
|
||||
"Summary: <br>",
|
||||
"<br>",
|
||||
"Total number of tests: " + (passed + failed) + "<br>",
|
||||
(passed ? "Passed tests: " + passed + "<br>" : ""),
|
||||
(failed ? "Failed tests: " + failed + "<br>" : "")
|
||||
].join("")
|
||||
console.log("Total number of tests: " + (passed + failed));
|
||||
console.log("Passed tests: " + passed);
|
||||
console.log("Failed tests: " + failed);
|
||||
})
|
||||
|
||||
});
|
||||
306
lib/ace/test/asyncjs/assert.js
Normal file
306
lib/ace/test/asyncjs/assert.js
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
||||
//
|
||||
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
||||
//
|
||||
// Originally from narwhal.js (http://narwhaljs.org)
|
||||
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the 'Software'), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// UTILITY
|
||||
var oop = require('pilot/oop');
|
||||
var pSlice = Array.prototype.slice;
|
||||
|
||||
// 1. The assert module provides functions that throw
|
||||
// AssertionError's when particular conditions are not met. The
|
||||
// assert module must conform to the following interface.
|
||||
|
||||
var assert = exports;
|
||||
|
||||
// 2. The AssertionError is defined in assert.
|
||||
// new assert.AssertionError({ message: message,
|
||||
// actual: actual,
|
||||
// expected: expected })
|
||||
|
||||
assert.AssertionError = function AssertionError(options) {
|
||||
this.name = 'AssertionError';
|
||||
this.message = options.message;
|
||||
this.actual = options.actual;
|
||||
this.expected = options.expected;
|
||||
this.operator = options.operator;
|
||||
var stackStartFunction = options.stackStartFunction || fail;
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, stackStartFunction);
|
||||
}
|
||||
};
|
||||
oop.inherits(assert.AssertionError, Error);
|
||||
|
||||
assert.AssertionError.prototype.toString = function() {
|
||||
if (this.message) {
|
||||
return [this.name + ':', this.message].join(' ');
|
||||
} else {
|
||||
return [this.name + ':',
|
||||
JSON.stringify(this.expected),
|
||||
this.operator,
|
||||
JSON.stringify(this.actual)].join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
// assert.AssertionError instanceof Error
|
||||
|
||||
assert.AssertionError.__proto__ = Error.prototype;
|
||||
|
||||
// At present only the three keys mentioned above are used and
|
||||
// understood by the spec. Implementations or sub modules can pass
|
||||
// other keys to the AssertionError's constructor - they will be
|
||||
// ignored.
|
||||
|
||||
// 3. All of the following functions must throw an AssertionError
|
||||
// when a corresponding condition is not met, with a message that
|
||||
// may be undefined if not provided. All assertion methods provide
|
||||
// both the actual and expected values to the assertion error for
|
||||
// display purposes.
|
||||
|
||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
||||
throw new assert.AssertionError({
|
||||
message: message,
|
||||
actual: actual,
|
||||
expected: expected,
|
||||
operator: operator,
|
||||
stackStartFunction: stackStartFunction
|
||||
});
|
||||
}
|
||||
|
||||
// EXTENSION! allows for well behaved errors defined elsewhere.
|
||||
assert.fail = fail;
|
||||
|
||||
// 4. Pure assertion tests whether a value is truthy, as determined
|
||||
// by !!guard.
|
||||
// assert.ok(guard, message_opt);
|
||||
// This statement is equivalent to assert.equal(true, guard,
|
||||
// message_opt);. To test strictly for the value true, use
|
||||
// assert.strictEqual(true, guard, message_opt);.
|
||||
|
||||
assert.ok = function ok(value, message) {
|
||||
if (!!!value) fail(value, true, message, '==', assert.ok);
|
||||
};
|
||||
|
||||
// 5. The equality assertion tests shallow, coercive equality with
|
||||
// ==.
|
||||
// assert.equal(actual, expected, message_opt);
|
||||
|
||||
assert.equal = function equal(actual, expected, message) {
|
||||
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
||||
};
|
||||
|
||||
// 6. The non-equality assertion tests for whether two objects are not equal
|
||||
// with != assert.notEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notEqual = function notEqual(actual, expected, message) {
|
||||
if (actual == expected) {
|
||||
fail(actual, expected, message, '!=', assert.notEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 7. The equivalence assertion tests a deep equality relation.
|
||||
// assert.deepEqual(actual, expected, message_opt);
|
||||
|
||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
||||
if (!_deepEqual(actual, expected)) {
|
||||
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
||||
}
|
||||
};
|
||||
|
||||
function _deepEqual(actual, expected) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
|
||||
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
||||
if (actual.length != expected.length) return false;
|
||||
|
||||
for (var i = 0; i < actual.length; i++) {
|
||||
if (actual[i] !== expected[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// 7.2. If the expected value is a Date object, the actual value is
|
||||
// equivalent if it is also a Date object that refers to the same time.
|
||||
} else if (actual instanceof Date && expected instanceof Date) {
|
||||
return actual.getTime() === expected.getTime();
|
||||
|
||||
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
||||
// equivalence is determined by ==.
|
||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
||||
return actual == expected;
|
||||
|
||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
function isArguments(object) {
|
||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
||||
}
|
||||
|
||||
function objEquiv(a, b) {
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
||||
return false;
|
||||
// an identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) return false;
|
||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
||||
// Converting to array solves the problem.
|
||||
if (isArguments(a)) {
|
||||
if (!isArguments(b)) {
|
||||
return false;
|
||||
}
|
||||
a = pSlice.call(a);
|
||||
b = pSlice.call(b);
|
||||
return _deepEqual(a, b);
|
||||
}
|
||||
try {
|
||||
var ka = Object.keys(a),
|
||||
kb = Object.keys(b),
|
||||
key, i;
|
||||
} catch (e) {//happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length != kb.length)
|
||||
return false;
|
||||
//the same set of keys (although not necessarily the same order),
|
||||
ka.sort();
|
||||
kb.sort();
|
||||
//~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
if (ka[i] != kb[i])
|
||||
return false;
|
||||
}
|
||||
//equivalent values for every corresponding key, and
|
||||
//~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
if (!_deepEqual(a[key], b[key])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 8. The non-equivalence assertion tests for any deep inequality.
|
||||
// assert.notDeepEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
||||
if (_deepEqual(actual, expected)) {
|
||||
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
||||
// assert.strictEqual(actual, expected, message_opt);
|
||||
|
||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
||||
if (actual !== expected) {
|
||||
fail(actual, expected, message, '===', assert.strictEqual);
|
||||
}
|
||||
};
|
||||
|
||||
// 10. The strict non-equality assertion tests for strict inequality, as
|
||||
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
||||
|
||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||
if (actual === expected) {
|
||||
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
||||
}
|
||||
};
|
||||
|
||||
function expectedException(actual, expected) {
|
||||
if (!actual || !expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected instanceof RegExp) {
|
||||
return expected.test(actual);
|
||||
} else if (actual instanceof expected) {
|
||||
return true;
|
||||
} else if (expected.call({}, actual) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function _throws(shouldThrow, block, expected, message) {
|
||||
var actual;
|
||||
|
||||
if (typeof expected === 'string') {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
try {
|
||||
block();
|
||||
} catch (e) {
|
||||
actual = e;
|
||||
}
|
||||
|
||||
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
||||
(message ? ' ' + message : '.');
|
||||
|
||||
if (shouldThrow && !actual) {
|
||||
fail('Missing expected exception' + message);
|
||||
}
|
||||
|
||||
if (!shouldThrow && expectedException(actual, expected)) {
|
||||
fail('Got unwanted exception' + message);
|
||||
}
|
||||
|
||||
if ((shouldThrow && actual && expected &&
|
||||
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
||||
throw actual;
|
||||
}
|
||||
}
|
||||
|
||||
// 11. Expected to throw an error:
|
||||
// assert.throws(block, Error_opt, message_opt);
|
||||
|
||||
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
||||
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
||||
};
|
||||
|
||||
// EXTENSION! This is annoying to write outside this module.
|
||||
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
||||
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
||||
};
|
||||
|
||||
assert.ifError = function(err) { if (err) {throw err;}};
|
||||
|
||||
});
|
||||
529
lib/ace/test/asyncjs/async.js
Normal file
529
lib/ace/test/asyncjs/async.js
Normal file
|
|
@ -0,0 +1,529 @@
|
|||
/*!
|
||||
* async.js
|
||||
* Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var STOP = exports.STOP = {}
|
||||
|
||||
exports.Generator = function(source) {
|
||||
if (typeof source == "function")
|
||||
this.source = {
|
||||
next: source
|
||||
}
|
||||
else
|
||||
this.source = source
|
||||
}
|
||||
|
||||
;(function() {
|
||||
this.next = function(callback) {
|
||||
this.source.next(callback)
|
||||
}
|
||||
|
||||
this.map = function(mapper) {
|
||||
if (!mapper)
|
||||
return this
|
||||
|
||||
mapper = makeAsync(1, mapper)
|
||||
|
||||
var source = this.source
|
||||
this.next = function(callback) {
|
||||
source.next(function(err, value) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else {
|
||||
mapper(value, function(err, value) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else
|
||||
callback(null, value)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.filter = function(filter) {
|
||||
if (!filter)
|
||||
return this
|
||||
|
||||
filter = makeAsync(1, filter)
|
||||
|
||||
var source = this.source
|
||||
this.next = function(callback) {
|
||||
source.next(function handler(err, value) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else {
|
||||
filter(value, function(err, takeIt) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else if (takeIt)
|
||||
callback(null, value)
|
||||
else
|
||||
source.next(handler)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.slice = function(begin, end) {
|
||||
var count = -1
|
||||
if (!end || end < 0)
|
||||
var end = Infinity
|
||||
|
||||
var source = this.source
|
||||
this.next = function(callback) {
|
||||
source.next(function handler(err, value) {
|
||||
count++
|
||||
if (err)
|
||||
callback(err)
|
||||
else if (count >= begin && count < end)
|
||||
callback(null, value)
|
||||
else if (count >= end)
|
||||
callback(STOP)
|
||||
else
|
||||
source.next(handler)
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.reduce = function(reduce, initialValue) {
|
||||
reduce = makeAsync(3, reduce)
|
||||
|
||||
var index = 0
|
||||
var done = false
|
||||
var previousValue = initialValue
|
||||
|
||||
var source = this.source
|
||||
this.next = function(callback) {
|
||||
if (done)
|
||||
return callback(STOP)
|
||||
|
||||
if (initialValue === undefined) {
|
||||
source.next(function(err, currentValue) {
|
||||
if (err)
|
||||
return callback(err, previousValue)
|
||||
|
||||
previousValue = currentValue
|
||||
reduceAll()
|
||||
})
|
||||
}
|
||||
else
|
||||
reduceAll()
|
||||
|
||||
function reduceAll() {
|
||||
source.next(function handler(err, currentValue) {
|
||||
if (err) {
|
||||
done = true
|
||||
if (err == STOP)
|
||||
return callback(null, previousValue)
|
||||
else
|
||||
return(err)
|
||||
}
|
||||
reduce(previousValue, currentValue, index++, function(err, value) {
|
||||
previousValue = value
|
||||
source.next(handler)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.forEach =
|
||||
this.each = function(fn) {
|
||||
fn = makeAsync(1, fn)
|
||||
|
||||
var source = this.source
|
||||
this.next = function(callback) {
|
||||
source.next(function handler(err, value) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else {
|
||||
fn(value, function(err) {
|
||||
callback(err, value)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.some = function(condition) {
|
||||
condition = makeAsync(1, condition)
|
||||
|
||||
var source = this.source
|
||||
var done = false
|
||||
this.next = function(callback) {
|
||||
if (done)
|
||||
return callback(STOP)
|
||||
|
||||
source.next(function handler(err, value) {
|
||||
if (err)
|
||||
return callback(err)
|
||||
|
||||
condition(value, function(err, result) {
|
||||
if (err) {
|
||||
done = true
|
||||
if (err == STOP)
|
||||
callback(null, false)
|
||||
else
|
||||
callback(err)
|
||||
}
|
||||
else if (result) {
|
||||
done = true
|
||||
callback(null, true)
|
||||
}
|
||||
else
|
||||
source.next(handler)
|
||||
})
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.every = function(condition) {
|
||||
condition = makeAsync(1, condition)
|
||||
|
||||
var source = this.source
|
||||
var done = false
|
||||
this.next = function(callback) {
|
||||
if (done)
|
||||
return callback(STOP)
|
||||
|
||||
source.next(function handler(err, value) {
|
||||
if (err)
|
||||
return callback(err)
|
||||
|
||||
condition(value, function(err, result) {
|
||||
if (err) {
|
||||
done = true
|
||||
if (err == STOP)
|
||||
callback(null, true)
|
||||
else
|
||||
callback(err)
|
||||
}
|
||||
else if (!result) {
|
||||
done = true
|
||||
callback(null, false)
|
||||
}
|
||||
else
|
||||
source.next(handler)
|
||||
})
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.call = function(context) {
|
||||
var source = this.source
|
||||
return this.map(function(fn, next) {
|
||||
fn = makeAsync(0, fn, context)
|
||||
fn.call(context, function(err, value) {
|
||||
next(err, value)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.concat = function(generator) {
|
||||
var generators = [this]
|
||||
generators.push.apply(generators, arguments)
|
||||
var index = 0
|
||||
var source = generators[index++]
|
||||
|
||||
return new this.constructor(function(callback) {
|
||||
source.next(function handler(err, value) {
|
||||
if (err) {
|
||||
if (err == STOP) {
|
||||
source = generators[index++]
|
||||
if (!source)
|
||||
return callback(STOP)
|
||||
else
|
||||
return source.next(handler)
|
||||
}
|
||||
else
|
||||
return callback(err)
|
||||
}
|
||||
else
|
||||
return callback(null, value)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.zip = function(generator) {
|
||||
var generators = [this]
|
||||
generators.push.apply(generators, arguments)
|
||||
|
||||
return new this.constructor(function(callback) {
|
||||
exports.list(generators)
|
||||
.map(function(gen, next) {
|
||||
gen.next(next)
|
||||
})
|
||||
.toArray(callback)
|
||||
})
|
||||
}
|
||||
|
||||
this.expand = function(inserter, constructor) {
|
||||
if (!inserter)
|
||||
return this
|
||||
|
||||
var inserter = makeAsync(1, inserter)
|
||||
var constructor = constructor || this.constructor
|
||||
var source = this.source;
|
||||
var spliced = null;
|
||||
|
||||
return new constructor(function next(callback) {
|
||||
if (!spliced) {
|
||||
source.next(function(err, value) {
|
||||
if (err)
|
||||
return callback(err)
|
||||
|
||||
inserter(value, function(err, toInsert) {
|
||||
if (err)
|
||||
return callback(err)
|
||||
|
||||
spliced = toInsert
|
||||
next(callback)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
else {
|
||||
spliced.next(function(err, value) {
|
||||
if (err == STOP) {
|
||||
spliced = null
|
||||
return next(callback)
|
||||
}
|
||||
else if (err)
|
||||
return callback(err)
|
||||
|
||||
callback(err, value)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.sort = function(compare) {
|
||||
var self = this
|
||||
var arrGen
|
||||
this.next = function(callback) {
|
||||
if (arrGen)
|
||||
return arrGen.next(callback)
|
||||
|
||||
self.toArray(function(err, arr) {
|
||||
if (err)
|
||||
callback(err)
|
||||
else {
|
||||
arrGen = exports.list(arr.sort(compare))
|
||||
arrGen.next(callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
}
|
||||
|
||||
this.join = function(separator) {
|
||||
return this.$arrayOp(Array.prototype.join, separator !== undefined ? [separator] : null)
|
||||
}
|
||||
|
||||
this.reverse = function() {
|
||||
return this.$arrayOp(Array.prototype.reverse)
|
||||
}
|
||||
|
||||
this.$arrayOp = function(arrayMethod, args) {
|
||||
var self = this
|
||||
var i = 0
|
||||
this.next = function(callback) {
|
||||
if (i++ > 0)
|
||||
return callback(STOP)
|
||||
|
||||
self.toArray(function(err, arr) {
|
||||
if (err)
|
||||
callback(err, "")
|
||||
else {
|
||||
if (args)
|
||||
callback(null, arrayMethod.apply(arr, args))
|
||||
else
|
||||
callback(null, arrayMethod.call(arr))
|
||||
}
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
|
||||
}
|
||||
|
||||
this.end = function(breakOnError, callback) {
|
||||
if (!callback) {
|
||||
callback = arguments[0]
|
||||
breakOnError = true
|
||||
}
|
||||
|
||||
var source = this.source
|
||||
var last
|
||||
var lastError
|
||||
source.next(function handler(err, value) {
|
||||
if (err) {
|
||||
if (err == STOP)
|
||||
callback && callback(lastError, last)
|
||||
else if (!breakOnError) {
|
||||
lastError = err
|
||||
source.next(handler)
|
||||
}
|
||||
else
|
||||
callback && callback(err, value)
|
||||
}
|
||||
else {
|
||||
last = value
|
||||
source.next(handler)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.toArray = function(breakOnError, callback) {
|
||||
if (!callback) {
|
||||
callback = arguments[0]
|
||||
breakOnError = true
|
||||
}
|
||||
|
||||
var values = []
|
||||
var errors = []
|
||||
var source = this.source
|
||||
|
||||
source.next(function handler(err, value) {
|
||||
if (err) {
|
||||
if (err == STOP) {
|
||||
if (breakOnError)
|
||||
return callback(null, values)
|
||||
else {
|
||||
errors.length = values.length
|
||||
return callback(errors, values)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (breakOnError)
|
||||
return callback(err)
|
||||
else
|
||||
errors[values.length] = err
|
||||
}
|
||||
}
|
||||
|
||||
values.push(value)
|
||||
source.next(handler)
|
||||
})
|
||||
}
|
||||
|
||||
}).call(exports.Generator.prototype)
|
||||
|
||||
var makeAsync = exports.makeAsync = function(args, fn, context) {
|
||||
if (fn.length > args)
|
||||
return fn
|
||||
else {
|
||||
return function() {
|
||||
var value
|
||||
var next = arguments[args]
|
||||
try {
|
||||
value = fn.apply(context || this, arguments)
|
||||
} catch(e) {
|
||||
return next(e)
|
||||
}
|
||||
next(null, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.list = function(arr, construct) {
|
||||
var construct = construct || exports.Generator
|
||||
var i = 0
|
||||
var len = arr.length
|
||||
|
||||
return new construct(function(callback) {
|
||||
if (i < len)
|
||||
callback(null, arr[i++])
|
||||
else
|
||||
callback(STOP)
|
||||
})
|
||||
}
|
||||
|
||||
exports.values = function(map, construct) {
|
||||
var values = []
|
||||
for (var key in map)
|
||||
values.push(map[key])
|
||||
|
||||
return exports.list(values, construct)
|
||||
}
|
||||
|
||||
exports.keys = function(map, construct) {
|
||||
var keys = []
|
||||
for (var key in map)
|
||||
keys.push(key)
|
||||
|
||||
return exports.list(keys, construct)
|
||||
}
|
||||
|
||||
/**
|
||||
* range([start,] stop[, step]) -> generator of integers
|
||||
*
|
||||
* Return a generator containing an arithmetic progression of integers.
|
||||
* range(i, j) returns [i, i+1, i+2, ..., j-1] start (!) defaults to 0.
|
||||
* When step is given, it specifies the increment (or decrement).
|
||||
*/
|
||||
exports.range = function(start, stop, step, construct) {
|
||||
var construct = construct || exports.Generator
|
||||
start = start || 0
|
||||
step = step || 1
|
||||
|
||||
if (stop === undefined || stop === null)
|
||||
stop = step > 0 ? Infinity : -Infinity
|
||||
|
||||
var value = start
|
||||
|
||||
return new construct(function(callback) {
|
||||
if (step > 0 && value >= stop || step < 0 && value <= stop)
|
||||
callback(STOP)
|
||||
else {
|
||||
var current = value
|
||||
value += step
|
||||
callback(null, current)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.concat = function(first, varargs) {
|
||||
if (arguments.length > 1)
|
||||
return first.concat.apply(first, Array.prototype.slice.call(arguments, 1))
|
||||
else
|
||||
return first
|
||||
}
|
||||
|
||||
exports.zip = function(first, varargs) {
|
||||
if (arguments.length > 1)
|
||||
return first.zip.apply(first, Array.prototype.slice.call(arguments, 1))
|
||||
else
|
||||
return first.map(function(item, next) {
|
||||
next(null, [item])
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
exports.plugin = function(members, constructors) {
|
||||
if (members) {
|
||||
for (var key in members) {
|
||||
exports.Generator.prototype[key] = members[key]
|
||||
}
|
||||
}
|
||||
|
||||
if (constructors) {
|
||||
for (var key in constructors) {
|
||||
exports[key] = constructors[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
12
lib/ace/test/asyncjs/index.js
Normal file
12
lib/ace/test/asyncjs/index.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*!
|
||||
* async.js
|
||||
* Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
module.exports = require("./async")
|
||||
require("./utils")
|
||||
|
||||
})
|
||||
195
lib/ace/test/asyncjs/test.js
Normal file
195
lib/ace/test/asyncjs/test.js
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*!
|
||||
* async.js
|
||||
* Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop")
|
||||
var async = require("asyncjs/async")
|
||||
require("asyncjs/utils")
|
||||
|
||||
exports.TestGenerator = function(source) {
|
||||
async.Generator.call(this, source)
|
||||
}
|
||||
|
||||
oop.inherits(exports.TestGenerator, async.Generator)
|
||||
|
||||
;(function() {
|
||||
|
||||
this.exec = function() {
|
||||
this.run().report().summary(function(err, passed) {
|
||||
console.log("DONE")
|
||||
})
|
||||
}
|
||||
|
||||
this.run = function() {
|
||||
return this.setupTest()
|
||||
.each(function(test, next) {
|
||||
if (test.setUpSuite)
|
||||
test.setUpSuite(next)
|
||||
else
|
||||
next()
|
||||
})
|
||||
.each(function(test, next) {
|
||||
test.test(function(err, passed) {
|
||||
test.err = err
|
||||
test.passed = passed
|
||||
next()
|
||||
})
|
||||
})
|
||||
.each(function(test, next) {
|
||||
if (test.tearDownSuite)
|
||||
test.tearDownSuite(next)
|
||||
else
|
||||
next()
|
||||
})
|
||||
}
|
||||
|
||||
this.report = function() {
|
||||
return this.each(function(test, next) {
|
||||
var color = test.passed ? "\x1b[32m" : "\x1b[31m"
|
||||
var name = test.name
|
||||
if (test.suiteName)
|
||||
name = test.suiteName + ": " + test.name
|
||||
console.log(color + "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL") + "\x1b[0m")
|
||||
if (!test.passed)
|
||||
if (test.err.stack)
|
||||
console.log(test.err.stack)
|
||||
else
|
||||
console.log(test.err)
|
||||
|
||||
next()
|
||||
})
|
||||
}
|
||||
|
||||
this.summary = function(callback) {
|
||||
var passed = 0
|
||||
var failed = 0
|
||||
|
||||
this.each(function(test) {
|
||||
if (test.passed)
|
||||
passed += 1
|
||||
else
|
||||
failed += 1
|
||||
}).end(function() {
|
||||
console.log("")
|
||||
console.log("Summary:")
|
||||
console.log("")
|
||||
console.log( "Total number of tests: " + (passed + failed))
|
||||
passed && console.log("\x1b[32mPassed tests: " + passed + "\x1b[0m")
|
||||
failed && console.log("\x1b[31mFailed tests: " + failed + "\x1b[0m")
|
||||
console.log("")
|
||||
callback(null, failed == 0)
|
||||
})
|
||||
}
|
||||
|
||||
this.setupTest = function() {
|
||||
return this.each(function(test, next) {
|
||||
var empty = function(next) { next() }
|
||||
var context = test.context || this
|
||||
|
||||
if (test.setUp)
|
||||
var setUp = async.makeAsync(0, test.setUp, context)
|
||||
else
|
||||
setUp = empty
|
||||
|
||||
tearDownCalled = false
|
||||
if (test.tearDown)
|
||||
var tearDownInner = async.makeAsync(0, test.tearDown, context)
|
||||
else
|
||||
tearDownInner = empty
|
||||
|
||||
function tearDown(next) {
|
||||
tearDownCalled = true
|
||||
tearDownInner.call(test.context, next)
|
||||
}
|
||||
|
||||
var testFn = async.makeAsync(0, test.fn, context)
|
||||
|
||||
test.test = function(callback) {
|
||||
var called
|
||||
function errorListener(e) {
|
||||
if (called)
|
||||
return
|
||||
called = true
|
||||
//process.removeListener('uncaughtException', errorListener)
|
||||
if (!tearDownCalled) {
|
||||
async.list([tearDown])
|
||||
.call()
|
||||
.timeout(test.timeout)
|
||||
.end(function() {
|
||||
callback(e, false)
|
||||
}) }
|
||||
else
|
||||
callback(e, false)
|
||||
}
|
||||
//process.addListener('uncaughtException', errorListener)
|
||||
|
||||
async.list([setUp, testFn, tearDown])
|
||||
.delay(0)
|
||||
.call(context)
|
||||
.timeout(test.timeout)
|
||||
.toArray(false, function(errors, values) {
|
||||
if (called)
|
||||
return
|
||||
called = true
|
||||
var err = errors[1]
|
||||
//process.removeListener('uncaughtException', errorListener)
|
||||
callback(err, !err)
|
||||
})
|
||||
}
|
||||
|
||||
next()
|
||||
})
|
||||
}
|
||||
|
||||
}).call(exports.TestGenerator.prototype)
|
||||
|
||||
exports.testcase = function(testcase, suiteName, timeout) {
|
||||
var methods = []
|
||||
for (var method in testcase)
|
||||
methods.push(method)
|
||||
|
||||
var setUp = testcase.setUp || null
|
||||
var tearDown = testcase.tearDown || null
|
||||
|
||||
var single
|
||||
methods.forEach(function(name) {
|
||||
if (name.charAt(0) == '>')
|
||||
single = name
|
||||
})
|
||||
if (single)
|
||||
methods = [single]
|
||||
|
||||
var testNames = methods.filter(function(method) {
|
||||
return method.match(/^>?test/) && typeof(testcase[method]) == "function"
|
||||
})
|
||||
var count = testNames.length
|
||||
var i=1
|
||||
tests = testNames.map(function(name) {
|
||||
return {
|
||||
suiteName: suiteName || testcase.name || "",
|
||||
name: name,
|
||||
setUp: setUp,
|
||||
tearDown: tearDown,
|
||||
context: testcase,
|
||||
timeout: timeout === undefined ? 3000 : timeout,
|
||||
fn: testcase[name],
|
||||
count: count,
|
||||
index: i++
|
||||
}
|
||||
})
|
||||
|
||||
if (testcase.setUpSuite) {
|
||||
tests[0].setUpSuite = async.makeAsync(0, testcase.setUpSuite, testcase)
|
||||
}
|
||||
if (testcase.tearDownSuite) {
|
||||
tests[tests.length-1].tearDownSuite = async.makeAsync(0, testcase.tearDownSuite, testcase)
|
||||
}
|
||||
|
||||
return async.list(tests, exports.TestGenerator)
|
||||
}
|
||||
|
||||
})
|
||||
63
lib/ace/test/asyncjs/utils.js
Normal file
63
lib/ace/test/asyncjs/utils.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*!
|
||||
* async.js
|
||||
* Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var async = require("asyncjs/async")
|
||||
|
||||
async.plugin({
|
||||
delay: function(delay) {
|
||||
return this.each(function(item, next) {
|
||||
setTimeout(next, delay)
|
||||
})
|
||||
},
|
||||
|
||||
timeout: function(timeout) {
|
||||
timeout = timeout || 0
|
||||
var source = this.source
|
||||
|
||||
this.next = function(callback) {
|
||||
var called
|
||||
var id = setTimeout(function() {
|
||||
called = true
|
||||
callback("Source did not respond after " + timeout + "ms!")
|
||||
}, timeout)
|
||||
|
||||
source.next(function(err, value) {
|
||||
if (called)
|
||||
return
|
||||
|
||||
called = true
|
||||
clearTimeout(id)
|
||||
|
||||
callback(err, value)
|
||||
})
|
||||
}
|
||||
return new this.constructor(this)
|
||||
},
|
||||
|
||||
get: function(key) {
|
||||
return this.map(function(value, next) {
|
||||
next(null, value[key])
|
||||
})
|
||||
},
|
||||
|
||||
inspect: function() {
|
||||
return this.each(function(item, next) {
|
||||
console.log(JSON.stringify(item))
|
||||
next()
|
||||
})
|
||||
},
|
||||
|
||||
print: function() {
|
||||
return this.each(function(item, next) {
|
||||
console.log(item)
|
||||
next()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
|
@ -1,295 +0,0 @@
|
|||
/* ***** 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 <fabian AT ajax DOT org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("../document").Document,
|
||||
UndoManager = require("../undomanager").UndoManager,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
Range = require("../range").Range,
|
||||
assert = require("./assertions"),
|
||||
async = require("async");
|
||||
|
||||
var Test = {
|
||||
|
||||
"test: find matching opening bracket" : function() {
|
||||
var doc = new Document(["(()(", "())))"]);
|
||||
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 3}), 0, 1);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 2}), 1, 0);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 3);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 4}), 0, 0);
|
||||
assert.equal(doc.findMatchingBracket({row: 1, column: 5}), null);
|
||||
},
|
||||
|
||||
"test: find matching closing bracket" : function() {
|
||||
var doc = new Document(["(()(", "())))"]);
|
||||
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 1}), 1, 1);
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 4}), 1, 2);
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 2}), 0, 2);
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 3);
|
||||
assert.equal(doc.findMatchingBracket({row: 0, column: 0}), null);
|
||||
},
|
||||
|
||||
"test: match different bracket types" : function() {
|
||||
var doc = new Document(["({[", ")]}"]);
|
||||
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 1}), 1, 0);
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 2}), 1, 2);
|
||||
assert.position(doc.findMatchingBracket({row: 0, column: 3}), 1, 1);
|
||||
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 1}), 0, 0);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 2}), 0, 2);
|
||||
assert.position(doc.findMatchingBracket({row: 1, column: 3}), 0, 1);
|
||||
},
|
||||
|
||||
"test: move lines down" : function() {
|
||||
var doc = new Document(["a1", "a2", "a3", "a4"]);
|
||||
|
||||
doc.moveLinesDown(0, 1);
|
||||
assert.equal(doc.toString(), ["a3", "a1", "a2", "a4"].join("\n"));
|
||||
|
||||
doc.moveLinesDown(1, 2);
|
||||
assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
doc.moveLinesDown(2, 3);
|
||||
assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
doc.moveLinesDown(2, 2);
|
||||
assert.equal(doc.toString(), ["a3", "a4", "a2", "a1"].join("\n"));
|
||||
},
|
||||
|
||||
"test: move lines up" : function() {
|
||||
var doc = new Document(["a1", "a2", "a3", "a4"]);
|
||||
|
||||
doc.moveLinesUp(2, 3);
|
||||
assert.equal(doc.toString(), ["a1", "a3", "a4", "a2"].join("\n"));
|
||||
|
||||
doc.moveLinesUp(1, 2);
|
||||
assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
doc.moveLinesUp(0, 1);
|
||||
assert.equal(doc.toString(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
doc.moveLinesUp(2, 2);
|
||||
assert.equal(doc.toString(), ["a3", "a1", "a4", "a2"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate lines" : function() {
|
||||
var doc = new Document(["1", "2", "3", "4"]);
|
||||
|
||||
doc.duplicateLines(1, 2);
|
||||
assert.equal(doc.toString(), ["1", "2", "3", "2", "3", "4"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate last line" : function() {
|
||||
var doc = new Document(["1", "2", "3"]);
|
||||
|
||||
doc.duplicateLines(2, 2);
|
||||
assert.equal(doc.toString(), ["1", "2", "3", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate first line" : function() {
|
||||
var doc = new Document(["1", "2", "3"]);
|
||||
|
||||
doc.duplicateLines(0, 0);
|
||||
assert.equal(doc.toString(), ["1", "1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: should handle unix style new lines" : function() {
|
||||
var doc = new Document(["1", "2", "3"]);
|
||||
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: should handle windows style new lines" : function() {
|
||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||
|
||||
doc.setNewLineMode("unix");
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: set new line mode to 'windows' should use '\r\n' as new lines": function() {
|
||||
var doc = new Document(["1", "2", "3"].join("\n"));
|
||||
doc.setNewLineMode("windows");
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n"));
|
||||
},
|
||||
|
||||
"test: set new line mode to 'unix' should use '\n' as new lines": function() {
|
||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||
|
||||
doc.setNewLineMode("unix");
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: set new line mode to 'auto' should detect the incoming nl type": function() {
|
||||
var doc = new Document(["1", "2", "3"].join("\n"));
|
||||
|
||||
doc.setNewLineMode("auto");
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\n"));
|
||||
|
||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||
|
||||
doc.setNewLineMode("auto");
|
||||
assert.equal(doc.toString(), ["1", "2", "3"].join("\r\n"));
|
||||
|
||||
doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n"));
|
||||
assert.equal(["4", "5", "6"].join("\n"), doc.toString());
|
||||
},
|
||||
|
||||
"test: convert document to screen coordinates" : function() {
|
||||
var doc = new Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assert.equal(doc.documentToScreenColumn(0, 0), 0);
|
||||
assert.equal(doc.documentToScreenColumn(0, 4), 4);
|
||||
assert.equal(doc.documentToScreenColumn(0, 5), 5);
|
||||
assert.equal(doc.documentToScreenColumn(0, 6), 9);
|
||||
assert.equal(doc.documentToScreenColumn(0, 12), 15);
|
||||
assert.equal(doc.documentToScreenColumn(0, 13), 19);
|
||||
|
||||
doc.setTabSize(2);
|
||||
|
||||
assert.equal(doc.documentToScreenColumn(0, 0), 0);
|
||||
assert.equal(doc.documentToScreenColumn(0, 4), 4);
|
||||
assert.equal(doc.documentToScreenColumn(0, 5), 5);
|
||||
assert.equal(doc.documentToScreenColumn(0, 6), 7);
|
||||
assert.equal(doc.documentToScreenColumn(0, 12), 13);
|
||||
assert.equal(doc.documentToScreenColumn(0, 13), 15);
|
||||
},
|
||||
|
||||
"test: convert document to scrren coordinates with leading tabs": function() {
|
||||
var doc = new Document("\t\t123");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assert.equal(doc.documentToScreenColumn(0, 0), 0);
|
||||
assert.equal(doc.documentToScreenColumn(0, 1), 4);
|
||||
assert.equal(doc.documentToScreenColumn(0, 2), 8);
|
||||
assert.equal(doc.documentToScreenColumn(0, 3), 9);
|
||||
},
|
||||
|
||||
"test: convert screen to document coordinates" : function() {
|
||||
var doc = new Document("01234\t567890\t1234");
|
||||
doc.setTabSize(4);
|
||||
|
||||
assert.equal(doc.screenToDocumentColumn(0, 0), 0);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 4), 4);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 5), 5);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 6), 5);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 7), 5);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 8), 5);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 9), 6);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 15), 12);
|
||||
assert.equal(doc.screenToDocumentColumn(0, 19), 13);
|
||||
},
|
||||
|
||||
"test: insert text in multiple rows": function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
|
||||
var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu 1");
|
||||
assert.equal(inserted.rows, 0);
|
||||
assert.equal(inserted.columns, 6);
|
||||
|
||||
assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: undo insert text in multiple rows": function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
|
||||
var undoManager = new UndoManager();
|
||||
doc.setUndoManager(undoManager);
|
||||
|
||||
doc.multiRowInsert([0, 1, 2], 2, "juhu 1");
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n"));
|
||||
|
||||
undoManager.undo();
|
||||
assert.equal(doc.toString(), ["12", "", "abcd"].join("\n"));
|
||||
|
||||
undoManager.redo();
|
||||
assert.equal(doc.toString(), ["12juhu 1", " juhu 1", "abjuhu 1cd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert new line in multiple rows": function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
|
||||
var inserted = doc.multiRowInsert([0, 1, 2], 2, "\n");
|
||||
assert.equal(inserted.rows, 1);
|
||||
assert.equal(doc.toString(), ["12\n", " \n", "ab\ncd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: insert multi line text in multiple rows": function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
|
||||
var inserted = doc.multiRowInsert([0, 1, 2], 2, "juhu\n12");
|
||||
assert.equal(inserted.rows, 1);
|
||||
assert.equal(doc.toString(), ["12juhu\n12", " juhu\n12", "abjuhu\n12cd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: remove right in multiple rows" : function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
|
||||
doc.multiRowRemove([0, 1, 2], new Range(0, 2, 0, 3));
|
||||
assert.equal(doc.toString(), ["12", "", "abd"].join("\n"));
|
||||
},
|
||||
|
||||
"test: undo remove right in multiple rows" : function() {
|
||||
var doc = new Document(["12", "", "abcd"]);
|
||||
var undoManager = new UndoManager();
|
||||
doc.setUndoManager(undoManager);
|
||||
|
||||
doc.multiRowRemove([0, 1, 2], new Range(0, 1, 0, 3));
|
||||
doc.$informUndoManager.call();
|
||||
assert.equal(doc.toString(), ["1", "", "ad"].join("\n"));
|
||||
|
||||
undoManager.undo();
|
||||
assert.equal(doc.toString(), ["12", "", "abcd"].join("\n"));
|
||||
|
||||
undoManager.redo();
|
||||
assert.equal(doc.toString(), ["1", "", "ad"].join("\n"));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
|
|
@ -35,17 +35,21 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
require("../../../support/paths");
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
EventEmitter = require("pilot/event_emitter").EventEmitter,
|
||||
assert = require("./assertions");
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Emitter = function() {};
|
||||
|
||||
oop.implement(Emitter.prototype, EventEmitter);
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
"test: dispatch event with no data" : function() {
|
||||
var emitter = new Emitter();
|
||||
|
||||
|
|
@ -60,7 +64,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("async/test").testcase(Test)
|
||||
});
|
||||
|
||||
if (module === require.main)
|
||||
module.exports.exec()
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -39,17 +39,14 @@ define(function(require, exports, module) {
|
|||
|
||||
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
|
||||
};
|
||||
|
||||
this.isMockRenderer = true;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -69,29 +66,52 @@ MockRenderer.prototype.getMouseEventTarget = function() {
|
|||
return this.container;
|
||||
};
|
||||
|
||||
MockRenderer.prototype.setDocument = function(doc) {
|
||||
this.doc = doc;
|
||||
MockRenderer.prototype.getTextAreaContainer = function() {
|
||||
return this.container;
|
||||
};
|
||||
|
||||
MockRenderer.prototype.moveTextAreaToCursor = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
||||
MockRenderer.prototype.getSession = function(session) {
|
||||
return this.session;
|
||||
};
|
||||
|
||||
MockRenderer.prototype.setTokenizer = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.updateCursor = function(position) {
|
||||
this.cursor.row = position.row;
|
||||
this.cursor.column = position.column;
|
||||
MockRenderer.prototype.updateCursor = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.scrollToLine = function(line, center) {
|
||||
var lineHeight = { lineHeight: 16 };
|
||||
var row = 0;
|
||||
for (var l = 1; l < line; l++) {
|
||||
row += this.session.getRowHeight(lineHeight, l-1) / lineHeight.lineHeight;
|
||||
}
|
||||
|
||||
if (center) {
|
||||
row -= this.visibleRowCount / 2;
|
||||
}
|
||||
this.scrollToRow(row);
|
||||
};
|
||||
|
||||
MockRenderer.prototype.scrollCursorIntoView = function() {
|
||||
if (this.cursor.row < this.layerConfig.firstVisibleRow) {
|
||||
this.scrollToRow(this.cursor.row);
|
||||
var cursor = this.session.getSelection().getCursor();
|
||||
if (cursor.row < this.layerConfig.firstVisibleRow) {
|
||||
this.scrollToRow(cursor.row);
|
||||
}
|
||||
else if (this.cursor.row > this.layerConfig.lastVisibleRow) {
|
||||
this.scrollToRow(this.cursor.row);
|
||||
else if (cursor.row > this.layerConfig.lastVisibleRow) {
|
||||
this.scrollToRow(cursor.row);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
@ -107,16 +127,22 @@ MockRenderer.prototype.draw = function() {
|
|||
MockRenderer.prototype.updateLines = function(startRow, endRow) {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.addMarker = function() {
|
||||
MockRenderer.prototype.updateBackMarkers = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.updateFrontMarkers = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.setBreakpoints = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.updateFull = function() {
|
||||
MockRenderer.prototype.onResize = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.updateText = function() {
|
||||
MockRenderer.prototype.updateFull = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.updateText = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.showCursor = function() {
|
||||
|
|
@ -125,5 +151,15 @@ MockRenderer.prototype.showCursor = function() {
|
|||
MockRenderer.prototype.visualizeFocus = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.setAnnotations = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.textToScreenCoordinates = function() {
|
||||
return {
|
||||
pageX: 0,
|
||||
pageY: 0
|
||||
}
|
||||
};
|
||||
|
||||
return MockRenderer;
|
||||
});
|
||||
|
|
|
|||
54
lib/ace/test/tests.html
Normal file
54
lib/ace/test/tests.html
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Ace Unit Tests</title>
|
||||
<style type="text/css" media="screen">
|
||||
|
||||
#log .passed {
|
||||
color: green;
|
||||
}
|
||||
|
||||
#log .failed {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#log pre.error {
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="log"></div>
|
||||
|
||||
<script src="../../../demo/require.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script>
|
||||
|
||||
require({
|
||||
paths: {
|
||||
ace: "../lib/ace",
|
||||
cockpit: "../support/cockpit/lib/cockpit",
|
||||
pilot: "../support/pilot/lib/pilot"
|
||||
},
|
||||
packages : [{
|
||||
name: "asyncjs",
|
||||
location: "../lib/ace/test",
|
||||
lib: "asyncjs",
|
||||
main: "index"
|
||||
}, {
|
||||
name: "assert",
|
||||
location: "../lib/ace/test",
|
||||
lib: "asyncjs",
|
||||
main: "assert"
|
||||
}]
|
||||
});
|
||||
|
||||
require(["ace/test/all_browser"], function(tests) {
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -192,4 +192,4 @@ define(function(require, exports, module) {
|
|||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-clouds";
|
||||
});
|
||||
});
|
||||
|
|
@ -193,4 +193,4 @@ background-color:#E92E2E;\
|
|||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-clouds-midnight";
|
||||
});
|
||||
});
|
||||
|
|
@ -194,4 +194,4 @@ color:#0088FF;\
|
|||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-cobalt";
|
||||
});
|
||||
});
|
||||
|
|
@ -198,4 +198,4 @@ color:#5A525F;\
|
|||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-dawn";
|
||||
});
|
||||
});
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
.ace-eclipse .ace_editor {
|
||||
border: 2px solid rgb(159, 159, 159);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_editor.ace_focus {
|
||||
border: 2px solid #327fbd;
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_gutter {
|
||||
width: 40px;
|
||||
background: rgb(227, 227, 227);
|
||||
border-right: 1px solid rgb(159, 159, 159);
|
||||
color: rgb(136, 136, 136);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_gutter-layer {
|
||||
right: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_text-layer {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_cursor {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_keyword, .ace-eclipse .ace_line .ace_variable {
|
||||
color: rgb(127, 0, 85);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_constant.ace_buildin {
|
||||
color: rgb(88, 72, 246);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_constant.ace_library {
|
||||
color: rgb(6, 150, 14);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_function {
|
||||
color: rgb(60, 76, 114);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_string {
|
||||
color: rgb(42, 0, 255);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_comment {
|
||||
color: rgb(63, 127, 95);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_comment.ace_doc {
|
||||
color: rgb(63, 95, 191);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_comment.ace_doc.ace_tag {
|
||||
color: rgb(127, 159, 191);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_constant.ace_numeric {
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_tag {
|
||||
color: rgb(63, 127, 127);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_line .ace_xml_pe {
|
||||
color: rgb(104, 104, 91);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_marker-layer .ace_selection {
|
||||
background: rgb(181, 213, 255);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_marker-layer .ace_bracket {
|
||||
margin: -1px 0 0 -1px;
|
||||
border: 1px solid rgb(192, 192, 192);
|
||||
}
|
||||
|
||||
.ace-eclipse .ace_marker-layer .ace_active_line {
|
||||
background: rgb(232, 242, 254);
|
||||
}
|
||||
|
|
@ -38,7 +38,94 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var dom = require("pilot/dom");
|
||||
var cssText = require("text!ace/theme/eclipse.css");
|
||||
|
||||
var cssText = ".ace-eclipse .ace_editor {\
|
||||
border: 2px solid rgb(159, 159, 159);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_editor.ace_focus {\
|
||||
border: 2px solid #327fbd;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_gutter {\
|
||||
width: 50px;\
|
||||
background: rgb(227, 227, 227);\
|
||||
border-right: 1px solid rgb(159, 159, 159); \
|
||||
color: rgb(136, 136, 136);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_gutter-layer {\
|
||||
width: 100%;\
|
||||
text-align: right;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_gutter-layer .ace_gutter-cell {\
|
||||
padding-right: 6px;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_text-layer {\
|
||||
cursor: text;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_cursor {\
|
||||
border-left: 1px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_keyword, .ace-eclipse .ace_line .ace_variable {\
|
||||
color: rgb(127, 0, 85);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_constant.ace_buildin {\
|
||||
color: rgb(88, 72, 246);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_constant.ace_library {\
|
||||
color: rgb(6, 150, 14);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_function {\
|
||||
color: rgb(60, 76, 114);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_string {\
|
||||
color: rgb(42, 0, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_comment {\
|
||||
color: rgb(63, 127, 95);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_comment.ace_doc {\
|
||||
color: rgb(63, 95, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_comment.ace_doc.ace_tag {\
|
||||
color: rgb(127, 159, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_constant.ace_numeric {\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_tag {\
|
||||
color: rgb(63, 127, 127);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_xml_pe {\
|
||||
color: rgb(104, 104, 91);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_marker-layer .ace_selection {\
|
||||
background: rgb(181, 213, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_marker-layer .ace_bracket {\
|
||||
margin: -1px 0 0 -1px;\
|
||||
border: 1px solid rgb(192, 192, 192);\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_marker-layer .ace_active_line {\
|
||||
background: rgb(232, 242, 254);\
|
||||
}";
|
||||
|
||||
// import CSS once
|
||||
dom.importCssString(cssText);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue