Merge branch 'master' of https://github.com/ajaxorg/ace
This commit is contained in:
commit
79281c4fdd
172 changed files with 29483 additions and 9460 deletions
80
lib/ace/ace.js
Normal file
80
lib/ace/ace.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 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) {
|
||||
|
||||
require("pilot/index");
|
||||
require("pilot/fixoldbrowsers");
|
||||
var catalog = require("pilot/plugin_manager").catalog;
|
||||
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;
|
||||
};
|
||||
});
|
||||
|
|
@ -35,15 +35,18 @@
|
|||
*
|
||||
* ***** 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("./assertions");
|
||||
var async = require("asyncjs");
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
|
||||
"test create anchor" : function() {
|
||||
var doc = new Document("juhu");
|
||||
|
|
@ -173,11 +176,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -56,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) {
|
||||
|
|
@ -67,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -144,6 +141,12 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
if (firstRow > 0 && this.lines[firstRow - 1]) {
|
||||
state = this.lines[firstRow - 1].state;
|
||||
doCache = true;
|
||||
} else if (firstRow == 0) {
|
||||
state = "start";
|
||||
doCache = true;
|
||||
} else if (this.lines.length > 0) {
|
||||
// Guess that we haven't changed state.
|
||||
state = this.lines[this.lines.length-1].state;
|
||||
}
|
||||
|
||||
var lines = this.doc.getLines(firstRow, lastRow);
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ canon.addCommand({
|
|||
});
|
||||
canon.addCommand({
|
||||
name: "selecttostart",
|
||||
bindKey: bindKey("Alt-Shift-Up", "Command-Shift-Up"),
|
||||
bindKey: bindKey("Ctrl-Shift-Home|Alt-Shift-Up", "Command-Shift-Up"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectFileStart(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
|
|
@ -182,7 +182,7 @@ canon.addCommand({
|
|||
});
|
||||
canon.addCommand({
|
||||
name: "selecttoend",
|
||||
bindKey: bindKey("Alt-Shift-Down", "Command-Shift-Down"),
|
||||
bindKey: bindKey("Ctrl-Shift-End|Alt-Shift-Down", "Command-Shift-Down"),
|
||||
exec: function(env, args, request) { env.editor.getSelection().selectFileEnd(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
|
|
@ -325,7 +325,7 @@ canon.addCommand({
|
|||
});
|
||||
canon.addCommand({
|
||||
name: "removewordleft",
|
||||
bindKey: bindKey(null, "Alt-Backspace|Ctrl-Alt-Backspace"),
|
||||
bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
|
||||
exec: function(env, args, request) { env.editor.removeWordLeft(); }
|
||||
});
|
||||
canon.addCommand({
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
overflow: hidden;
|
||||
|
||||
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ace_scroller {
|
||||
position: absolute;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ace_content {
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
.ace_layer {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
|
@ -117,12 +117,17 @@
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.ace_cursor.ace_hidden {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.ace_line {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ace_marker-layer {
|
||||
cursor: text;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ace_marker-layer .ace_step {
|
||||
|
|
@ -153,6 +158,10 @@
|
|||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ace_line .ace_fold {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {
|
||||
cursor: move;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ var Document = function(text) {
|
|||
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
|
||||
this.insert({row: 0, column:0}, text);
|
||||
};
|
||||
|
||||
|
||||
this.getValue = function() {
|
||||
return this.getAllLines().join(this.getNewLineCharacter());
|
||||
};
|
||||
|
||||
|
||||
this.createAnchor = function(row, column) {
|
||||
return new Anchor(this, row, column);
|
||||
};
|
||||
|
|
@ -128,7 +128,7 @@ var Document = function(text) {
|
|||
* Get a verbatim copy of the given line as it is in the document
|
||||
*/
|
||||
this.getLine = function(row) {
|
||||
return this.getLines(row, row + 1)[0] || "";
|
||||
return this.$lines[row] || "";
|
||||
};
|
||||
|
||||
this.getLines = function(firstRow, lastRow) {
|
||||
|
|
@ -183,12 +183,14 @@ var Document = function(text) {
|
|||
var firstLine = lines.splice(0, 1)[0];
|
||||
var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
position = this.insertInLine(position, firstLine);
|
||||
if (lastLine !== null) {
|
||||
position = this.insertNewLine(position); // terminate first line
|
||||
position = this.insertLines(position.row, lines);
|
||||
position = this.insertInLine(position, lastLine || "");
|
||||
}
|
||||
this._dispatchEvent("changeEnd");
|
||||
return position;
|
||||
};
|
||||
|
||||
|
|
@ -200,6 +202,7 @@ var Document = function(text) {
|
|||
args.push.apply(args, lines);
|
||||
this.$lines.splice.apply(this.$lines, args);
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
var range = new Range(row, 0, row + lines.length, 0);
|
||||
var delta = {
|
||||
action: "insertLines",
|
||||
|
|
@ -207,12 +210,15 @@ var Document = function(text) {
|
|||
lines: lines
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.end;
|
||||
},
|
||||
|
||||
this.insertNewLine = function(position) {
|
||||
position = this.$clipPosition(position);
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
this.$lines[position.row] = line.substring(0, position.column);
|
||||
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
|
||||
|
||||
|
|
@ -227,6 +233,7 @@ var Document = function(text) {
|
|||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
@ -236,6 +243,8 @@ var Document = function(text) {
|
|||
return position;
|
||||
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
this.$lines[position.row] = line.substring(0, position.column) + text
|
||||
+ line.substring(position.column);
|
||||
|
||||
|
|
@ -250,6 +259,7 @@ var Document = function(text) {
|
|||
text: text
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
@ -265,6 +275,7 @@ var Document = function(text) {
|
|||
var firstRow = range.start.row;
|
||||
var lastRow = range.end.row;
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
if (range.isMultiLine()) {
|
||||
var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
|
||||
var lastFullRow = lastRow - 1;
|
||||
|
|
@ -283,6 +294,7 @@ var Document = function(text) {
|
|||
else {
|
||||
this.removeInLine(firstRow, range.start.column, range.end.column);
|
||||
}
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.start;
|
||||
};
|
||||
|
||||
|
|
@ -294,6 +306,7 @@ var Document = function(text) {
|
|||
var line = this.getLine(row);
|
||||
var removed = line.substring(startColumn, endColumn);
|
||||
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
||||
this._dispatchEvent("changeStart");
|
||||
this.$lines.splice(row, 1, newLine);
|
||||
|
||||
var delta = {
|
||||
|
|
@ -302,6 +315,7 @@ var Document = function(text) {
|
|||
text: removed
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.start;
|
||||
};
|
||||
|
||||
|
|
@ -313,6 +327,7 @@ var Document = function(text) {
|
|||
* @return {String[]} The removed lines
|
||||
*/
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
this._dispatchEvent("changeStart");
|
||||
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||
|
||||
|
|
@ -323,6 +338,7 @@ var Document = function(text) {
|
|||
lines: removed
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return removed;
|
||||
};
|
||||
|
||||
|
|
@ -333,6 +349,7 @@ var Document = function(text) {
|
|||
var range = new Range(row, firstLine.length, row+1, 0);
|
||||
var line = firstLine + secondLine;
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
this.$lines.splice(row, 2, line);
|
||||
|
||||
var delta = {
|
||||
|
|
@ -341,6 +358,7 @@ var Document = function(text) {
|
|||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
};
|
||||
|
||||
this.replace = function(range, text) {
|
||||
|
|
@ -352,6 +370,7 @@ var Document = function(text) {
|
|||
if (text == this.getTextRange(range))
|
||||
return range.end;
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
this.remove(range);
|
||||
if (text) {
|
||||
var end = this.insert(range.start, text);
|
||||
|
|
@ -359,6 +378,7 @@ var Document = function(text) {
|
|||
else {
|
||||
end = range.start;
|
||||
}
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
@ -382,6 +402,7 @@ var Document = function(text) {
|
|||
this.revertDeltas = function(deltas) {
|
||||
for (var i=deltas.length-1; i>=0; i--) {
|
||||
var delta = deltas[i];
|
||||
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
||||
if (delta.action == "insertLines")
|
||||
|
|
|
|||
|
|
@ -36,14 +36,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var Document = require("../document").Document,
|
||||
Range = require("../range").Range,
|
||||
assert = require("./assertions"),
|
||||
async = require("asyncjs");
|
||||
var Document = require("ace/document").Document;
|
||||
var Range = require("ace/range").Range;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
|
||||
"test: insert text in line" : function() {
|
||||
var doc = new Document(["12", "34"]);
|
||||
|
|
@ -302,11 +306,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
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.setFoldLine(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;
|
||||
});
|
||||
561
lib/ace/edit_session/folding.js
Normal file
561
lib/ace/edit_session/folding.js
Normal file
|
|
@ -0,0 +1,561 @@
|
|||
/* 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();
|
||||
}
|
||||
|
||||
Fold.prototype.setFoldLine = function(foldLine) {
|
||||
this.foldLine = foldLine;
|
||||
this.subFolds.forEach(function(fold) {
|
||||
fold.setFoldLine(foldLine);
|
||||
});
|
||||
}
|
||||
|
||||
Fold.prototype.clone = function() {
|
||||
var range = this.range.clone();
|
||||
var fold = new Fold(range, this.placeholder);
|
||||
this.subFolds.forEach(function(subFold) {
|
||||
fold.subFolds.push(subFold.clone());
|
||||
});
|
||||
return fold;
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
if(startFoldLine)
|
||||
i = foldData.indexOf(startFoldLine);
|
||||
if(i == -1)
|
||||
i = 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;
|
||||
}
|
||||
|
||||
// returns the fold which starts after or contains docRow
|
||||
this.getNextFold = function(docRow, startFoldLine) {
|
||||
var foldData = this.$foldData, ans;
|
||||
var i = 0;
|
||||
if(startFoldLine)
|
||||
i = foldData.indexOf(startFoldLine);
|
||||
if(i == -1)
|
||||
i = 0;
|
||||
for (i; i < foldData.length; i++) {
|
||||
var foldLine = foldData[i];
|
||||
if (foldLine.end.row >= docRow) {
|
||||
return foldLine;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
this.getFoldedRowCount = function(first, last) {
|
||||
var foldData = this.$foldData, rowCount = last-first+1;
|
||||
for (var i = 0; i < foldData.length; i++) {
|
||||
var foldLine = foldData[i],
|
||||
end = foldLine.end.row,
|
||||
start = foldLine.start.row;
|
||||
if(end >= last) {
|
||||
if(start < last) {
|
||||
if(start >= first)
|
||||
rowCount -= last-start;
|
||||
else
|
||||
rowCount = 0;//in one fold
|
||||
}
|
||||
break;
|
||||
} else if(end >= first){
|
||||
if (start >= first) //fold inside range
|
||||
rowCount -= end-start;
|
||||
else
|
||||
rowCount -= end-first+1;
|
||||
}
|
||||
}
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
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.getLength()) {
|
||||
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 doc = this.doc;
|
||||
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 += doc.getLine(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.getLine(row);
|
||||
return line.substring(startColumn || 0, endColumn || line.length);
|
||||
} else {
|
||||
return this.getFoldDisplayLine(
|
||||
foldLine, row, endColumn, startRow, startColumn);
|
||||
}
|
||||
};
|
||||
|
||||
this.$cloneFoldData = function() {
|
||||
var foldData = this.$foldData;
|
||||
var fd = [];
|
||||
fd = this.$foldData.map(function(foldLine) {
|
||||
var folds = foldLine.folds.map(function(fold) {
|
||||
return fold.clone();
|
||||
});
|
||||
return new FoldLine(fd, folds);
|
||||
});
|
||||
|
||||
return fd;
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
|
@ -52,7 +52,6 @@ var MouseHandler = require("ace/mouse_handler").MouseHandler;
|
|||
var KeyBinding = require("ace/keyboard/keybinding").KeyBinding;
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var Search = require("ace/search").Search;
|
||||
var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenizer;
|
||||
var Range = require("ace/range").Range;
|
||||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
|
|
@ -63,7 +62,7 @@ var Editor =function(renderer, session) {
|
|||
|
||||
this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
|
||||
this.keyBinding = new KeyBinding(this);
|
||||
|
||||
|
||||
// TODO detect touch event support
|
||||
if (useragent.isIPad) {
|
||||
//this.$mouseHandler = new TouchHandler(this);
|
||||
|
|
@ -122,9 +121,11 @@ var Editor =function(renderer, session) {
|
|||
var oldSession = this.session;
|
||||
this.session.removeEventListener("change", this.$onDocumentChange);
|
||||
this.session.removeEventListener("changeMode", this.$onChangeMode);
|
||||
this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
|
||||
this.session.removeEventListener("changeTabSize", this.$onChangeTabSize);
|
||||
this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit);
|
||||
this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode);
|
||||
this.session.removeEventListener("onChangeFold", this.$onChangeFold);
|
||||
this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker);
|
||||
this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker);
|
||||
this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint);
|
||||
|
|
@ -147,6 +148,9 @@ var Editor =function(renderer, session) {
|
|||
this.$onChangeMode = this.onChangeMode.bind(this);
|
||||
session.addEventListener("changeMode", this.$onChangeMode);
|
||||
|
||||
this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
|
||||
session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
|
||||
|
||||
this.$onChangeTabSize = this.renderer.updateText.bind(this.renderer);
|
||||
session.addEventListener("changeTabSize", this.$onChangeTabSize);
|
||||
|
||||
|
|
@ -156,18 +160,21 @@ var Editor =function(renderer, session) {
|
|||
this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
|
||||
session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
|
||||
|
||||
this.$onChangeFold = this.onChangeFold.bind(this);
|
||||
session.addEventListener("changeFold", this.$onChangeFold);
|
||||
|
||||
this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
|
||||
this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
|
||||
|
||||
|
||||
this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
|
||||
this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
|
||||
|
||||
|
||||
this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
|
||||
this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
|
||||
|
||||
this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
|
||||
this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
|
||||
|
||||
|
||||
this.$onCursorChange = this.onCursorChange.bind(this);
|
||||
this.session.addEventListener("changeOverwrite", this.$onCursorChange);
|
||||
|
||||
|
|
@ -178,8 +185,6 @@ var Editor =function(renderer, session) {
|
|||
this.selection.addEventListener("changeSelection", this.$onSelectionChange);
|
||||
|
||||
this.onChangeMode();
|
||||
this.bgTokenizer.setDocument(session.getDocument());
|
||||
this.bgTokenizer.start(0);
|
||||
|
||||
this.onCursorChange();
|
||||
this.onSelectionChange();
|
||||
|
|
@ -187,6 +192,7 @@ var Editor =function(renderer, session) {
|
|||
this.onChangeBackMarker();
|
||||
this.onChangeBreakpoint();
|
||||
this.onChangeAnnotation();
|
||||
this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
|
||||
this.renderer.scrollToRow(session.getScrollTopRow());
|
||||
this.renderer.updateFull();
|
||||
|
||||
|
|
@ -212,13 +218,21 @@ var Editor =function(renderer, session) {
|
|||
this.renderer.setTheme(theme);
|
||||
};
|
||||
|
||||
this.getTheme = function() {
|
||||
return this.renderer.getTheme();
|
||||
};
|
||||
|
||||
this.setStyle = function(style) {
|
||||
this.renderer.setStyle(style)
|
||||
this.renderer.setStyle(style);
|
||||
};
|
||||
|
||||
this.unsetStyle = function(style) {
|
||||
this.renderer.unsetStyle(style)
|
||||
}
|
||||
this.renderer.unsetStyle(style);
|
||||
};
|
||||
|
||||
this.setFontSize = function(size) {
|
||||
this.container.style.fontSize = size;
|
||||
};
|
||||
|
||||
this.$highlightBrackets = function() {
|
||||
if (this.session.$bracketHighlight) {
|
||||
|
|
@ -250,7 +264,7 @@ var Editor =function(renderer, session) {
|
|||
// to be on the save side we do both
|
||||
// except for IE
|
||||
var _self = this;
|
||||
if (!useragent.isIE) {
|
||||
if (!useragent.isIE) {
|
||||
setTimeout(function() {
|
||||
_self.textInput.focus();
|
||||
});
|
||||
|
|
@ -278,7 +292,6 @@ var Editor =function(renderer, session) {
|
|||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
|
||||
this.bgTokenizer.start(range.start.row);
|
||||
if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
|
||||
var lastRow = range.end.row;
|
||||
else
|
||||
|
|
@ -311,22 +324,28 @@ var Editor =function(renderer, session) {
|
|||
|
||||
this.$updateHighlightActiveLine = function() {
|
||||
var session = this.getSession();
|
||||
|
||||
|
||||
if (session.$highlightLineMarker) {
|
||||
session.removeMarker(session.$highlightLineMarker);
|
||||
}
|
||||
session.$highlightLineMarker = null;
|
||||
|
||||
if (this.getHighlightActiveLine() && (this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
|
||||
var cursor = this.getCursorPosition();
|
||||
var range = new Range(cursor.row, 0, cursor.row+1, 0);
|
||||
var cursor = this.getCursorPosition(),
|
||||
foldLine = this.session.getFoldLine(cursor.row);
|
||||
var range;
|
||||
if (foldLine) {
|
||||
range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0);
|
||||
} else {
|
||||
range = new Range(cursor.row, 0, cursor.row+1, 0);
|
||||
}
|
||||
session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "line");
|
||||
}
|
||||
};
|
||||
|
||||
this.onSelectionChange = function(e) {
|
||||
var session = this.getSession();
|
||||
|
||||
|
||||
if (session.$selectionMarker) {
|
||||
session.removeMarker(session.$selectionMarker);
|
||||
}
|
||||
|
|
@ -336,22 +355,22 @@ var Editor =function(renderer, session) {
|
|||
var range = this.selection.getRange();
|
||||
var style = this.getSelectionStyle();
|
||||
session.$selectionMarker = session.addMarker(range, "ace_selection", style);
|
||||
} else {
|
||||
this.$updateHighlightActiveLine();
|
||||
}
|
||||
|
||||
this.onCursorChange(e);
|
||||
|
||||
if (this.$highlightSelectedWord)
|
||||
this.mode.highlightSelection(this);
|
||||
this.session.getMode().highlightSelection(this);
|
||||
};
|
||||
|
||||
this.onChangeFrontMarker = function() {
|
||||
this.renderer.updateFrontMarkers();
|
||||
};
|
||||
|
||||
|
||||
this.onChangeBackMarker = function() {
|
||||
this.renderer.updateBackMarkers();
|
||||
};
|
||||
|
||||
|
||||
this.onChangeBreakpoint = function() {
|
||||
this.renderer.setBreakpoints(this.session.getBreakpoints());
|
||||
};
|
||||
|
|
@ -361,22 +380,7 @@ var Editor =function(renderer, session) {
|
|||
};
|
||||
|
||||
this.onChangeMode = function() {
|
||||
var mode = this.session.getMode();
|
||||
if (this.mode == mode)
|
||||
return;
|
||||
|
||||
this.mode = mode;
|
||||
var tokenizer = mode.getTokenizer();
|
||||
|
||||
if (!this.bgTokenizer) {
|
||||
var onUpdate = this.onTokenizerUpdate.bind(this);
|
||||
this.bgTokenizer = new BackgroundTokenizer(tokenizer, this);
|
||||
this.bgTokenizer.addEventListener("update", onUpdate);
|
||||
} else {
|
||||
this.bgTokenizer.setTokenizer(tokenizer);
|
||||
}
|
||||
|
||||
this.renderer.setTokenizer(this.bgTokenizer);
|
||||
this.renderer.updateText()
|
||||
};
|
||||
|
||||
this.onChangeWrapLimit = function() {
|
||||
|
|
@ -387,6 +391,14 @@ var Editor =function(renderer, session) {
|
|||
this.renderer.onResize(true);
|
||||
};
|
||||
|
||||
this.onChangeFold = function() {
|
||||
// Update the active line marker as due to folding changes the current
|
||||
// line range on the screen might have changed.
|
||||
this.$updateHighlightActiveLine();
|
||||
// TODO: This might be too much updating. Okay for now.
|
||||
this.renderer.updateFull();
|
||||
};
|
||||
|
||||
this.getCopyText = function() {
|
||||
if (!this.selection.isEmpty()) {
|
||||
return this.session.getTextRange(this.getSelectionRange());
|
||||
|
|
@ -410,7 +422,18 @@ var Editor =function(renderer, session) {
|
|||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
var session = this.session;
|
||||
var mode = session.getMode();
|
||||
|
||||
var cursor = this.getCursorPosition();
|
||||
|
||||
if (this.getBehavioursEnabled()) {
|
||||
// Get a transform if the current mode wants one.
|
||||
var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
|
||||
if (transform)
|
||||
text = transform.text;
|
||||
}
|
||||
|
||||
text = text.replace("\t", this.session.getTabString());
|
||||
|
||||
// remove selected text
|
||||
|
|
@ -426,28 +449,42 @@ var Editor =function(renderer, session) {
|
|||
|
||||
this.clearSelection();
|
||||
|
||||
var lineState = this.bgTokenizer.getState(cursor.row);
|
||||
var shouldOutdent = this.mode.checkOutdent(lineState, this.session.getLine(cursor.row), text);
|
||||
var line = this.session.getLine(cursor.row);
|
||||
var lineIndent = this.mode.getNextLineIndent(lineState, line.slice(0, cursor.column), this.session.getTabString());
|
||||
var end = this.session.insert(cursor, text);
|
||||
|
||||
var start = cursor.column;
|
||||
var lineState = session.getState(cursor.row);
|
||||
var shouldOutdent = mode.checkOutdent(lineState, session.getLine(cursor.row), text);
|
||||
var line = session.getLine(cursor.row);
|
||||
var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
|
||||
var end = session.insert(cursor, text);
|
||||
|
||||
var lineState = this.bgTokenizer.getState(cursor.row);
|
||||
if (transform && transform.selection) {
|
||||
if (transform.selection.length == 2) { // Transform relative to the current column
|
||||
this.selection.setSelectionRange(
|
||||
new Range(cursor.row, start + transform.selection[0],
|
||||
cursor.row, start + transform.selection[1]));
|
||||
} else { // Transform relative to the current row.
|
||||
this.selection.setSelectionRange(
|
||||
new Range(cursor.row + transform.selection[0],
|
||||
transform.selection[1],
|
||||
cursor.row + transform.selection[2],
|
||||
transform.selection[3]));
|
||||
}
|
||||
}
|
||||
|
||||
var lineState = session.getState(cursor.row);
|
||||
|
||||
// TODO disabled multiline auto indent
|
||||
// possibly doing the indent before inserting the text
|
||||
// if (cursor.row !== end.row) {
|
||||
if (this.session.getDocument().isNewLine(text)) {
|
||||
if (session.getDocument().isNewLine(text)) {
|
||||
this.moveCursorTo(cursor.row+1, 0);
|
||||
|
||||
var size = this.session.getTabSize(),
|
||||
minIndent = Number.MAX_VALUE;
|
||||
|
||||
|
||||
var size = session.getTabSize();
|
||||
var minIndent = Number.MAX_VALUE;
|
||||
|
||||
for (var row = cursor.row + 1; row <= end.row; ++row) {
|
||||
var indent = 0;
|
||||
|
||||
line = this.session.getLine(row);
|
||||
line = session.getLine(row);
|
||||
for (var i = 0; i < line.length; ++i)
|
||||
if (line.charAt(i) == '\t')
|
||||
indent += size;
|
||||
|
|
@ -462,21 +499,21 @@ var Editor =function(renderer, session) {
|
|||
for (var row = cursor.row + 1; row <= end.row; ++row) {
|
||||
var outdent = minIndent;
|
||||
|
||||
line = this.session.getLine(row);
|
||||
line = session.getLine(row);
|
||||
for (var i = 0; i < line.length && outdent > 0; ++i)
|
||||
if (line.charAt(i) == '\t')
|
||||
outdent -= size;
|
||||
else if (line.charAt(i) == ' ')
|
||||
outdent -= 1;
|
||||
this.session.remove(new Range(row, 0, row, i));
|
||||
session.remove(new Range(row, 0, row, i));
|
||||
}
|
||||
this.session.indentRows(cursor.row + 1, end.row, lineIndent);
|
||||
session.indentRows(cursor.row + 1, end.row, lineIndent);
|
||||
} else {
|
||||
if (shouldOutdent) {
|
||||
this.mode.autoOutdent(lineState, this.session, cursor.row);
|
||||
mode.autoOutdent(lineState, session, cursor.row);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.onTextInput = function(text) {
|
||||
this.keyBinding.onTextInput(text);
|
||||
|
|
@ -487,7 +524,7 @@ var Editor =function(renderer, session) {
|
|||
};
|
||||
|
||||
this.setOverwrite = function(overwrite) {
|
||||
this.session.setOverwrite();
|
||||
this.session.setOverwrite(overwrite);
|
||||
};
|
||||
|
||||
this.getOverwrite = function() {
|
||||
|
|
@ -538,9 +575,9 @@ var Editor =function(renderer, session) {
|
|||
|
||||
this.$highlightSelectedWord = shouldHighlight;
|
||||
if (shouldHighlight)
|
||||
this.mode.highlightSelection(this);
|
||||
this.session.getMode().highlightSelection(this);
|
||||
else
|
||||
this.mode.clearSelectionHighlight(this);
|
||||
this.session.getMode().clearSelectionHighlight(this);
|
||||
};
|
||||
|
||||
this.getHighlightSelectedWord = function() {
|
||||
|
|
@ -582,6 +619,15 @@ var Editor =function(renderer, session) {
|
|||
this.getReadOnly = function() {
|
||||
return this.$readOnly;
|
||||
};
|
||||
|
||||
this.$modeBehaviours = false;
|
||||
this.setBehavioursEnabled = function (enabled) {
|
||||
this.$modeBehaviours = enabled;
|
||||
}
|
||||
|
||||
this.getBehavioursEnabled = function () {
|
||||
return this.$modeBehaviours;
|
||||
}
|
||||
|
||||
this.removeRight = function() {
|
||||
if (this.$readOnly)
|
||||
|
|
@ -600,11 +646,21 @@ var Editor =function(renderer, session) {
|
|||
|
||||
if (this.selection.isEmpty())
|
||||
this.selection.selectLeft();
|
||||
|
||||
var range = this.getSelectionRange();
|
||||
if (this.getBehavioursEnabled()) {
|
||||
var session = this.session;
|
||||
var state = session.getState(range.start.row);
|
||||
var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
|
||||
if (new_range !== false) {
|
||||
range = new_range;
|
||||
}
|
||||
}
|
||||
|
||||
this.session.remove(this.getSelectionRange());
|
||||
this.session.remove(range);
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
||||
this.removeWordRight = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
|
@ -615,7 +671,7 @@ var Editor =function(renderer, session) {
|
|||
this.session.remove(this.getSelectionRange());
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
||||
this.removeWordLeft = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
|
@ -626,7 +682,7 @@ var Editor =function(renderer, session) {
|
|||
this.session.remove(this.getSelectionRange());
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
||||
this.removeToLineStart = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
|
@ -637,7 +693,7 @@ var Editor =function(renderer, session) {
|
|||
this.session.remove(this.getSelectionRange());
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
||||
this.removeToLineEnd = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
|
@ -645,37 +701,43 @@ var Editor =function(renderer, session) {
|
|||
if (this.selection.isEmpty())
|
||||
this.selection.selectLineEnd();
|
||||
|
||||
this.session.remove(this.getSelectionRange());
|
||||
var range = this.getSelectionRange();
|
||||
if (range.start.column == range.end.column && range.start.row == range.end.row) {
|
||||
range.end.column = 0;
|
||||
range.end.row++;
|
||||
}
|
||||
|
||||
this.session.remove(range);
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
this.splitLine = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
|
||||
if (!this.selection.isEmpty()) {
|
||||
this.session.remove(this.getSelectionRange());
|
||||
this.clearSelection();
|
||||
}
|
||||
|
||||
|
||||
var cursor = this.getCursorPosition();
|
||||
this.insert("\n");
|
||||
this.moveCursorToPosition(cursor);
|
||||
};
|
||||
|
||||
|
||||
this.transposeLetters = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
|
||||
if (!this.selection.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var cursor = this.getCursorPosition();
|
||||
var column = cursor.column;
|
||||
if (column == 0)
|
||||
return;
|
||||
|
||||
|
||||
var line = this.session.getLine(cursor.row);
|
||||
if (column < line.length) {
|
||||
var swap = line.charAt(column) + line.charAt(column-1);
|
||||
|
|
@ -687,7 +749,7 @@ var Editor =function(renderer, session) {
|
|||
}
|
||||
this.session.replace(range, swap);
|
||||
};
|
||||
|
||||
|
||||
this.indent = function() {
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
|
@ -726,9 +788,9 @@ var Editor =function(renderer, session) {
|
|||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
var state = this.bgTokenizer.getState(this.getCursorPosition().row);
|
||||
var state = this.session.getState(this.getCursorPosition().row);
|
||||
var rows = this.$getSelectedRows()
|
||||
this.mode.toggleCommentLines(state, this.session, rows.first, rows.last);
|
||||
this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
|
||||
};
|
||||
|
||||
this.removeLines = function() {
|
||||
|
|
@ -900,7 +962,7 @@ var Editor =function(renderer, session) {
|
|||
this.scrollToLine = function(line, center) {
|
||||
this.renderer.scrollToLine(line, center);
|
||||
};
|
||||
|
||||
|
||||
this.centerSelection = function() {
|
||||
var range = this.getSelectionRange();
|
||||
var line = Math.floor(range.start.row + (range.end.row - range.start.row) / 2);
|
||||
|
|
@ -925,7 +987,7 @@ var Editor =function(renderer, session) {
|
|||
this.selection.selectAll();
|
||||
this.$blockScrolling -= 1;
|
||||
};
|
||||
|
||||
|
||||
this.clearSelection = function() {
|
||||
this.selection.clearSelection();
|
||||
};
|
||||
|
|
@ -1052,7 +1114,7 @@ var Editor =function(renderer, session) {
|
|||
this.$blockScrolling += 1;
|
||||
for (var i = ranges.length - 1; i >= 0; --i)
|
||||
this.$tryReplace(ranges[i], replacement);
|
||||
|
||||
|
||||
this.selection.setSelectionRange(selection);
|
||||
this.$blockScrolling -= 1;
|
||||
},
|
||||
|
|
@ -1119,6 +1181,10 @@ var Editor =function(renderer, session) {
|
|||
this.session.getUndoManager().redo();
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
this.renderer.destroy();
|
||||
}
|
||||
|
||||
}).call(Editor.prototype);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,16 +35,21 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
require("ace/test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var EditSession = require("../edit_session").EditSession,
|
||||
Editor = require("../editor").Editor,
|
||||
Text = require("../mode/text").Mode,
|
||||
JavaScriptMode = require("../mode/javascript").Mode,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
assert = require("./assertions");
|
||||
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 Test = {
|
||||
module.exports = {
|
||||
|
||||
setUp : function(next) {
|
||||
this.session1 = new EditSession(["abc", "def"]);
|
||||
|
|
@ -153,10 +158,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -36,14 +36,18 @@
|
|||
*
|
||||
* ***** 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,
|
||||
Editor = require("../editor").Editor,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
TextMode = require("ace/mode/text").Mode,
|
||||
assert = require("./assertions"),
|
||||
async = require("asyncjs");
|
||||
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 " +
|
||||
|
|
@ -66,7 +70,7 @@ var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
|||
"libero vehicula odio, eget bibendum mauris velit eu lorem.\n" +
|
||||
"consectetur";
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
setUp: function(next) {
|
||||
this.session = new EditSession(lipsum);
|
||||
this.editor = new Editor(new MockRenderer(), this.session);
|
||||
|
|
@ -201,13 +205,11 @@ var Test = {
|
|||
|
||||
assert.equal(this.session.getTextRange(match), "consectetur");
|
||||
assert.equal(this.session.$selectionOccurrences.length, 2);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec();
|
||||
}
|
||||
|
|
@ -35,14 +35,19 @@
|
|||
*
|
||||
* ***** 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,
|
||||
Editor = require("../editor").Editor,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
assert = require("./assertions");
|
||||
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 Test = {
|
||||
module.exports = {
|
||||
createEditSession : function(rows, cols) {
|
||||
var line = new Array(cols + 1).join("a");
|
||||
var text = new Array(rows).join(line + "\n") + line;
|
||||
|
|
@ -148,10 +153,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test)
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,16 +35,21 @@
|
|||
*
|
||||
* ***** 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,
|
||||
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 session = new EditSession(["a", "b", "c", "d"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
|
@ -483,14 +488,31 @@ var Test = {
|
|||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 2);
|
||||
editor.transposeLetters();
|
||||
assert.position(editor.getCursorPosition(), 1, 3);
|
||||
assert.position(editor.getCursorPosition(), 1, 3);
|
||||
},
|
||||
|
||||
"test: remove to line end": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 2);
|
||||
editor.removeToLineEnd();
|
||||
assert.equal(session.getValue(), ["123", "45", "89"].join("\n"));
|
||||
},
|
||||
|
||||
"test: remove to line end at line end should remove the new line": function() {
|
||||
var session = new EditSession(["123", "4567", "89"]);
|
||||
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
editor.moveCursorTo(1, 4);
|
||||
editor.removeToLineEnd();
|
||||
assert.position(editor.getCursorPosition(), 1, 4);
|
||||
assert.equal(session.getValue(), ["123", "456789"].join("\n"));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -46,6 +46,31 @@ var vimStates = {
|
|||
key: "i",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "a",
|
||||
exec: "gotoright",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "shift-i",
|
||||
exec: "gotolinestart",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "shift-a",
|
||||
exec: "gotolineend",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "shift-c",
|
||||
exec: "removetolineend",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "shift-r",
|
||||
exec: "overwrite",
|
||||
then: "replaceMode"
|
||||
},
|
||||
{
|
||||
regex: [ "([0-9]*)", "(k|up)" ],
|
||||
exec: "golineup",
|
||||
|
|
@ -94,6 +119,30 @@ var vimStates = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "shift-g",
|
||||
exec: "gotoend"
|
||||
},
|
||||
{
|
||||
key: "b",
|
||||
exec: "gotowordleft"
|
||||
},
|
||||
{
|
||||
key: "e",
|
||||
exec: "gotowordright"
|
||||
},
|
||||
{
|
||||
key: "x",
|
||||
exec: "del"
|
||||
},
|
||||
{
|
||||
key: "shift-x",
|
||||
exec: "backspace"
|
||||
},
|
||||
{
|
||||
key: "shift-d",
|
||||
exec: "removetolineend"
|
||||
},
|
||||
{
|
||||
comment: "Catch some keyboard input to stop it here",
|
||||
match: matchCharacterOnly
|
||||
|
|
@ -104,6 +153,13 @@ var vimStates = {
|
|||
key: "esc",
|
||||
then: "start"
|
||||
}
|
||||
],
|
||||
replaceMode: [
|
||||
{
|
||||
key: "esc",
|
||||
exec: "overwrite",
|
||||
then: "start"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -140,11 +140,11 @@ StateHandler.prototype = {
|
|||
}
|
||||
|
||||
// If there is a command to execute, then figure out the
|
||||
// comand and the arguments.
|
||||
// command and the arguments.
|
||||
if (binding.exec) {
|
||||
result.command = binding.exec;
|
||||
|
||||
// Bulid the arguments.
|
||||
// Build the arguments.
|
||||
if (binding.params) {
|
||||
var value;
|
||||
result.args = {};
|
||||
|
|
@ -197,7 +197,7 @@ StateHandler.prototype = {
|
|||
// 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))) {
|
||||
if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,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
|
||||
|
|
@ -97,12 +98,17 @@ var TextInput = function(parentNode, host) {
|
|||
host.onCompositionUpdate(text.value);
|
||||
};
|
||||
|
||||
var onCompositionEnd = function() {
|
||||
var onCompositionEnd = function(e) {
|
||||
inCompostion = false;
|
||||
host.onCompositionEnd();
|
||||
setTimeout(function () {
|
||||
sendText();
|
||||
}, 0);
|
||||
if (useragent.isGecko) {
|
||||
sendText();
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
if (!inCompostion)
|
||||
sendText();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
var onCopy = function(e) {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ var Cursor = function(parentEl) {
|
|||
parentEl.appendChild(this.element);
|
||||
|
||||
this.cursor = dom.createElement("div");
|
||||
this.cursor.className = "ace_cursor";
|
||||
this.cursor.className = "ace_cursor ace_hidden";
|
||||
this.element.appendChild(this.cursor);
|
||||
|
||||
this.isVisible = false;
|
||||
};
|
||||
|
|
@ -60,18 +61,14 @@ var Cursor = function(parentEl) {
|
|||
|
||||
this.hideCursor = function() {
|
||||
this.isVisible = false;
|
||||
if (this.cursor.parentNode) {
|
||||
this.cursor.parentNode.removeChild(this.cursor);
|
||||
}
|
||||
dom.addCssClass(this.cursor, "ace_hidden");
|
||||
clearInterval(this.blinkId);
|
||||
};
|
||||
|
||||
this.showCursor = function() {
|
||||
this.isVisible = true;
|
||||
this.element.appendChild(this.cursor);
|
||||
|
||||
var cursor = this.cursor;
|
||||
cursor.style.visibility = "visible";
|
||||
this.isVisible = true;
|
||||
dom.removeCssClass(this.cursor, "ace_hidden");
|
||||
this.cursor.style.visibility = "visible";
|
||||
this.restartTimer();
|
||||
};
|
||||
|
||||
|
|
@ -120,19 +117,22 @@ var Cursor = function(parentEl) {
|
|||
this.cursor.style.width = config.characterWidth + "px";
|
||||
this.cursor.style.height = config.lineHeight + "px";
|
||||
|
||||
if (this.isVisible) {
|
||||
this.element.appendChild(this.cursor);
|
||||
var overwrite = this.session.getOverwrite()
|
||||
if (overwrite != this.overwrite) {
|
||||
this.overwrite = overwrite;
|
||||
if (overwrite)
|
||||
dom.addCssClass(this.cursor, "ace_overwrite");
|
||||
else
|
||||
dom.removeCssClass(this.cursor, "ace_overwrite");
|
||||
}
|
||||
|
||||
if (this.session.getOverwrite()) {
|
||||
dom.addCssClass(this.cursor, "ace_overwrite");
|
||||
} else {
|
||||
dom.removeCssClass(this.cursor, "ace_overwrite");
|
||||
}
|
||||
|
||||
|
||||
this.restartTimer();
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
clearInterval(this.blinkId);
|
||||
}
|
||||
|
||||
}).call(Cursor.prototype);
|
||||
|
||||
exports.Cursor = Cursor;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
* 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
|
||||
|
|
@ -73,12 +73,12 @@ var Gutter = function(parentEl) {
|
|||
|
||||
this.setAnnotations = function(annotations) {
|
||||
// iterate over sparse array
|
||||
this.$annotations = [];
|
||||
this.$annotations = [];
|
||||
for (var row in annotations) if (annotations.hasOwnProperty(row)) {
|
||||
var rowAnnotations = annotations[row];
|
||||
if (!rowAnnotations)
|
||||
continue;
|
||||
|
||||
|
||||
var rowInfo = this.$annotations[row] = {
|
||||
text: []
|
||||
};
|
||||
|
|
@ -99,20 +99,40 @@ var Gutter = function(parentEl) {
|
|||
this.update = function(config) {
|
||||
this.$config = config;
|
||||
|
||||
var emptyAnno = {className: "", text: []};
|
||||
var html = [];
|
||||
for ( var i = config.firstRow; i <= config.lastRow; i++) {
|
||||
var annotation = this.$annotations[i] || {
|
||||
className: "",
|
||||
text: []
|
||||
};
|
||||
var i = config.firstRow;
|
||||
var lastRow = config.lastRow;
|
||||
var fold = this.session.getNextFold(i);
|
||||
var foldStart = fold ? fold.start.row : Infinity;
|
||||
|
||||
while (true) {
|
||||
if(i > foldStart) {
|
||||
i = fold.end.row + 1;
|
||||
fold = this.session.getNextFold(i);
|
||||
foldStart = fold ?fold.start.row :Infinity;
|
||||
}
|
||||
if(i > lastRow)
|
||||
break;
|
||||
|
||||
var annotation = this.$annotations[i] || emptyAnno;
|
||||
html.push("<div class='ace_gutter-cell",
|
||||
this.$decorations[i] || "",
|
||||
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
||||
annotation.className,
|
||||
"' title='", annotation.text.join("\n"),
|
||||
"' style='height:", this.session.getRowHeight(config, i), "px;'>", (i+1), "</div>");
|
||||
"' style='height:", config.lineHeight, "px;'>", (i+1));
|
||||
|
||||
var wrappedRowLength = this.session.getRowLength(i) - 1;
|
||||
while (wrappedRowLength--) {
|
||||
html.push("</div><div class='ace_gutter-cell' style='height:", config.lineHeight, "px'>¦</div>");
|
||||
}
|
||||
|
||||
html.push("</div>");
|
||||
|
||||
i++;
|
||||
}
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
this.element.style.height = config.minHeight + "px";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
* 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
|
||||
|
|
@ -43,6 +43,7 @@ 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) {
|
||||
|
|
@ -63,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;
|
||||
};
|
||||
|
|
@ -85,7 +82,7 @@ var Text = function(parentEl) {
|
|||
|
||||
this.$pollSizeChanges = function() {
|
||||
var self = this;
|
||||
setInterval(function() {
|
||||
this.$pollSizeChangesTimer = setInterval(function() {
|
||||
self.checkForSizeChanges();
|
||||
}, 500);
|
||||
};
|
||||
|
|
@ -129,10 +126,9 @@ var Text = function(parentEl) {
|
|||
}
|
||||
|
||||
var style = this.$measureNode.style;
|
||||
for (var prop in this.$fontStyles) {
|
||||
var value = dom.computedStyle(this.element, prop);
|
||||
style[prop] = value;
|
||||
}
|
||||
var computedStyle = dom.computedStyle(this.element);
|
||||
for (var prop in this.$fontStyles)
|
||||
style[prop] = computedStyle[prop];
|
||||
|
||||
var size = {
|
||||
height: this.$measureNode.offsetHeight,
|
||||
|
|
@ -190,18 +186,32 @@ var Text = function(parentEl) {
|
|||
var first = Math.max(firstRow, config.firstRow);
|
||||
var last = Math.min(lastRow, config.lastRow);
|
||||
|
||||
var lineElements = this.element.childNodes;
|
||||
var tokens = this.tokenizer.getTokens(first, last);
|
||||
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 ++;
|
||||
}
|
||||
|
||||
for (var i=first; i<=last; i++) {
|
||||
var lineElement = lineElements[i - config.firstRow];
|
||||
var lineElement = lineElements[lineElementsIdx++];
|
||||
if (!lineElement)
|
||||
continue;
|
||||
|
||||
var html = [];
|
||||
this.$renderLine(html, i, tokens[i-first].tokens);
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -217,13 +227,12 @@ var Text = function(parentEl) {
|
|||
return this.update(config);
|
||||
|
||||
var el = this.element;
|
||||
|
||||
if (oldConfig.firstRow < config.firstRow)
|
||||
for (var row=oldConfig.firstRow; row<config.firstRow; row++)
|
||||
for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)
|
||||
el.removeChild(el.firstChild);
|
||||
|
||||
if (oldConfig.lastRow > config.lastRow)
|
||||
for (var row=config.lastRow+1; row<=oldConfig.lastRow; row++)
|
||||
for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
|
||||
el.removeChild(el.lastChild);
|
||||
|
||||
if (config.firstRow < oldConfig.firstRow) {
|
||||
|
|
@ -241,21 +250,38 @@ 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 fragment = document.createDocumentFragment(),
|
||||
row = firstRow,
|
||||
fold = this.session.getNextFold(row),
|
||||
foldStart = fold ?fold.start.row :Infinity;
|
||||
|
||||
while (true) {
|
||||
if(row > foldStart) {
|
||||
row = fold.end.row+1;
|
||||
fold = this.session.getNextFold(row);
|
||||
foldStart = fold ?fold.start.row :Infinity;
|
||||
}
|
||||
if(row > lastRow)
|
||||
break;
|
||||
|
||||
var lineEl = dom.createElement("div");
|
||||
|
||||
lineEl.className = "ace_line";
|
||||
var style = lineEl.style;
|
||||
style.height = this.session.getRowHeight(config, row) + "px";
|
||||
style.width = config.width + "px";
|
||||
|
||||
var html = [];
|
||||
if (tokens.length > row-firstRow)
|
||||
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++;
|
||||
}
|
||||
return fragment;
|
||||
};
|
||||
|
|
@ -265,12 +291,34 @@ var Text = function(parentEl) {
|
|||
this.config = config;
|
||||
|
||||
var html = [];
|
||||
var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow)
|
||||
var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow);
|
||||
var firstRow = config.firstRow, lastRow = config.lastRow;
|
||||
|
||||
// Clear the current content of the element and add the rendered fragment.
|
||||
this.element.innerHTML = "";
|
||||
this.element.appendChild(fragment);
|
||||
var row = firstRow,
|
||||
fold = this.session.getNextFold(row),
|
||||
foldStart = fold ?fold.start.row :Infinity;
|
||||
|
||||
while (true) {
|
||||
if(row > foldStart) {
|
||||
row = fold.end.row+1;
|
||||
fold = this.session.getNextFold(row);
|
||||
foldStart = fold ?fold.start.row :Infinity;
|
||||
}
|
||||
if(row > lastRow)
|
||||
break;
|
||||
|
||||
html.push("<div class='ace_line'>");
|
||||
// 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);
|
||||
html.push("</div>");
|
||||
|
||||
row++;
|
||||
}
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
};
|
||||
|
||||
this.$textToken = {
|
||||
|
|
@ -279,51 +327,63 @@ var Text = function(parentEl) {
|
|||
"lparen": true
|
||||
};
|
||||
|
||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||
var _self = this,
|
||||
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>";
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
screenColumn = 0,
|
||||
self = this;
|
||||
|
||||
function addToken(token, value) {
|
||||
var output = value
|
||||
.replace(/\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, 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 == "&") {
|
||||
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 (this.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:" + (characterWidth * 2) + "px'>" + c + "</span>"
|
||||
}
|
||||
});
|
||||
screenColumn += value.length;
|
||||
|
||||
if (!_self.$textToken[token.type]) {
|
||||
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
||||
stringBuilder.push("<span class='", classes, "'>", output, "</span>");
|
||||
}
|
||||
else {
|
||||
stringBuilder.push(output);
|
||||
}
|
||||
screenColumn += self.$renderToken(
|
||||
stringBuilder, screenColumn, token, value);
|
||||
}
|
||||
|
||||
var splits = this.session.getRowSplitData(row);
|
||||
var chars = 0, split = 0, splitChars;
|
||||
|
||||
if (!splits || splits.length == 0) {
|
||||
splitChars = Number.MAX_VALUE;
|
||||
} else {
|
||||
|
|
@ -359,10 +419,10 @@ var Text = function(parentEl) {
|
|||
addToken(token, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (this.showInvisibles) {
|
||||
if (row !== this.session.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>");
|
||||
|
|
@ -371,6 +431,87 @@ var Text = function(parentEl) {
|
|||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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.$useWrapMode?this.session.$wrapData[row]:null;
|
||||
this.$renderLineCore(stringBuilder, row, renderTokens, splits);
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
clearInterval(this.$pollSizeChangesTimer);
|
||||
};
|
||||
|
||||
}).call(Text.prototype);
|
||||
|
||||
exports.Text = Text;
|
||||
|
|
|
|||
97
lib/ace/mode/behaviour.js
Normal file
97
lib/ace/mode/behaviour.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):
|
||||
* Chris Spencer <chris.ag.spencer AT googlemail 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 Behaviour = function() {
|
||||
this.$behaviours = {};
|
||||
};
|
||||
|
||||
(function () {
|
||||
|
||||
this.add = function (name, action, callback) {
|
||||
switch (undefined) {
|
||||
case this.$behaviours:
|
||||
this.$behaviours = {};
|
||||
case this.$behaviours[name]:
|
||||
this.$behaviours[name] = {};
|
||||
}
|
||||
this.$behaviours[name][action] = callback;
|
||||
}
|
||||
|
||||
this.addBehaviours = function (behaviours) {
|
||||
for (var key in behaviours) {
|
||||
for (var action in behaviours[key]) {
|
||||
this.add(key, action, behaviours[key][action]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.remove = function (name) {
|
||||
if (this.$behaviours && this.$behaviours[name]) {
|
||||
delete this.$behaviours[name];
|
||||
}
|
||||
}
|
||||
|
||||
this.inherit = function (mode, filter) {
|
||||
if (typeof mode === "function") {
|
||||
var behaviours = new mode().getBehaviours(filter);
|
||||
} else {
|
||||
var behaviours = mode.getBehaviours(filter);
|
||||
}
|
||||
this.addBehaviours(behaviours);
|
||||
}
|
||||
|
||||
this.getBehaviours = function (filter) {
|
||||
if (!filter) {
|
||||
return this.$behaviours;
|
||||
} else {
|
||||
var ret = {}
|
||||
for (var i = 0; i < filter.length; i++) {
|
||||
if (this.$behaviours[filter[i]]) {
|
||||
ret[filter[i]] = this.$behaviours[filter[i]];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
}).call(Behaviour.prototype);
|
||||
|
||||
exports.Behaviour = Behaviour;
|
||||
});
|
||||
226
lib/ace/mode/behaviour/cstyle.js
Normal file
226
lib/ace/mode/behaviour/cstyle.js
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/* 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):
|
||||
* Chris Spencer <chris.ag.spencer AT googlemail 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 Behaviour = require('ace/mode/behaviour').Behaviour;
|
||||
|
||||
var CstyleBehaviour = function () {
|
||||
|
||||
this.add("braces", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == '{') {
|
||||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "") {
|
||||
return {
|
||||
text: '{' + selected + '}',
|
||||
selection: false
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
text: '{}',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
} else if (text == '}') {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == '}') {
|
||||
var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
|
||||
if (matching !== null) {
|
||||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (text == "\n") {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == '}') {
|
||||
var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column});
|
||||
|
||||
var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString());
|
||||
var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row));
|
||||
|
||||
return {
|
||||
text: '\n' + indent + '\n' + next_indent,
|
||||
selection: [1, indent.length, 1, indent.length]
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.add("braces", "deletion", function (state, action, editor, session, range) {
|
||||
var selected = session.doc.getTextRange(range);
|
||||
if (!range.isMultiLine() && selected == '{') {
|
||||
var line = session.doc.getLine(range.start.row);
|
||||
var rightChar = line.substring(range.end.column, range.end.column + 1);
|
||||
if (rightChar == '}') {
|
||||
return new Range(range.start.row, range.start.column,
|
||||
range.start.row, range.end.column + 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.add("parens", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == '(') {
|
||||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "") {
|
||||
return {
|
||||
text: '(' + selected + ')',
|
||||
selection: false
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
text: '()',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
} else if (text == ')') {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == ')') {
|
||||
var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});
|
||||
if (matching !== null) {
|
||||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.add("parens", "deletion", function (state, action, editor, session, range) {
|
||||
var selected = session.doc.getTextRange(range);
|
||||
if (!range.isMultiLine() && selected == '(') {
|
||||
var line = session.doc.getLine(range.start.row);
|
||||
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
|
||||
if (rightChar == ')') {
|
||||
return new Range(range.start.row, range.start.column,
|
||||
range.start.row, range.end.column + 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == '"') {
|
||||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "") {
|
||||
return {
|
||||
text: '"' + selected + '"',
|
||||
selection: false
|
||||
}
|
||||
} else {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var leftChar = line.substring(cursor.column-1, cursor.column);
|
||||
|
||||
// We're escaped.
|
||||
if (leftChar == '\\') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find what token we're inside.
|
||||
var tokens = session.getTokens(selection.start.row, selection.start.row)[0].tokens;
|
||||
var col = 0, token;
|
||||
var quotepos = -1; // Track whether we're inside an open quote.
|
||||
|
||||
for (var x = 0; x < tokens.length; x++) {
|
||||
token = tokens[x];
|
||||
if (token.type == "string") {
|
||||
quotepos = -1;
|
||||
} else if (quotepos < 0) {
|
||||
quotepos = token.value.indexOf('"');
|
||||
}
|
||||
if ((token.value.length + col) > selection.start.column) {
|
||||
break;
|
||||
}
|
||||
col += tokens[x].value.length;
|
||||
}
|
||||
|
||||
// Try and be smart about when we auto insert.
|
||||
if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
|
||||
return {
|
||||
text: '""',
|
||||
selection: [1,1]
|
||||
}
|
||||
} else if (token && token.type === "string") {
|
||||
// Ignore input and move right one if we're typing over the closing quote.
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == '"') {
|
||||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
|
||||
var selected = session.doc.getTextRange(range);
|
||||
if (!range.isMultiLine() && selected == '"') {
|
||||
var line = session.doc.getLine(range.start.row);
|
||||
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
|
||||
if (rightChar == '"') {
|
||||
return new Range(range.start.row, range.start.column,
|
||||
range.start.row, range.end.column + 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
oop.inherits(CstyleBehaviour, Behaviour);
|
||||
|
||||
exports.CstyleBehaviour = CstyleBehaviour;
|
||||
});
|
||||
92
lib/ace/mode/behaviour/xml.js
Normal file
92
lib/ace/mode/behaviour/xml.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/* 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):
|
||||
* Chris Spencer <chris.ag.spencer AT googlemail 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 Behaviour = require('ace/mode/behaviour').Behaviour;
|
||||
var CstyleBehaviour = require('ace/mode/behaviour/cstyle').CstyleBehaviour;
|
||||
|
||||
var XmlBehaviour = function () {
|
||||
|
||||
this.inherit(CstyleBehaviour, ["string_dquotes"]); // Get string behaviour
|
||||
|
||||
this.add("brackets", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == '<') {
|
||||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "") {
|
||||
return false;
|
||||
} else {
|
||||
return {
|
||||
text: '<>',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
} else if (text == '>') {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == '>') { // need some kind of matching check here
|
||||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
}
|
||||
} else if (text == "\n") {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChars = line.substring(cursor.column, cursor.column + 2);
|
||||
if (rightChars == '</') {
|
||||
var indent = this.$getIndent(session.doc.getLine(cursor.row)) + session.getTabString();
|
||||
var next_indent = this.$getIndent(session.doc.getLine(cursor.row));
|
||||
|
||||
return {
|
||||
text: '\n' + indent + '\n' + next_indent,
|
||||
selection: [1, indent.length, 1, indent.length]
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
oop.inherits(XmlBehaviour, Behaviour);
|
||||
|
||||
exports.XmlBehaviour = XmlBehaviour;
|
||||
});
|
||||
|
|
@ -44,10 +44,12 @@ 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 CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new c_cppHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
|
||||
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|" +
|
||||
|
|
@ -73,7 +71,7 @@ var c_cppHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
|
|
@ -161,9 +159,9 @@ var c_cppHighlightRules = function() {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(c_cppHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
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;
|
||||
});
|
||||
|
|
@ -38,62 +38,88 @@
|
|||
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")
|
||||
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 WorkerClient = require("ace/worker/worker_client").WorkerClient;
|
||||
var oop = require("pilot/oop");
|
||||
|
||||
function CoffeeMode() {
|
||||
function Mode() {
|
||||
this.$tokenizer = new Tokenizer(new Rules().getRules());
|
||||
this.$outdent = new Outdent();
|
||||
};
|
||||
}
|
||||
|
||||
oop.inherits(CoffeeMode, TextMode);
|
||||
oop.inherits(Mode, 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*/;
|
||||
(function() {
|
||||
|
||||
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*/;
|
||||
|
||||
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.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);
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
var doc = session.getDocument();
|
||||
var worker = new WorkerClient(["ace", "pilot"], "worker-coffee.js", "ace/mode/coffee_worker", "Worker");
|
||||
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("error", function(e) {
|
||||
session.setAnnotations([e.data]);
|
||||
});
|
||||
|
||||
worker.on("ok", function(e) {
|
||||
session.clearAnnotations();
|
||||
});
|
||||
};
|
||||
|
||||
proto.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
|
||||
}).call(Mode.prototype);
|
||||
|
||||
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;
|
||||
exports.Mode = Mode;
|
||||
|
||||
});
|
||||
63
lib/ace/mode/coffee/coffee-script.js
Normal file
63
lib/ace/mode/coffee/coffee-script.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* ***** 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 Lexer = require("ace/mode/coffee/lexer").Lexer;
|
||||
var parser = require("ace/mode/coffee/parser");
|
||||
|
||||
var lexer = new Lexer();
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var tag, _ref2;
|
||||
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
|
||||
return tag;
|
||||
},
|
||||
setInput: function(tokens) {
|
||||
this.tokens = tokens;
|
||||
return this.pos = 0;
|
||||
},
|
||||
upcomingInput: function() {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
parser.yy = require('ace/mode/coffee/nodes');
|
||||
|
||||
exports.parse = function(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
});
|
||||
92
lib/ace/mode/coffee/helpers.js
Normal file
92
lib/ace/mode/coffee/helpers.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
* 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 OR COPYRIGHT
|
||||
* HOLDERS 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.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var extend, flatten;
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
};
|
||||
exports.ends = function(string, literal, back) {
|
||||
var len;
|
||||
len = literal.length;
|
||||
return literal === string.substr(string.length - len - (back || 0), len);
|
||||
};
|
||||
exports.compact = function(array) {
|
||||
var item, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
item = array[_i];
|
||||
if (item) {
|
||||
_results.push(item);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
exports.count = function(string, substr) {
|
||||
var num, pos;
|
||||
num = pos = 0;
|
||||
if (!substr.length) {
|
||||
return 1 / 0;
|
||||
}
|
||||
while (pos = 1 + string.indexOf(substr, pos)) {
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
exports.merge = function(options, overrides) {
|
||||
return extend(extend({}, options), overrides);
|
||||
};
|
||||
extend = exports.extend = function(object, properties) {
|
||||
var key, val;
|
||||
for (key in properties) {
|
||||
val = properties[key];
|
||||
object[key] = val;
|
||||
}
|
||||
return object;
|
||||
};
|
||||
exports.flatten = flatten = function(array) {
|
||||
var element, flattened, _i, _len;
|
||||
flattened = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
element = array[_i];
|
||||
if (element instanceof Array) {
|
||||
flattened = flattened.concat(flatten(element));
|
||||
} else {
|
||||
flattened.push(element);
|
||||
}
|
||||
}
|
||||
return flattened;
|
||||
};
|
||||
exports.del = function(obj, key) {
|
||||
var val;
|
||||
val = obj[key];
|
||||
delete obj[key];
|
||||
return val;
|
||||
};
|
||||
exports.last = function(array, back) {
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
});
|
||||
677
lib/ace/mode/coffee/lexer.js
Normal file
677
lib/ace/mode/coffee/lexer.js
Normal file
|
|
@ -0,0 +1,677 @@
|
|||
/**
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
* 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 OR COPYRIGHT
|
||||
* HOLDERS 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.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
Rewriter = require('ace/mode/coffee/rewriter').Rewriter;
|
||||
_ref = require('ace/mode/coffee/helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
|
||||
exports.Lexer = Lexer = (function() {
|
||||
function Lexer() {}
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var i;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
}
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
this.code = code;
|
||||
this.line = opts.line || 0;
|
||||
this.indent = 0;
|
||||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.tokens = [];
|
||||
i = 0;
|
||||
while (this.chunk = code.slice(i)) {
|
||||
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (opts.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
this.token('OWN', id);
|
||||
return id.length;
|
||||
}
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
|
||||
tag = 'IDENTIFIER';
|
||||
if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
} else if (tag === 'UNLESS') {
|
||||
tag = 'IF';
|
||||
} else if (__indexOf.call(UNARY, tag) >= 0) {
|
||||
tag = 'UNARY';
|
||||
} else if (__indexOf.call(RELATION, tag) >= 0) {
|
||||
if (tag !== 'INSTANCEOF' && this.seenFor) {
|
||||
tag = 'FOR' + tag;
|
||||
this.seenFor = false;
|
||||
} else {
|
||||
tag = 'RELATION';
|
||||
if (this.value() === '!') {
|
||||
this.tokens.pop();
|
||||
id = '!' + id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'IDENTIFIER';
|
||||
id = new String(id);
|
||||
id.reserved = true;
|
||||
} else if (__indexOf.call(RESERVED, id) >= 0) {
|
||||
this.identifierError(id);
|
||||
}
|
||||
}
|
||||
if (!forcedIdentifier) {
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
}
|
||||
tag = (function() {
|
||||
switch (id) {
|
||||
case '!':
|
||||
return 'UNARY';
|
||||
case '==':
|
||||
case '!=':
|
||||
return 'COMPARE';
|
||||
case '&&':
|
||||
case '||':
|
||||
return 'LOGIC';
|
||||
case 'true':
|
||||
case 'false':
|
||||
case 'null':
|
||||
case 'undefined':
|
||||
return 'BOOL';
|
||||
case 'break':
|
||||
case 'continue':
|
||||
case 'debugger':
|
||||
return 'STATEMENT';
|
||||
default:
|
||||
return tag;
|
||||
}
|
||||
})();
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) {
|
||||
this.token(':', ':');
|
||||
}
|
||||
return input.length;
|
||||
};
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
number = match[0];
|
||||
this.token('NUMBER', number);
|
||||
return number.length;
|
||||
};
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var match, string;
|
||||
switch (this.chunk.charAt(0)) {
|
||||
case "'":
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
||||
break;
|
||||
case '"':
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) {
|
||||
return 0;
|
||||
}
|
||||
if (0 < string.indexOf('#{', 1)) {
|
||||
this.interpolateString(string.slice(1, -1));
|
||||
} else {
|
||||
this.token('STRING', this.escapeLines(string));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
this.line += count(string, '\n');
|
||||
return string.length;
|
||||
};
|
||||
Lexer.prototype.heredocToken = function() {
|
||||
var doc, heredoc, match, quote;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
heredoc = match[0];
|
||||
quote = heredoc.charAt(0);
|
||||
doc = this.sanitizeHeredoc(match[2], {
|
||||
quote: quote,
|
||||
indent: null
|
||||
});
|
||||
if (quote === '"' && 0 <= doc.indexOf('#{')) {
|
||||
this.interpolateString(doc, {
|
||||
heredoc: true
|
||||
});
|
||||
} else {
|
||||
this.token('STRING', this.makeString(doc, quote, true));
|
||||
}
|
||||
this.line += count(heredoc, '\n');
|
||||
return heredoc.length;
|
||||
};
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var comment, here, match;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return 0;
|
||||
}
|
||||
comment = match[0], here = match[1];
|
||||
if (here) {
|
||||
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
|
||||
herecomment: true,
|
||||
indent: Array(this.indent + 1).join(' ')
|
||||
}));
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
this.line += count(comment, '\n');
|
||||
return comment.length;
|
||||
};
|
||||
Lexer.prototype.jsToken = function() {
|
||||
var match, script;
|
||||
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
|
||||
return 0;
|
||||
}
|
||||
this.token('JS', (script = match[0]).slice(1, -1));
|
||||
return script.length;
|
||||
};
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var match, prev, regex, _ref2;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return 0;
|
||||
}
|
||||
if (match = HEREGEX.exec(this.chunk)) {
|
||||
this.line += count(match[0], '\n');
|
||||
return this.heregexToken(match);
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
regex = match[0];
|
||||
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
|
||||
return regex.length;
|
||||
};
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
|
||||
return heregex.length;
|
||||
}
|
||||
this.token('IDENTIFIER', 'RegExp');
|
||||
this.tokens.push(['CALL_START', '(']);
|
||||
tokens = [];
|
||||
_ref2 = this.interpolateString(body, {
|
||||
regex: true
|
||||
});
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
|
||||
if (tag === 'TOKENS') {
|
||||
tokens.push.apply(tokens, value);
|
||||
} else {
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
|
||||
continue;
|
||||
}
|
||||
value = value.replace(/\\/g, '\\\\');
|
||||
tokens.push(['STRING', this.makeString(value, '"', true)]);
|
||||
}
|
||||
tokens.push(['+', '+']);
|
||||
}
|
||||
tokens.pop();
|
||||
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_ref5 = this.tokens).push.apply(_ref5, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
this.token(')', ')');
|
||||
return heregex.length;
|
||||
};
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, match, noNewlines, prev, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
indent = match[0];
|
||||
this.line += count(indent, '\n');
|
||||
prev = last(this.tokens, 1);
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
noNewlines = this.unfinished();
|
||||
if (size - this.indebt === this.indent) {
|
||||
if (noNewlines) {
|
||||
this.suppressNewlines();
|
||||
} else {
|
||||
this.newlineToken();
|
||||
}
|
||||
return indent.length;
|
||||
}
|
||||
if (size > this.indent) {
|
||||
if (noNewlines) {
|
||||
this.indebt = size - this.indent;
|
||||
this.suppressNewlines();
|
||||
return indent.length;
|
||||
}
|
||||
diff = size - this.indent + this.outdebt;
|
||||
this.token('INDENT', diff);
|
||||
this.indents.push(diff);
|
||||
this.outdebt = this.indebt = 0;
|
||||
} else {
|
||||
this.indebt = 0;
|
||||
this.outdentToken(this.indent - size, noNewlines);
|
||||
}
|
||||
this.indent = size;
|
||||
return indent.length;
|
||||
};
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
|
||||
var dent, len;
|
||||
while (moveOut > 0) {
|
||||
len = this.indents.length - 1;
|
||||
if (this.indents[len] === void 0) {
|
||||
moveOut = 0;
|
||||
} else if (this.indents[len] === this.outdebt) {
|
||||
moveOut -= this.outdebt;
|
||||
this.outdebt = 0;
|
||||
} else if (this.indents[len] < this.outdebt) {
|
||||
this.outdebt -= this.indents[len];
|
||||
moveOut -= this.indents[len];
|
||||
} else {
|
||||
dent = this.indents.pop() - this.outdebt;
|
||||
moveOut -= dent;
|
||||
this.outdebt = 0;
|
||||
this.token('OUTDENT', dent);
|
||||
}
|
||||
}
|
||||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.whitespaceToken = function() {
|
||||
var match, nline, prev;
|
||||
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
|
||||
return 0;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev) {
|
||||
prev[match ? 'spaced' : 'newLine'] = true;
|
||||
}
|
||||
if (match) {
|
||||
return match[0].length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
Lexer.prototype.newlineToken = function() {
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
value = match[0];
|
||||
if (CODE.test(value)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
} else {
|
||||
value = this.chunk.charAt(0);
|
||||
}
|
||||
tag = value;
|
||||
prev = last(this.tokens);
|
||||
if (value === '=' && prev) {
|
||||
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
|
||||
this.assignmentError();
|
||||
}
|
||||
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] += '=';
|
||||
return value.length;
|
||||
}
|
||||
}
|
||||
if (value === ';') {
|
||||
tag = 'TERMINATOR';
|
||||
} else if (__indexOf.call(MATH, value) >= 0) {
|
||||
tag = 'MATH';
|
||||
} else if (__indexOf.call(COMPARE, value) >= 0) {
|
||||
tag = 'COMPARE';
|
||||
} else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {
|
||||
tag = 'COMPOUND_ASSIGN';
|
||||
} else if (__indexOf.call(UNARY, value) >= 0) {
|
||||
tag = 'UNARY';
|
||||
} else if (__indexOf.call(SHIFT, value) >= 0) {
|
||||
tag = 'SHIFT';
|
||||
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
prev[0] = 'INDEX_SOAK';
|
||||
break;
|
||||
case '::':
|
||||
prev[0] = 'INDEX_PROTO';
|
||||
}
|
||||
}
|
||||
}
|
||||
this.token(tag, value);
|
||||
return value.length;
|
||||
};
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var attempt, herecomment, indent, match, _ref2;
|
||||
indent = options.indent, herecomment = options.herecomment;
|
||||
if (herecomment) {
|
||||
if (HEREDOC_ILLEGAL.test(doc)) {
|
||||
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) {
|
||||
return doc;
|
||||
}
|
||||
} else {
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
|
||||
indent = attempt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (indent) {
|
||||
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
}
|
||||
if (!herecomment) {
|
||||
doc = doc.replace(/^\n/, '');
|
||||
}
|
||||
return doc;
|
||||
};
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var i, stack, tok, tokens;
|
||||
if (this.tag() !== ')') {
|
||||
return this;
|
||||
}
|
||||
stack = [];
|
||||
tokens = this.tokens;
|
||||
i = tokens.length;
|
||||
tokens[--i][0] = 'PARAM_END';
|
||||
while (tok = tokens[--i]) {
|
||||
switch (tok[0]) {
|
||||
case ')':
|
||||
stack.push(tok);
|
||||
break;
|
||||
case '(':
|
||||
case 'CALL_START':
|
||||
if (stack.length) {
|
||||
stack.pop();
|
||||
} else if (tok[0] === '(') {
|
||||
tok[0] = 'PARAM_START';
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.closeIndentation = function() {
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||
};
|
||||
Lexer.prototype.balancedString = function(str, end) {
|
||||
var i, letter, prev, stack, _ref2;
|
||||
stack = [end];
|
||||
for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
|
||||
switch (letter = str.charAt(i)) {
|
||||
case '\\':
|
||||
i++;
|
||||
continue;
|
||||
case end:
|
||||
stack.pop();
|
||||
if (!stack.length) {
|
||||
return str.slice(0, i + 1);
|
||||
}
|
||||
end = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
if (end === '}' && (letter === '"' || letter === "'")) {
|
||||
stack.push(end = letter);
|
||||
} else if (end === '}' && letter === '{') {
|
||||
stack.push(end = '}');
|
||||
} else if (end === '"' && prev === '#' && letter === '{') {
|
||||
stack.push(end = '}');
|
||||
}
|
||||
prev = letter;
|
||||
}
|
||||
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
heredoc = options.heredoc, regex = options.regex;
|
||||
tokens = [];
|
||||
pi = 0;
|
||||
i = -1;
|
||||
while (letter = str.charAt(i += 1)) {
|
||||
if (letter === '\\') {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
|
||||
continue;
|
||||
}
|
||||
if (pi < i) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
}
|
||||
inner = expr.slice(1, -1);
|
||||
if (inner.length) {
|
||||
nested = new Lexer().tokenize(inner, {
|
||||
line: this.line,
|
||||
rewrite: false
|
||||
});
|
||||
nested.pop();
|
||||
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
|
||||
nested.shift();
|
||||
}
|
||||
if (len = nested.length) {
|
||||
if (len > 1) {
|
||||
nested.unshift(['(', '(']);
|
||||
nested.push([')', ')']);
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
}
|
||||
}
|
||||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if ((i > pi && pi < str.length)) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
}
|
||||
if (regex) {
|
||||
return tokens;
|
||||
}
|
||||
if (!tokens.length) {
|
||||
return this.token('STRING', '""');
|
||||
}
|
||||
if (tokens[0][0] !== 'NEOSTRING') {
|
||||
tokens.unshift(['', '']);
|
||||
}
|
||||
if (interpolated = tokens.length > 1) {
|
||||
this.token('(', '(');
|
||||
}
|
||||
for (i = 0, _len = tokens.length; i < _len; i++) {
|
||||
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
|
||||
if (i) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
if (tag === 'TOKENS') {
|
||||
(_ref4 = this.tokens).push.apply(_ref4, value);
|
||||
} else {
|
||||
this.token('STRING', this.makeString(value, '"', heredoc));
|
||||
}
|
||||
}
|
||||
if (interpolated) {
|
||||
this.token(')', ')');
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
Lexer.prototype.token = function(tag, value) {
|
||||
return this.tokens.push([tag, value, this.line]);
|
||||
};
|
||||
Lexer.prototype.tag = function(index, tag) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
|
||||
};
|
||||
Lexer.prototype.value = function(index, val) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
|
||||
};
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var prev, value;
|
||||
return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
|
||||
};
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
return str.replace(MULTILINER, heredoc ? '\\n' : '');
|
||||
};
|
||||
Lexer.prototype.makeString = function(body, quote, heredoc) {
|
||||
if (!body) {
|
||||
return quote + quote;
|
||||
}
|
||||
body = body.replace(/\\([\s\S])/g, function(match, contents) {
|
||||
if (contents === '\n' || contents === quote) {
|
||||
return contents;
|
||||
} else {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
body = body.replace(RegExp("" + quote, "g"), '\\$&');
|
||||
return quote + this.escapeLines(body, heredoc) + quote;
|
||||
};
|
||||
return Lexer;
|
||||
})();
|
||||
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
|
||||
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
|
||||
COFFEE_ALIAS_MAP = {
|
||||
and: '&&',
|
||||
or: '||',
|
||||
is: '==',
|
||||
isnt: '!=',
|
||||
not: '!',
|
||||
yes: 'true',
|
||||
no: 'false',
|
||||
on: 'true',
|
||||
off: 'false'
|
||||
};
|
||||
COFFEE_ALIASES = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
for (key in COFFEE_ALIAS_MAP) {
|
||||
_results.push(key);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
|
||||
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
|
||||
NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
WHITESPACE = /^[^\n\S]+/;
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
|
||||
CODE = /^[-=]>/;
|
||||
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
|
||||
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
|
||||
REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
|
||||
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
|
||||
HEREGEX_OMIT = /\s+(?:#.*)?/g;
|
||||
MULTILINER = /\n/g;
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)/g;
|
||||
HEREDOC_ILLEGAL = /\*\//;
|
||||
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
|
||||
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
|
||||
TRAILING_SPACES = /\s+$/;
|
||||
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
|
||||
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
|
||||
LOGIC = ['&&', '||', '&', '|', '^'];
|
||||
SHIFT = ['<<', '>>', '>>>'];
|
||||
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
|
||||
MATH = ['*', '/', '%'];
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
});
|
||||
2301
lib/ace/mode/coffee/nodes.js
Normal file
2301
lib/ace/mode/coffee/nodes.js
Normal file
File diff suppressed because it is too large
Load diff
685
lib/ace/mode/coffee/parser.js
Normal file
685
lib/ace/mode/coffee/parser.js
Normal file
File diff suppressed because one or more lines are too long
67
lib/ace/mode/coffee/parser_test.js
Normal file
67
lib/ace/mode/coffee/parser_test.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* ***** 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 assert = require("ace/test/assertions");
|
||||
var coffee = require("ace/mode/coffee/coffee-script");
|
||||
|
||||
|
||||
module.exports = {
|
||||
|
||||
"test parse valid coffee script": function() {
|
||||
coffee.parse("square = (x) -> x * x");
|
||||
},
|
||||
|
||||
"test parse invalid coffee script": function() {
|
||||
try {
|
||||
coffee.parse("a = 12 f");
|
||||
} catch (e) {
|
||||
assert.ok((e + "").indexOf("Parse error on line 1: Unexpected 'IDENTIFIER'") >= 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec();
|
||||
}
|
||||
389
lib/ace/mode/coffee/rewriter.js
Normal file
389
lib/ace/mode/coffee/rewriter.js
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
/**
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
* 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 OR COPYRIGHT
|
||||
* HOLDERS 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.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
}, __slice = Array.prototype.slice;
|
||||
exports.Rewriter = (function() {
|
||||
function Rewriter() {}
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.removeLeadingNewlines();
|
||||
this.removeMidExpressionNewlines();
|
||||
this.closeOpenCalls();
|
||||
this.closeOpenIndexes();
|
||||
this.addImplicitIndentation();
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBraces();
|
||||
this.addImplicitParentheses();
|
||||
this.ensureBalance(BALANCED_PAIRS);
|
||||
this.rewriteClosingParens();
|
||||
return this.tokens;
|
||||
};
|
||||
Rewriter.prototype.scanTokens = function(block) {
|
||||
var i, token, tokens;
|
||||
tokens = this.tokens;
|
||||
i = 0;
|
||||
while (token = tokens[i]) {
|
||||
i += block.call(this, token, i, tokens);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref2;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
};
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
tag = _ref[i][0];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
}
|
||||
};
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var _ref;
|
||||
if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === ']' || _ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var action, condition, stack, start, startIndent;
|
||||
stack = [];
|
||||
start = null;
|
||||
startIndent = 0;
|
||||
condition = function(token, i) {
|
||||
var one, tag, three, two, _ref, _ref2;
|
||||
_ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
|
||||
return false;
|
||||
}
|
||||
tag = token[0];
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var tok;
|
||||
tok = ['}', '}', token[2]];
|
||||
tok.generated = true;
|
||||
return this.tokens.splice(i, 0, tok);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var ago, idx, tag, tok, value, _ref, _ref2;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
|
||||
start = stack.pop();
|
||||
return 1;
|
||||
}
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
stack.push(['{']);
|
||||
idx = ago === '@' ? i - 2 : i - 1;
|
||||
while (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
value = new String('{');
|
||||
value.generated = true;
|
||||
tok = ['{', value, token[2]];
|
||||
tok.generated = true;
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var action, noCall;
|
||||
noCall = false;
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF') {
|
||||
noCall = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
seenSingle = false;
|
||||
seenControl = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = false;
|
||||
}
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (token.fromThen) {
|
||||
return 1;
|
||||
}
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
var post, _ref4;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));
|
||||
return 2;
|
||||
}
|
||||
if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
|
||||
tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));
|
||||
return 4;
|
||||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
indent.generated = outdent.generated = true;
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
var _ref3;
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
var condition;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var original;
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, function(token, i) {
|
||||
if (token[0] !== 'INDENT') {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
});
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.ensureBalance = function(pairs) {
|
||||
var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
|
||||
levels = {};
|
||||
openLine = {};
|
||||
_ref = this.tokens;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
token = _ref[_i];
|
||||
tag = token[0];
|
||||
for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
|
||||
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
|
||||
levels[open] |= 0;
|
||||
if (tag === open) {
|
||||
if (levels[open]++ === 0) {
|
||||
openLine[open] = token[2];
|
||||
}
|
||||
} else if (tag === close && --levels[open] < 0) {
|
||||
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (open in levels) {
|
||||
level = levels[open];
|
||||
if (level > 0) {
|
||||
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Rewriter.prototype.rewriteClosingParens = function() {
|
||||
var debt, key, stack;
|
||||
stack = [];
|
||||
debt = {};
|
||||
for (key in INVERSES) {
|
||||
debt[key] = 0;
|
||||
}
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var inv, match, mtag, oppos, tag, val, _ref;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push(token);
|
||||
return 1;
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (debt[inv = INVERSES[tag]] > 0) {
|
||||
debt[inv] -= 1;
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
match = stack.pop();
|
||||
mtag = match[0];
|
||||
oppos = INVERSES[mtag];
|
||||
if (tag === oppos) {
|
||||
return 1;
|
||||
}
|
||||
debt[mtag] += 1;
|
||||
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
|
||||
if (this.tag(i + 2) === mtag) {
|
||||
tokens.splice(i + 3, 0, val);
|
||||
stack.push(match);
|
||||
} else {
|
||||
tokens.splice(i, 0, val);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
};
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
var _ref;
|
||||
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
|
||||
};
|
||||
return Rewriter;
|
||||
})();
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
|
||||
INVERSES = {};
|
||||
EXPRESSION_START = [];
|
||||
EXPRESSION_END = [];
|
||||
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
|
||||
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
});
|
||||
145
lib/ace/mode/coffee/scope.js
Normal file
145
lib/ace/mode/coffee/scope.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
* 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 OR COPYRIGHT
|
||||
* HOLDERS 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.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
var Scope, extend, last, _ref;
|
||||
_ref = require('ace/mode/coffee/helpers'), extend = _ref.extend, last = _ref.last;
|
||||
exports.Scope = Scope = (function() {
|
||||
Scope.root = null;
|
||||
function Scope(parent, expressions, method) {
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
this.method = method;
|
||||
this.variables = [
|
||||
{
|
||||
name: 'arguments',
|
||||
type: 'arguments'
|
||||
}
|
||||
];
|
||||
this.positions = {};
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
}
|
||||
}
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
var pos;
|
||||
if (this.shared && !immediate) {
|
||||
return this.parent.add(name, type, immediate);
|
||||
}
|
||||
if (typeof (pos = this.positions[name]) === 'number') {
|
||||
return this.variables[pos].type = type;
|
||||
} else {
|
||||
return this.positions[name] = this.variables.push({
|
||||
name: name,
|
||||
type: type
|
||||
}) - 1;
|
||||
}
|
||||
};
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, 'var');
|
||||
return false;
|
||||
};
|
||||
Scope.prototype.parameter = function(name) {
|
||||
if (this.shared && this.parent.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
Scope.prototype.check = function(name, immediate) {
|
||||
var found, _ref2;
|
||||
found = !!this.type(name);
|
||||
if (found || immediate) {
|
||||
return found;
|
||||
}
|
||||
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
|
||||
};
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index : '');
|
||||
} else {
|
||||
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
}
|
||||
};
|
||||
Scope.prototype.type = function(name) {
|
||||
var v, _i, _len, _ref2;
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.name === name) {
|
||||
return v.type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
var index, temp;
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(type, index)))) {
|
||||
index++;
|
||||
}
|
||||
this.add(temp, 'var', true);
|
||||
return temp;
|
||||
};
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
Scope.prototype.hasDeclarations = function() {
|
||||
return !!this.declaredVariables().length;
|
||||
};
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref2;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
}
|
||||
}
|
||||
return realVars.sort().concat(tempVars.sort());
|
||||
};
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref2, _results;
|
||||
_ref2 = this.variables;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.type.assigned) {
|
||||
_results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
return Scope;
|
||||
})();
|
||||
});
|
||||
91
lib/ace/mode/coffee_worker.js
Normal file
91
lib/ace/mode/coffee_worker.js
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* ***** 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 Mirror = require("ace/worker/mirror").Mirror;
|
||||
var coffee = require("ace/mode/coffee/coffee-script");
|
||||
|
||||
window.addEventListener = function() {};
|
||||
|
||||
|
||||
var Worker = exports.Worker = function(sender) {
|
||||
Mirror.call(this, sender);
|
||||
this.setTimeout(200);
|
||||
};
|
||||
|
||||
oop.inherits(Worker, Mirror);
|
||||
|
||||
(function() {
|
||||
|
||||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
|
||||
try {
|
||||
coffee.parse(value);
|
||||
} catch(e) {
|
||||
var m = e.message.match(/Parse error on line (\d+): (.*)/);
|
||||
if (m) {
|
||||
this.sender.emit("error", {
|
||||
row: parseInt(m[1]) - 1,
|
||||
column: null,
|
||||
text: m[2],
|
||||
type: "error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e instanceof SyntaxError) {
|
||||
var m = e.message.match(/ on line (\d+)/);
|
||||
if (m) {
|
||||
this.sender.emit("error", {
|
||||
row: parseInt(m[1]) - 1,
|
||||
column: null,
|
||||
text: e.message.replace(m[0], ""),
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.sender.emit("ok");
|
||||
};
|
||||
|
||||
}).call(Worker.prototype);
|
||||
|
||||
});
|
||||
|
|
@ -5,10 +5,12 @@ 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 CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new CSharpHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").D
|
|||
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("|")
|
||||
);
|
||||
|
|
@ -26,7 +25,7 @@ var CSharpHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
|
|
@ -112,9 +111,9 @@ var CSharpHighlightRules = function() {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(CSharpHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ var TextMode = require("ace/mode/text").Mode;
|
|||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var CssHighlightRules = require("ace/mode/css_highlight_rules").CssHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var WorkerClient = require("ace/worker/worker_client").WorkerClient;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new CssHighlightRules().getRules());
|
||||
|
|
@ -75,6 +76,35 @@ oop.inherits(Mode, TextMode);
|
|||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
this.createWorker = function(session) {
|
||||
var doc = session.getDocument();
|
||||
var worker = new WorkerClient(["ace", "pilot"], "worker-css.js", "ace/mode/css_worker", "Worker");
|
||||
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("csslint", function(e) {
|
||||
var errors = [];
|
||||
e.data.forEach(function(message) {
|
||||
errors.push({
|
||||
row: message.line - 1,
|
||||
column: message.col - 1,
|
||||
text: message.message,
|
||||
type: message.type,
|
||||
lint: message
|
||||
});
|
||||
});
|
||||
|
||||
session.setAnnotations(errors);
|
||||
});
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
|
|
|
|||
5832
lib/ace/mode/css/csslint.js
Normal file
5832
lib/ace/mode/css/csslint.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -44,7 +44,7 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
var CssHighlightRules = function() {
|
||||
|
||||
var properties = lang.arrayToMap(
|
||||
("-moz-box-sizing|-webkit-box-sizing|azimuth|background-attachment|background-color|background-image|" +
|
||||
("-moz-box-sizing|-webkit-box-sizing|appearance|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|" +
|
||||
|
|
@ -97,7 +97,7 @@ var CssHighlightRules = function() {
|
|||
"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
|
||||
"zero").split("|")
|
||||
);
|
||||
|
||||
|
||||
var colors = lang.arrayToMap(
|
||||
("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|" +
|
||||
"purple|red|silver|teal|white|yellow").split("|")
|
||||
|
|
@ -122,12 +122,12 @@ var CssHighlightRules = function() {
|
|||
return re.join("");
|
||||
}
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
var base_ruleset = [
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
next : "ruleset_comment"
|
||||
},{
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
|
|
@ -190,12 +190,6 @@ var CssHighlightRules = function() {
|
|||
}, {
|
||||
token : "constant.numeric", // hex3 color
|
||||
regex : "#[a-fA-F0-9]{3}"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "\{"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "\}"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (properties.hasOwnProperty(value.toLowerCase())) {
|
||||
|
|
@ -215,15 +209,121 @@ var CssHighlightRules = function() {
|
|||
}
|
||||
},
|
||||
regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
|
||||
}],
|
||||
"comment" : [{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}
|
||||
];
|
||||
|
||||
var ruleset = lang.copyArray( base_ruleset );
|
||||
ruleset.unshift(
|
||||
{
|
||||
token : "rparen",
|
||||
regex : "\}",
|
||||
next: "start"
|
||||
}
|
||||
);
|
||||
|
||||
var media_ruleset = lang.copyArray( base_ruleset );
|
||||
media_ruleset.unshift(
|
||||
{
|
||||
token : "rparen",
|
||||
regex : "\}",
|
||||
next: "media"
|
||||
}
|
||||
);
|
||||
|
||||
var base_comment = [
|
||||
{
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
];
|
||||
|
||||
var comment = lang.copyArray( base_comment );
|
||||
comment.unshift(
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}
|
||||
);
|
||||
|
||||
var media_comment = lang.copyArray( base_comment );
|
||||
media_comment.unshift(
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "media"
|
||||
}
|
||||
);
|
||||
|
||||
var ruleset_comment = lang.copyArray( base_comment );
|
||||
ruleset_comment.unshift(
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "ruleset"
|
||||
}
|
||||
);
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}]
|
||||
token: "lparen",
|
||||
regex: "{",
|
||||
next: "ruleset"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "@media.*?{",
|
||||
next: "media"
|
||||
},{
|
||||
token: "keyword",
|
||||
regex: "#[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "variable",
|
||||
regex: "\\.[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "string",
|
||||
regex: ":[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "constant",
|
||||
regex: "[a-zA-Z0-9-_]+"
|
||||
}],
|
||||
|
||||
"media" : [ {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "media_comment"
|
||||
}, {
|
||||
token: "lparen",
|
||||
regex: "{",
|
||||
next: "media_ruleset"
|
||||
},{
|
||||
token: "string",
|
||||
regex: "}",
|
||||
next: "start"
|
||||
},{
|
||||
token: "keyword",
|
||||
regex: "#[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "variable",
|
||||
regex: "\\.[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "string",
|
||||
regex: ":[a-zA-Z0-9-_]+"
|
||||
},{
|
||||
token: "constant",
|
||||
regex: "[a-zA-Z0-9-_]+"
|
||||
}],
|
||||
|
||||
"comment" : comment,
|
||||
|
||||
"ruleset" : ruleset,
|
||||
"ruleset_comment" : ruleset_comment,
|
||||
|
||||
"media_ruleset" : media_ruleset,
|
||||
"media_comment" : media_comment
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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();
|
||||
},
|
||||
|
|
@ -70,10 +74,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -35,33 +35,37 @@
|
|||
*
|
||||
* ***** 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();
|
||||
},
|
||||
|
||||
"test: tokenize pixel number" : function() {
|
||||
var line = "-12px";
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
var tokens = this.tokenizer.getLineTokens(line, "ruleset").tokens;
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("constant.numeric", tokens[0].type);
|
||||
},
|
||||
|
||||
"test: tokenize hex3 color" : function() {
|
||||
var tokens = this.tokenizer.getLineTokens("#abc", "start").tokens;
|
||||
var tokens = this.tokenizer.getLineTokens("#abc", "ruleset").tokens;
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("constant.numeric", tokens[0].type);
|
||||
},
|
||||
|
||||
"test: tokenize hex6 color" : function() {
|
||||
var tokens = this.tokenizer.getLineTokens("#abc012", "start").tokens;
|
||||
var tokens = this.tokenizer.getLineTokens("#abc012", "ruleset").tokens;
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("constant.numeric", tokens[0].type);
|
||||
|
|
@ -77,18 +81,15 @@ var Test = {
|
|||
},
|
||||
|
||||
"test for last rule in ruleset to catch capturing group bugs" : function() {
|
||||
var tokens = this.tokenizer.getLineTokens("top", "start").tokens;
|
||||
var tokens = this.tokenizer.getLineTokens("top", "ruleset").tokens;
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("support.type", tokens[0].type);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test, "css tokenizer");
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
62
lib/ace/mode/css_worker.js
Normal file
62
lib/ace/mode/css_worker.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* ***** 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 Mirror = require("ace/worker/mirror").Mirror;
|
||||
var CSSLint = require("ace/mode/css/csslint").CSSLint;
|
||||
|
||||
var Worker = exports.Worker = function(sender) {
|
||||
Mirror.call(this, sender);
|
||||
this.setTimeout(200);
|
||||
};
|
||||
|
||||
oop.inherits(Worker, Mirror);
|
||||
|
||||
(function() {
|
||||
|
||||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
|
||||
result = CSSLint.verify(value);
|
||||
this.sender.emit("csslint", result.messages);
|
||||
};
|
||||
|
||||
}).call(Worker.prototype);
|
||||
|
||||
});
|
||||
74
lib/ace/mode/css_worker_test.js
Normal file
74
lib/ace/mode/css_worker_test.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/* ***** 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 assert = require("ace/test/assertions");
|
||||
var Worker = require("ace/mode/css_worker").Worker;
|
||||
|
||||
|
||||
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 Worker(this.sender);
|
||||
worker.setValue("Juhu Kinners");
|
||||
worker.deferredUpdate.call();
|
||||
assert.equal(this.sender.events[0][1][0].type, "error");
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec();
|
||||
}
|
||||
|
|
@ -44,15 +44,11 @@ var DocCommentHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
token : "comment.doc", // closing comment
|
||||
regex : "\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment.doc.tag",
|
||||
regex : "@[\\w\\d_]+" // TODO: fix email addresses
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
regex : "\s+"
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
regex : "TODO"
|
||||
|
|
@ -77,6 +73,14 @@ oop.inherits(DocCommentHighlightRules, TextHighlightRules);
|
|||
next: start
|
||||
};
|
||||
};
|
||||
|
||||
this.getEndRule = function (start) {
|
||||
return {
|
||||
token : "comment.doc", // closing comment
|
||||
regex : "\\*\\/",
|
||||
next : start
|
||||
};
|
||||
};
|
||||
|
||||
}).call(DocCommentHighlightRules.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,56 +43,33 @@ var JavaScriptMode = require("ace/mode/javascript").Mode;
|
|||
var CssMode = require("ace/mode/css").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var HtmlHighlightRules = require("ace/mode/html_highlight_rules").HtmlHighlightRules;
|
||||
var XmlBehaviour = require("ace/mode/behaviour/xml").XmlBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new HtmlHighlightRules().getRules());
|
||||
|
||||
this.$js = new JavaScriptMode();
|
||||
this.$css = new CssMode();
|
||||
var highlighter = new HtmlHighlightRules();
|
||||
this.$tokenizer = new Tokenizer(highlighter.getRules());
|
||||
this.$behaviour = new XmlBehaviour();
|
||||
|
||||
this.$embeds = highlighter.getEmbeds();
|
||||
this.createModeDelegates({
|
||||
"js-": JavaScriptMode,
|
||||
"css-": CssMode
|
||||
});
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
this.$delegate("toggleCommentLines", arguments, function() {
|
||||
return 0;
|
||||
});
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var self = this;
|
||||
return this.$delegate("getNextLineIndent", arguments, function() {
|
||||
return self.$getIndent(line);
|
||||
});
|
||||
return this.$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);
|
||||
}
|
||||
|
||||
var split = state.split("css-");
|
||||
if (!split[0] && split[1]) {
|
||||
args[0] = split[1];
|
||||
return this.$css[method].apply(this.$css, args);
|
||||
}
|
||||
|
||||
return defaultHandler ? defaultHandler() : undefined;
|
||||
return false;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -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("style")),
|
||||
|
||||
tag : [ {
|
||||
token : "text",
|
||||
|
|
@ -125,14 +143,15 @@ var HtmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
|
||||
}].concat(string("tag")),
|
||||
|
||||
"style-qstring": multiLineString("'", "style"),
|
||||
"style-qqstring": multiLineString('"', "style"),
|
||||
"script-qstring": multiLineString("'", "script"),
|
||||
"script-qqstring": multiLineString('"', "script"),
|
||||
"tag-qstring": multiLineString("'", "tag"),
|
||||
"tag-qqstring": multiLineString('"', "tag"),
|
||||
|
||||
cdata : [ {
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
|
|
@ -154,10 +173,8 @@ var HtmlHighlightRules = function() {
|
|||
regex : ".+"
|
||||
} ]
|
||||
};
|
||||
|
||||
var jsRules = new JavaScriptHighlightRules().getRules();
|
||||
this.addRules(jsRules, "js-");
|
||||
this.$rules["js-start"].unshift({
|
||||
|
||||
this.embedRules(JavaScriptHighlightRules, "js-", [{
|
||||
token: "comment",
|
||||
regex: "\\/\\/.*(?=<\\/script>)",
|
||||
next: "tag"
|
||||
|
|
@ -165,15 +182,13 @@ var HtmlHighlightRules = function() {
|
|||
token: "text",
|
||||
regex: "<\\/(?=script)",
|
||||
next: "tag"
|
||||
});
|
||||
|
||||
var cssRules = new CssHighlightRules().getRules();
|
||||
this.addRules(cssRules, "css-");
|
||||
this.$rules["css-start"].unshift({
|
||||
}]);
|
||||
|
||||
this.embedRules(CssHighlightRules, "css-", [{
|
||||
token: "text",
|
||||
regex: "<\\/(?=style)",
|
||||
next: "tag"
|
||||
});
|
||||
}]);
|
||||
};
|
||||
|
||||
oop.inherits(HtmlHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -35,14 +35,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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();
|
||||
},
|
||||
|
|
@ -62,10 +66,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
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("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -5,10 +5,12 @@ 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 CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new JavaHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, JavaScriptMode);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
|
||||
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|" +
|
||||
|
|
@ -66,7 +64,7 @@ var JavaHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
|
|
@ -156,9 +154,9 @@ var JavaHighlightRules = function() {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(JavaHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ var JavaScriptHighlightRules = require("ace/mode/javascript_highlight_rules").Ja
|
|||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
var WorkerClient = require("ace/worker/worker_client").WorkerClient;
|
||||
var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
|
|
@ -146,10 +148,9 @@ oop.inherits(Mode, TextMode);
|
|||
text: error.reason,
|
||||
type: "warning",
|
||||
lint: error
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
session.setAnnotations(errors)
|
||||
session.setAnnotations(errors);
|
||||
});
|
||||
|
||||
worker.on("narcissus", function(e) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -44,11 +45,10 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
|
||||
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(
|
||||
|
|
@ -56,8 +56,8 @@ var JavaScriptHighlightRules = function() {
|
|||
);
|
||||
|
||||
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.
|
||||
|
|
@ -69,7 +69,7 @@ var JavaScriptHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
|
|
@ -166,9 +166,9 @@ var JavaScriptHighlightRules = function() {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -35,14 +35,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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();
|
||||
},
|
||||
|
|
@ -144,10 +148,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
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();
|
||||
},
|
||||
|
|
@ -106,10 +110,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
|
|
@ -26,7 +25,7 @@ oop.inherits(JavaScriptWorker, Mirror);
|
|||
} catch(e) {
|
||||
// console.log("narcissus")
|
||||
// console.log(e);
|
||||
sender.emit("narcissus", {
|
||||
this.sender.emit("narcissus", {
|
||||
row: e.lineno-1,
|
||||
column: null, // TODO convert e.cursor
|
||||
text: e.message,
|
||||
|
|
|
|||
81
lib/ace/mode/javascript_worker_test.js
Normal file
81
lib/ace/mode/javascript_worker_test.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/* ***** 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 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();
|
||||
}
|
||||
85
lib/ace/mode/json.js
Normal file
85
lib/ace/mode/json.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* ***** 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var HighlightRules = require("ace/mode/json_highlight_rules").JsonHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new HighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
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 (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;
|
||||
});
|
||||
87
lib/ace/mode/json_highlight_rules.js
Normal file
87
lib/ace/mode/json_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>
|
||||
* 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 oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var JsonHighlightRules = function() {
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
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 : "invalid.illegal", // single quoted strings are not allowed
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "invalid.illegal", // comments are not allowed
|
||||
regex : "\\/\\/.*$"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
oop.inherits(JsonHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.JsonHighlightRules = JsonHighlightRules;
|
||||
});
|
||||
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;
|
||||
});
|
||||
|
|
@ -43,10 +43,12 @@ var Tokenizer = require("ace/tokenizer").Tokenizer;
|
|||
var PhpHighlightRules = require("ace/mode/php_highlight_rules").PhpHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("ace/range").Range;
|
||||
var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new PhpHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").D
|
|||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var PhpHighlightRules = function() {
|
||||
|
||||
var docComment = new DocCommentHighlightRules();
|
||||
|
||||
|
||||
var builtinFunctions = lang.arrayToMap(
|
||||
('abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|' +
|
||||
'aggregate_methods_by_list|aggregate_methods_by_regexp|aggregate_properties|aggregate_properties_by_list|' +
|
||||
|
|
@ -476,7 +474,7 @@ var PhpHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : "#.*$"
|
||||
},
|
||||
docComment.getStartRule("doc-start"),
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
|
|
@ -544,7 +542,7 @@ var PhpHighlightRules = 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";
|
||||
},
|
||||
|
|
@ -596,9 +594,9 @@ var PhpHighlightRules = function() {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.addRules(docComment.getRules(), "doc-");
|
||||
this.$rules["doc-start"][0].next = "start";
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(PhpHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
83
lib/ace/mode/scss.js
Normal file
83
lib/ace/mode/scss.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* ***** 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 TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var ScssHighlightRules = require("ace/mode/scss_highlight_rules").ScssHighlightRules;
|
||||
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new ScssHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
// ignore braces in comments
|
||||
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
});
|
||||
358
lib/ace/mode/scss_highlight_rules.js
Normal file
358
lib/ace/mode/scss_highlight_rules.js
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/* ***** 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 lang = require("pilot/lang");
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var ScssHighlightRules = function() {
|
||||
|
||||
var properties = lang.arrayToMap( (function () {
|
||||
|
||||
var browserPrefix = ("-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-").split("|");
|
||||
|
||||
var prefixProperties = ("appearance|background-clip|background-inline-policy|background-origin|" +
|
||||
"background-size|binding|border-bottom-colors|border-left-colors|" +
|
||||
"border-right-colors|border-top-colors|border-end|border-end-color|" +
|
||||
"border-end-style|border-end-width|border-image|border-start|" +
|
||||
"border-start-color|border-start-style|border-start-width|box-align|" +
|
||||
"box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|" +
|
||||
"box-pack|box-sizing|column-count|column-gap|column-width|column-rule|" +
|
||||
"column-rule-width|column-rule-style|column-rule-color|float-edge|" +
|
||||
"font-feature-settings|font-language-override|force-broken-image-icon|" +
|
||||
"image-region|margin-end|margin-start|opacity|outline|outline-color|" +
|
||||
"outline-offset|outline-radius|outline-radius-bottomleft|" +
|
||||
"outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|" +
|
||||
"outline-style|outline-width|padding-end|padding-start|stack-sizing|" +
|
||||
"tab-size|text-blink|text-decoration-color|text-decoration-line|" +
|
||||
"text-decoration-style|transform|transform-origin|transition|" +
|
||||
"transition-delay|transition-duration|transition-property|" +
|
||||
"transition-timing-function|user-focus|user-input|user-modify|user-select|" +
|
||||
"window-shadow|border-radius").split("|");
|
||||
|
||||
var properties = ("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|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|" +
|
||||
"letter-spacing|line-height|list-style-image|list-style-position|" +
|
||||
"list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
|
||||
"margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
|
||||
"min-width|opacity|orphans|outline-color|" +
|
||||
"outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
|
||||
"padding-left|padding-right|padding-top|padding|page-break-after|" +
|
||||
"page-break-before|page-break-inside|page|pause-after|pause-before|" +
|
||||
"pause|pitch-range|pitch|play-during|position|quotes|richness|right|" +
|
||||
"size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
|
||||
"stress|table-layout|text-align|text-decoration|text-indent|" +
|
||||
"text-shadow|text-transform|top|unicode-bidi|vertical-align|" +
|
||||
"visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
|
||||
"z-index").split("|");
|
||||
|
||||
//The return array
|
||||
var ret = [];
|
||||
|
||||
//All prefixProperties will get the browserPrefix in
|
||||
//the begning by join the prefixProperties array with the value of browserPrefix
|
||||
for (var i=0, ln=browserPrefix.length; i<ln; i++) {
|
||||
Array.prototype.push.apply(
|
||||
ret,
|
||||
(( browserPrefix[i] + prefixProperties.join("|" + browserPrefix[i]) ).split("|"))
|
||||
);
|
||||
}
|
||||
|
||||
//Add also prefixProperties and properties without any browser prefix
|
||||
Array.prototype.push.apply(ret, prefixProperties);
|
||||
Array.prototype.push.apply(ret, properties);
|
||||
|
||||
return ret;
|
||||
|
||||
})() );
|
||||
|
||||
|
||||
|
||||
var functions = lang.arrayToMap(
|
||||
("hsl|hsla|rgb|rgba|url|attr|counter|counters|abs|adjust_color|adjust_hue|" +
|
||||
"alpha|join|blue|ceil|change_color|comparable|complement|darken|desaturate|" +
|
||||
"floor|grayscale|green|hue|if|invert|join|length|lighten|lightness|mix|" +
|
||||
"nth|opacify|opacity|percentage|quote|red|round|saturate|saturation|" +
|
||||
"scale_color|transparentize|type_of|unit|unitless|unqoute").split("|")
|
||||
);
|
||||
|
||||
var constants = lang.arrayToMap(
|
||||
("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
|
||||
"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|" +
|
||||
"hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
|
||||
"ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
|
||||
"ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
|
||||
"inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
|
||||
"keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
|
||||
"lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
|
||||
"medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
|
||||
"nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
|
||||
"overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
|
||||
"ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
|
||||
"solid|square|static|strict|super|sw-resize|table-footer-group|" +
|
||||
"table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
|
||||
"transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
|
||||
"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
|
||||
"zero").split("|")
|
||||
);
|
||||
|
||||
var colors = lang.arrayToMap(
|
||||
("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|" +
|
||||
"purple|red|silver|teal|white|yellow").split("|")
|
||||
);
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare").split("|")
|
||||
)
|
||||
|
||||
var tags = lang.arrayToMap(
|
||||
("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|" +
|
||||
"big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|" +
|
||||
"command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|" +
|
||||
"figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" +
|
||||
"header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|" +
|
||||
"link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|" +
|
||||
"option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|" +
|
||||
"small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|" +
|
||||
"textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
|
||||
|
||||
function ic(str) {
|
||||
var re = [];
|
||||
var chars = str.split("");
|
||||
for (var i=0; i<chars.length; i++) {
|
||||
re.push(
|
||||
"[",
|
||||
chars[i].toLowerCase(),
|
||||
chars[i].toUpperCase(),
|
||||
"]"
|
||||
);
|
||||
}
|
||||
return re.join("");
|
||||
}
|
||||
|
||||
|
||||
// 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 : "\\/\\*",
|
||||
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",
|
||||
regex : numRe + ic("em")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("ex")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("px")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("cm")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("mm")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("in")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("pt")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("pc")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("deg")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("rad")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("grad")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("ms")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("s")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("hz")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + ic("khz")
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + "%"
|
||||
}, {
|
||||
token : "constant.numeric", // hex6 color
|
||||
regex : "#[a-fA-F0-9]{6}"
|
||||
}, {
|
||||
token : "constant.numeric", // hex3 color
|
||||
regex : "#[a-fA-F0-9]{3}"
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (properties.hasOwnProperty(value.toLowerCase()))
|
||||
return "support.type";
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (constants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (functions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (colors.hasOwnProperty(value.toLowerCase()))
|
||||
return "support.constant.color";
|
||||
else if (tags.hasOwnProperty(value.toLowerCase()))
|
||||
return "variable.language";
|
||||
else
|
||||
return "text";
|
||||
},
|
||||
regex : "\\-?[@a-zA-Z_][@a-zA-Z0-9_\\-]*"
|
||||
}, {
|
||||
token : "variable",
|
||||
regex : "[a-zA-Z_\\-$][a-zA-Z0-9_\\-$]*\\b"
|
||||
}, {
|
||||
token: "variable.language",
|
||||
regex: "#[a-zA-Z0-9-_]+"
|
||||
}, {
|
||||
token: "variable.language",
|
||||
regex: "\\.[a-zA-Z0-9-_]+"
|
||||
}, {
|
||||
token: "variable.language",
|
||||
regex: ":[a-zA-Z0-9-_]+"
|
||||
}, {
|
||||
token: "constant",
|
||||
regex: "[a-zA-Z0-9-_]+"
|
||||
}, {
|
||||
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 : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
oop.inherits(ScssHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.ScssHighlightRules = ScssHighlightRules;
|
||||
|
||||
});
|
||||
|
|
@ -42,10 +42,17 @@ 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 XmlBehaviour = require("ace/mode/behaviour/xml").XmlBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new SvgHighlightRules().getRules());
|
||||
this.$js = new JavaScriptMode();
|
||||
this.highlighter = new SvgHighlightRules();
|
||||
this.$tokenizer = new Tokenizer(this.highlighter.getRules());
|
||||
this.$behaviour = new XmlBehaviour();
|
||||
|
||||
this.$embeds = this.highlighter.getEmbeds();
|
||||
this.createModeDelegates({
|
||||
"js-": JavaScriptMode
|
||||
});
|
||||
};
|
||||
|
||||
oop.inherits(Mode, XmlMode);
|
||||
|
|
@ -53,38 +60,15 @@ oop.inherits(Mode, XmlMode);
|
|||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
this.$delegate("toggleCommentLines", arguments, function() {
|
||||
return 0;
|
||||
});
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var self = this;
|
||||
return this.$delegate("getNextLineIndent", arguments, function() {
|
||||
return self.$getIndent(line);
|
||||
});
|
||||
return this.$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;
|
||||
return false;
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -65,11 +65,9 @@ var SvgHighlightRules = function() {
|
|||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
}];
|
||||
|
||||
var jsRules = new JavaScriptHighlightRules().getRules();
|
||||
this.addRules(jsRules, "js-");
|
||||
this.$rules["js-start"].unshift({
|
||||
}];
|
||||
|
||||
this.embedRules(JavaScriptHighlightRules, "js-", [{
|
||||
token: "comment",
|
||||
regex: "\\/\\/.*(?=<\\/script>)",
|
||||
next: "tag"
|
||||
|
|
@ -77,7 +75,7 @@ var SvgHighlightRules = function() {
|
|||
token: "text",
|
||||
regex: "<\\/(?=script)",
|
||||
next: "tag"
|
||||
});
|
||||
}]);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Mihai Sucan <mihai DOT sucan AT gmail DOT com>
|
||||
* Chris Spencer <chris.ag.spencer AT googlemail 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
|
||||
|
|
@ -41,9 +42,11 @@ define(function(require, exports, module) {
|
|||
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
var Behaviour = require("ace/mode/behaviour").Behaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());
|
||||
this.$behaviour = new Behaviour();
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
|
@ -140,7 +143,63 @@ var Mode = function() {
|
|||
|
||||
editor.session.$selectionOccurrences = [];
|
||||
};
|
||||
|
||||
this.createModeDelegates = function (mapping) {
|
||||
if (!this.$embeds) {
|
||||
return;
|
||||
}
|
||||
this.$modes = {};
|
||||
for (var i = 0; i < this.$embeds.length; i++) {
|
||||
if (mapping[this.$embeds[i]]) {
|
||||
this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]]();
|
||||
}
|
||||
}
|
||||
|
||||
var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction'];
|
||||
|
||||
for (var i = 0; i < delegations.length; i++) {
|
||||
(function(scope) {
|
||||
var functionName = delegations[i];
|
||||
var defaultHandler = scope[functionName];
|
||||
scope[delegations[i]] = function() {
|
||||
return this.$delegator(functionName, arguments, defaultHandler);
|
||||
}
|
||||
} (this));
|
||||
}
|
||||
}
|
||||
|
||||
this.$delegator = function(method, args, defaultHandler) {
|
||||
var state = args[0];
|
||||
|
||||
for (var i = 0; i < this.$embeds.length; i++) {
|
||||
if (!this.$modes[this.$embeds[i]]) continue;
|
||||
|
||||
var split = state.split(this.$embeds[i]);
|
||||
if (!split[0] && split[1]) {
|
||||
args[0] = split[1];
|
||||
var mode = this.$modes[this.$embeds[i]];
|
||||
return mode[method].apply(mode, args);
|
||||
}
|
||||
}
|
||||
var ret = defaultHandler.apply(this, args);
|
||||
return defaultHandler ? ret : undefined;
|
||||
};
|
||||
|
||||
this.transformAction = function(state, action, editor, session, param) {
|
||||
if (this.$behaviour) {
|
||||
var behaviours = this.$behaviour.getBehaviours();
|
||||
for (var key in behaviours) {
|
||||
if (behaviours[key][action]) {
|
||||
var ret = behaviours[key][action].apply(this, arguments);
|
||||
if (ret !== false) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var lang = require("pilot/lang");
|
||||
|
||||
var TextHighlightRules = function() {
|
||||
|
||||
// regexp must not have capturing parentheses
|
||||
|
|
@ -73,6 +75,34 @@ var TextHighlightRules = function() {
|
|||
this.getRules = function() {
|
||||
return this.$rules;
|
||||
};
|
||||
|
||||
this.embedRules = function (HighlightRules, prefix, escapeRules, states) {
|
||||
var embedRules = new HighlightRules().getRules();
|
||||
if (states) {
|
||||
for (var i = 0; i < states.length; i++) {
|
||||
states[i] = prefix + states[i];
|
||||
}
|
||||
} else {
|
||||
states = [];
|
||||
for (var key in embedRules) {
|
||||
states.push(prefix + key);
|
||||
}
|
||||
}
|
||||
this.addRules(embedRules, prefix);
|
||||
|
||||
for (var i = 0; i < states.length; i++) {
|
||||
Array.prototype.unshift.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
|
||||
}
|
||||
|
||||
if (!this.$embeds) {
|
||||
this.$embeds = [];
|
||||
}
|
||||
this.$embeds.push(prefix);
|
||||
}
|
||||
|
||||
this.getEmbeds = function() {
|
||||
return this.$embeds;
|
||||
}
|
||||
|
||||
}).call(TextHighlightRules.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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();
|
||||
},
|
||||
|
|
@ -59,10 +63,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -41,9 +41,11 @@ var oop = require("pilot/oop");
|
|||
var TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var XmlHighlightRules = require("ace/mode/xml_highlight_rules").XmlHighlightRules;
|
||||
var XmlBehaviour = require("ace/mode/behaviour/xml").XmlBehaviour;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new XmlHighlightRules().getRules());
|
||||
this.$behaviour = new XmlBehaviour();
|
||||
};
|
||||
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
|
|
|||
|
|
@ -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 : "\\]\\]>",
|
||||
|
|
|
|||
|
|
@ -35,14 +35,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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();
|
||||
},
|
||||
|
|
@ -70,10 +74,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
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("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ var MouseHandler = function(editor) {
|
|||
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));
|
||||
|
|
@ -73,7 +73,7 @@ var MouseHandler = function(editor) {
|
|||
this.setScrollSpeed = function(speed) {
|
||||
this.$scrollSpeed = speed;
|
||||
};
|
||||
|
||||
|
||||
this.getScrollSpeed = function() {
|
||||
return this.$scrollSpeed;
|
||||
};
|
||||
|
|
@ -100,7 +100,7 @@ var MouseHandler = function(editor) {
|
|||
var selectionEmpty = selectionRange.isEmpty();
|
||||
var state = STATE_UNKNOWN;
|
||||
var inSelection = false;
|
||||
|
||||
|
||||
var button = event.getButton(e);
|
||||
if (button !== 0) {
|
||||
if (selectionEmpty) {
|
||||
|
|
@ -112,6 +112,13 @@ var MouseHandler = function(editor) {
|
|||
}
|
||||
return;
|
||||
} else {
|
||||
// Select the fold as the user clicks it.
|
||||
var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
|
||||
if (fold) {
|
||||
editor.selection.setSelectionRange(fold.range);
|
||||
return;
|
||||
}
|
||||
|
||||
inSelection = !editor.getReadOnly()
|
||||
&& !selectionEmpty
|
||||
&& selectionRange.contains(pos.row, pos.column);
|
||||
|
|
@ -123,25 +130,23 @@ var MouseHandler = function(editor) {
|
|||
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;
|
||||
};
|
||||
|
|
@ -174,7 +179,7 @@ var MouseHandler = function(editor) {
|
|||
|
||||
editor.selection.setSelectionRange(newRange);
|
||||
};
|
||||
|
||||
|
||||
var onSelectionInterval = function() {
|
||||
if (mousePageX === undefined || mousePageY === undefined)
|
||||
return;
|
||||
|
|
@ -183,7 +188,7 @@ var MouseHandler = function(editor) {
|
|||
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);
|
||||
|
|
@ -199,13 +204,13 @@ var MouseHandler = function(editor) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (state == STATE_DRAG)
|
||||
onDragSelectionInterval();
|
||||
else if (state == STATE_SELECT)
|
||||
onUpdateSelectionInterval();
|
||||
};
|
||||
|
||||
|
||||
function onStartSelect(pos) {
|
||||
if (e.shiftKey)
|
||||
editor.selection.selectToPosition(pos)
|
||||
|
|
@ -217,12 +222,12 @@ var MouseHandler = function(editor) {
|
|||
}
|
||||
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) {
|
||||
if (self.$clickSelection.contains(cursor.row, cursor.column)) {
|
||||
editor.selection.setSelectionRange(self.$clickSelection);
|
||||
} else {
|
||||
|
|
@ -238,7 +243,7 @@ var MouseHandler = function(editor) {
|
|||
else {
|
||||
editor.selection.selectToPosition(cursor);
|
||||
}
|
||||
|
||||
|
||||
editor.renderer.scrollCursorIntoView();
|
||||
};
|
||||
|
||||
|
|
@ -252,32 +257,40 @@ var MouseHandler = function(editor) {
|
|||
|
||||
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
|
||||
var timerId = setInterval(onSelectionInterval, 20);
|
||||
|
||||
|
||||
return event.preventDefault(e);
|
||||
};
|
||||
|
||||
|
||||
this.onMouseDoubleClick = function(e) {
|
||||
var editor = this.editor;
|
||||
var pos = this.$getEventPosition(e);
|
||||
this.editor.moveCursorToPosition(pos);
|
||||
this.editor.selection.selectWord();
|
||||
this.$clickSelection = this.editor.getSelectionRange();
|
||||
|
||||
// If the user dclicked on a fold, then expand it.
|
||||
var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
|
||||
if (fold) {
|
||||
editor.session.expandFold(fold);
|
||||
} else {
|
||||
editor.moveCursorToPosition(pos);
|
||||
editor.selection.selectWord();
|
||||
this.$clickSelection = 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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -281,6 +281,8 @@ Tokenizer.prototype = {
|
|||
|
||||
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");
|
||||
|
|
|
|||
140
lib/ace/range.js
140
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 = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -161,10 +168,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -63,7 +63,16 @@ var RenderLoop = function(onRender) {
|
|||
}
|
||||
};
|
||||
|
||||
if (window.postMessage) {
|
||||
this.setTimeoutZero = window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame;
|
||||
|
||||
if (this.setTimeoutZero) {
|
||||
|
||||
this.setTimeoutZero = this.setTimeoutZero.bind(window)
|
||||
} else if (window.postMessage) {
|
||||
|
||||
this.messageName = "zero-timeout-message";
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var EditSession = require("ace/edit_session").EditSession,
|
||||
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({
|
||||
|
|
@ -390,10 +394,8 @@ var Test = {
|
|||
},
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test)
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec();
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -247,9 +247,19 @@ var Selection = function(session) {
|
|||
};
|
||||
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -262,8 +272,12 @@ var Selection = function(session) {
|
|||
};
|
||||
|
||||
this.moveCursorLeft = function() {
|
||||
var cursor = this.selectionLead.getPosition();
|
||||
if (cursor.column == 0) {
|
||||
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);
|
||||
|
|
@ -279,7 +293,11 @@ var Selection = function(session) {
|
|||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -298,25 +316,38 @@ var Selection = function(session) {
|
|||
var row = this.selectionLead.row;
|
||||
var column = this.selectionLead.column;
|
||||
var screenRow = this.session.documentToScreenRow(row, column);
|
||||
var firstRowColumn = this.session.getScreenFirstRowColumn(screenRow);
|
||||
var beforeCursor = this.doc.getLine(row).slice(firstRowColumn, 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) {
|
||||
var lastRowColumn = this.session.getDocumentLastRowColumn(row, column);
|
||||
leadingSpace = this.doc.getLine(row).
|
||||
substring(firstRowColumn, lastRowColumn).
|
||||
match(/^\s*/);
|
||||
this.moveCursorTo(row, firstRowColumn + leadingSpace[0].length);
|
||||
} else if (leadingSpace[0].length >= column) {
|
||||
this.moveCursorTo(row, firstRowColumn);
|
||||
if (leadingSpace[0].length == 0
|
||||
|| leadingSpace[0].length >= column - firstColumnPosition.column)
|
||||
{
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row, firstColumnPosition.column);
|
||||
} else {
|
||||
this.moveCursorTo(row, firstRowColumn + leadingSpace[0].length);
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row,
|
||||
firstColumnPosition.column + leadingSpace[0].length);
|
||||
}
|
||||
};
|
||||
|
||||
this.moveCursorLineEnd = function() {
|
||||
var lead = this.selectionLead;
|
||||
this.moveCursorTo(lead.row, this.session.getDocumentLastRowColumn(lead.row, lead.column));
|
||||
var lastRowColumnPosition =
|
||||
this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
|
||||
this.moveCursorTo(
|
||||
lastRowColumnPosition.row,
|
||||
lastRowColumnPosition.column
|
||||
);
|
||||
};
|
||||
|
||||
this.moveCursorFileEnd = function() {
|
||||
|
|
@ -339,7 +370,11 @@ var Selection = function(session) {
|
|||
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;
|
||||
}
|
||||
|
|
@ -358,18 +393,29 @@ var Selection = function(session) {
|
|||
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.session.nonTokenRe.lastIndex = 0;
|
||||
this.session.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.session.nonTokenRe.exec(leftOfCursor)) {
|
||||
|
||||
var str = this.session.getFoldStringAt(row, column, -1);
|
||||
if (str == null) {
|
||||
str = this.doc.getLine(row).substring(0, column)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -397,6 +443,12 @@ var Selection = function(session) {
|
|||
};
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -35,12 +35,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var EditSession = require("ace/edit_session").EditSession,
|
||||
assert = require("./assertions");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
var Test = {
|
||||
module.exports = {
|
||||
createSession : function(rows, cols) {
|
||||
var line = new Array(cols + 1).join("a");
|
||||
var text = new Array(rows).join(line + "\n") + line;
|
||||
|
|
@ -326,10 +330,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
295
lib/ace/split.js
Normal file
295
lib/ace/split.js
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/* 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
|
||||
* Julian Viereck <julian.viereck@gmail.com>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var Renderer = require("ace/virtual_renderer").VirtualRenderer;
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
|
||||
var Split = function(container, theme, splits) {
|
||||
this.BELOW = 1;
|
||||
this.BESIDE = 0;
|
||||
|
||||
this.$container = container;
|
||||
this.$theme = theme;
|
||||
this.$splits = 0;
|
||||
this.$editorCSS = "";
|
||||
this.$editors = [];
|
||||
this.$oriantation = this.BESIDE;
|
||||
|
||||
this.setSplits(splits || 1);
|
||||
this.$cEditor = this.$editors[0];
|
||||
|
||||
|
||||
this.on("focus", function(editor) {
|
||||
this.$cEditor = editor;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
(function(){
|
||||
|
||||
oop.implement(this, EventEmitter);
|
||||
|
||||
this.$createEditor = function() {
|
||||
var dom = document.createElement("div");
|
||||
dom.className = this.$editorCSS;
|
||||
dom.style = "position: absolute; top:0px; bottom:0px";
|
||||
this.$container.appendChild(dom);
|
||||
var session = new EditSession("");
|
||||
var editor = new Editor(new Renderer(dom, this.$theme));
|
||||
|
||||
editor.on("focus", function() {
|
||||
this._emit("focus", editor);
|
||||
}.bind(this));
|
||||
|
||||
this.$editors.push(editor);
|
||||
editor.setFontSize(this.$fontSize);
|
||||
return editor;
|
||||
};
|
||||
|
||||
this.setSplits = function(splits) {
|
||||
var editor;
|
||||
if (splits < 1) {
|
||||
throw "The number of splits have to be > 0!";
|
||||
}
|
||||
|
||||
if (splits == this.$splits) {
|
||||
return;
|
||||
} else if (splits > this.$splits) {
|
||||
while (this.$splits < this.$editors.length && this.$splits < splits) {
|
||||
editor = this.$editors[this.$splits];
|
||||
this.$container.appendChild(editor.container);
|
||||
editor.setFontSize(this.$fontSize);
|
||||
this.$splits ++;
|
||||
}
|
||||
while (this.$splits < splits) {
|
||||
this.$createEditor();
|
||||
this.$splits ++;
|
||||
}
|
||||
} else {
|
||||
while (this.$splits > splits) {
|
||||
editor = this.$editors[this.$splits - 1];
|
||||
this.$container.removeChild(editor.container);
|
||||
this.$splits --;
|
||||
}
|
||||
}
|
||||
this.resize();
|
||||
};
|
||||
|
||||
this.getSplits = function() {
|
||||
return this.$splits;
|
||||
};
|
||||
|
||||
this.getEditor = function(idx) {
|
||||
return this.$editors[idx];
|
||||
};
|
||||
|
||||
this.getCurrentEditor = function() {
|
||||
return this.$cEditor;
|
||||
};
|
||||
|
||||
this.focus = function() {
|
||||
this.$cEditor.focus();
|
||||
};
|
||||
|
||||
this.blur = function() {
|
||||
this.$cEditor.blur();
|
||||
};
|
||||
|
||||
this.setTheme = function(theme) {
|
||||
this.$editors.forEach(function(editor) {
|
||||
editor.setTheme(theme);
|
||||
});
|
||||
};
|
||||
|
||||
this.setKeyboardHandler = function(keybinding) {
|
||||
this.$editors.forEach(function(editor) {
|
||||
editor.setKeyboardHandler(keybinding);
|
||||
});
|
||||
};
|
||||
|
||||
this.forEach = function(callback, scope) {
|
||||
this.$editors.forEach(callback, scope);
|
||||
};
|
||||
|
||||
this.setFontSize = function(size) {
|
||||
this.$fontSize = size;
|
||||
this.forEach(function(editor) {
|
||||
editor.setFontSize(size);
|
||||
});
|
||||
};
|
||||
|
||||
this.$cloneSession = function(session) {
|
||||
var s = new EditSession(session.getDocument(), session.getMode());
|
||||
|
||||
var undoManager = session.getUndoManager();
|
||||
if (undoManager) {
|
||||
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
|
||||
s.setUndoManager(undoManagerProxy);
|
||||
}
|
||||
|
||||
// Overwrite the default $informUndoManager function such that new delas
|
||||
// aren't added to the undo manager from the new and the old session.
|
||||
s.$informUndoManager = lang.deferredCall(function() { s.$deltas = []; });
|
||||
|
||||
// Copy over 'settings' from the session.
|
||||
s.setTabSize(session.getTabSize());
|
||||
s.setUseSoftTabs(session.getUseSoftTabs());
|
||||
s.setOverwrite(session.getOverwrite());
|
||||
s.setBreakpoints(session.getBreakpoints());
|
||||
s.setUseWrapMode(session.getUseWrapMode());
|
||||
s.setUseWorker(session.getUseWorker());
|
||||
s.setWrapLimitRange(session.$wrapLimitRange.min,
|
||||
session.$wrapLimitRange.max);
|
||||
s.$foldData = session.$cloneFoldData();
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
this.setSession = function(session, idx) {
|
||||
var editor
|
||||
if (idx == null) {
|
||||
editor = this.$cEditor;
|
||||
} else {
|
||||
editor = this.$editors[idx];
|
||||
}
|
||||
|
||||
// Check if the session is used already by any of the editors in the
|
||||
// split. If it is, we have to clone the session as two editors using
|
||||
// the same session can cause terrible side effects (e.g. UndoQueue goes
|
||||
// wrong). This also gives the user of Split the possibility to treat
|
||||
// each session on each split editor different.
|
||||
var isUsed = this.$editors.some(function(editor) {
|
||||
return editor.session === session;
|
||||
});
|
||||
|
||||
if (isUsed) {
|
||||
session = this.$cloneSession(session);
|
||||
}
|
||||
editor.setSession(session);
|
||||
|
||||
// Return the session set on the editor. This might be a cloned one.
|
||||
return session;
|
||||
};
|
||||
|
||||
this.getOriantation = function() {
|
||||
return this.$oriantation;
|
||||
};
|
||||
|
||||
this.setOriantation = function(oriantation) {
|
||||
if (this.$oriantation == oriantation) {
|
||||
return;
|
||||
}
|
||||
this.$oriantation = oriantation;
|
||||
this.resize();
|
||||
};
|
||||
|
||||
this.resize = function() {
|
||||
var width = this.$container.clientWidth;
|
||||
var height = this.$container.clientHeight;
|
||||
var editor;
|
||||
|
||||
if (this.$oriantation == this.BESIDE) {
|
||||
var editorWidth = width / this.$splits;
|
||||
for (var i = 0; i < this.$splits; i++) {
|
||||
editor = this.$editors[i];
|
||||
editor.container.style.width = editorWidth + "px";
|
||||
editor.container.style.top = "0px";
|
||||
editor.container.style.left = i * editorWidth + "px";
|
||||
editor.container.style.height = height + "px";
|
||||
editor.resize();
|
||||
}
|
||||
} else {
|
||||
var editorHeight = height / this.$splits;
|
||||
for (var i = 0; i < this.$splits; i++) {
|
||||
editor = this.$editors[i];
|
||||
editor.container.style.width = width + "px";
|
||||
editor.container.style.top = i * editorHeight + "px";
|
||||
editor.container.style.left = "0px";
|
||||
editor.container.style.height = editorHeight + "px";
|
||||
editor.resize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}).call(Split.prototype);
|
||||
|
||||
function UndoManagerProxy(undoManager, session) {
|
||||
this.$u = undoManager;
|
||||
this.$doc = session;
|
||||
}
|
||||
|
||||
(function() {
|
||||
this.execute = function(options) {
|
||||
this.$u.execute(options);
|
||||
};
|
||||
|
||||
this.undo = function() {
|
||||
var selectionRange = this.$u.undo(true);
|
||||
if (selectionRange) {
|
||||
this.$doc.selection.setSelectionRange(selectionRange);
|
||||
}
|
||||
};
|
||||
|
||||
this.redo = function() {
|
||||
var selectionRange = this.$u.redo(true);
|
||||
if (selectionRange) {
|
||||
this.$doc.selection.setSelectionRange(selectionRange);
|
||||
}
|
||||
};
|
||||
|
||||
this.reset = function() {
|
||||
this.$u.reset();
|
||||
};
|
||||
|
||||
this.hasUndo = function() {
|
||||
return this.$u.hasUndo();
|
||||
};
|
||||
|
||||
this.hasRedo = function() {
|
||||
return this.$u.hasRedo();
|
||||
};
|
||||
}).call(UndoManagerProxy.prototype);
|
||||
|
||||
exports.Split = Split;
|
||||
});
|
||||
|
|
@ -37,28 +37,5 @@
|
|||
|
||||
require("../../../support/paths");
|
||||
|
||||
require("./mockdom");
|
||||
var async = require("asyncjs");
|
||||
|
||||
async.concat(
|
||||
require("./anchor_test"),
|
||||
require("./change_document_test"),
|
||||
require("./document_test"),
|
||||
require("./edit_session_test"),
|
||||
require("./event_emitter_test"),
|
||||
require("./navigation_test"),
|
||||
require("./range_test"),
|
||||
require("./search_test"),
|
||||
require("./selection_test"),
|
||||
require("./text_edit_test"),
|
||||
require("./highlight_selected_word_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()
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
require("pilot/fixoldbrowsers");
|
||||
var AsyncTest = require("asyncjs/test");
|
||||
var async = require("asyncjs");
|
||||
var dom = require("pilot/dom");
|
||||
|
||||
|
|
@ -8,48 +9,57 @@ var passed = 0
|
|||
var failed = 0
|
||||
var log = document.getElementById("log")
|
||||
|
||||
async.concat(
|
||||
require("./anchor_test"),
|
||||
require("./change_document_test"),
|
||||
require("./document_test"),
|
||||
require("./edit_session_test"),
|
||||
require("./event_emitter_test"),
|
||||
require("./navigation_test"),
|
||||
require("./range_test"),
|
||||
require("./search_test"),
|
||||
require("./selection_test"),
|
||||
require("./text_edit_test"),
|
||||
require("./virtual_renderer_test"),
|
||||
require("./highlight_selected_word_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")
|
||||
)
|
||||
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);
|
||||
|
||||
|
|
@ -71,6 +81,9 @@ async.concat(
|
|||
(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);
|
||||
})
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -270,6 +270,46 @@ exports.Generator = function(source) {
|
|||
})
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,361 +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 EditSession = require("ace/edit_session").EditSession,
|
||||
Editor = require("../editor").Editor,
|
||||
UndoManager = require("ace/undomanager").UndoManager,
|
||||
MockRenderer = require("./mockrenderer"),
|
||||
Range = require("ace/range").Range,
|
||||
assert = require("./assertions"),
|
||||
async = require("asyncjs");
|
||||
|
||||
var Test = {
|
||||
|
||||
"test: find matching opening bracket" : function() {
|
||||
var session = new EditSession(["(()(", "())))"]);
|
||||
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 3}), 0, 1);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 2}), 1, 0);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 3);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 4}), 0, 0);
|
||||
assert.equal(session.findMatchingBracket({row: 1, column: 5}), null);
|
||||
},
|
||||
|
||||
"test: find matching closing bracket" : function() {
|
||||
var session = new EditSession(["(()(", "())))"]);
|
||||
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 4}), 1, 2);
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 2}), 0, 2);
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 3);
|
||||
assert.equal(session.findMatchingBracket({row: 0, column: 0}), null);
|
||||
},
|
||||
|
||||
"test: match different bracket types" : function() {
|
||||
var session = new EditSession(["({[", ")]}"]);
|
||||
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 0);
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 2}), 1, 2);
|
||||
assert.position(session.findMatchingBracket({row: 0, column: 3}), 1, 1);
|
||||
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 1}), 0, 0);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 2}), 0, 2);
|
||||
assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 1);
|
||||
},
|
||||
|
||||
"test: move lines down" : function() {
|
||||
var session = new EditSession(["a1", "a2", "a3", "a4"]);
|
||||
|
||||
session.moveLinesDown(0, 1);
|
||||
assert.equal(session.getValue(), ["a3", "a1", "a2", "a4"].join("\n"));
|
||||
|
||||
session.moveLinesDown(1, 2);
|
||||
assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
session.moveLinesDown(2, 3);
|
||||
assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
session.moveLinesDown(2, 2);
|
||||
assert.equal(session.getValue(), ["a3", "a4", "a2", "a1"].join("\n"));
|
||||
},
|
||||
|
||||
"test: move lines up" : function() {
|
||||
var session = new EditSession(["a1", "a2", "a3", "a4"]);
|
||||
|
||||
session.moveLinesUp(2, 3);
|
||||
assert.equal(session.getValue(), ["a1", "a3", "a4", "a2"].join("\n"));
|
||||
|
||||
session.moveLinesUp(1, 2);
|
||||
assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
session.moveLinesUp(0, 1);
|
||||
assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
|
||||
|
||||
session.moveLinesUp(2, 2);
|
||||
assert.equal(session.getValue(), ["a3", "a1", "a4", "a2"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate lines" : function() {
|
||||
var session = new EditSession(["1", "2", "3", "4"]);
|
||||
|
||||
session.duplicateLines(1, 2);
|
||||
assert.equal(session.getValue(), ["1", "2", "3", "2", "3", "4"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate last line" : function() {
|
||||
var session = new EditSession(["1", "2", "3"]);
|
||||
|
||||
session.duplicateLines(2, 2);
|
||||
assert.equal(session.getValue(), ["1", "2", "3", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: duplicate first line" : function() {
|
||||
var session = new EditSession(["1", "2", "3"]);
|
||||
|
||||
session.duplicateLines(0, 0);
|
||||
assert.equal(session.getValue(), ["1", "1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: convert document to screen coordinates" : function() {
|
||||
var session = new EditSession("01234\t567890\t1234");
|
||||
session.setTabSize(4);
|
||||
|
||||
assert.equal(session.documentToScreenColumn(0, 0), 0);
|
||||
assert.equal(session.documentToScreenColumn(0, 4), 4);
|
||||
assert.equal(session.documentToScreenColumn(0, 5), 5);
|
||||
assert.equal(session.documentToScreenColumn(0, 6), 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;
|
||||
var splits = EditSession.prototype.$computeWrapSplits(line, 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"));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test);
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("../../../support/paths");
|
||||
exports.exec()
|
||||
}
|
||||
|
|
@ -35,17 +35,21 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
EventEmitter = require("pilot/event_emitter").EventEmitter,
|
||||
assert = require("./assertions");
|
||||
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,5 +64,8 @@ var Test = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = require("asyncjs/test").testcase(Test)
|
||||
});
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
var dom = require('jsdom/level2/html').dom.level2.html;
|
||||
var browser = require('jsdom/browser/index').windowAugmentation(dom);
|
||||
var dom = require('jsdom/lib/jsdom/level2/html').dom.level2.html;
|
||||
var browser = require('jsdom/lib/jsdom/browser/index').windowAugmentation(dom);
|
||||
|
||||
global.document = browser.document;
|
||||
global.window = browser.window;
|
||||
|
|
|
|||
200
lib/ace/theme/solarized_dark.js
Normal file
200
lib/ace/theme/solarized_dark.js
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/* ***** 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 dom = require("pilot/dom");
|
||||
|
||||
var cssText = ".ace-solarized-dark .ace_editor {\
|
||||
border: 2px solid rgb(159, 159, 159);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_editor.ace_focus {\
|
||||
border: 2px solid #327fbd;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_gutter {\
|
||||
width: 50px;\
|
||||
background: #e8e8e8;\
|
||||
color: #333;\
|
||||
overflow : hidden;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_gutter-layer {\
|
||||
width: 100%;\
|
||||
text-align: right;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_gutter-layer .ace_gutter-cell {\
|
||||
padding-right: 6px;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_print_margin {\
|
||||
width: 1px;\
|
||||
background: #e8e8e8;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_scroller {\
|
||||
background-color: #002B36;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_text-layer {\
|
||||
cursor: text;\
|
||||
color: #93A1A1;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_cursor {\
|
||||
border-left: 2px solid #D30102;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_cursor.ace_overwrite {\
|
||||
border-left: 0px;\
|
||||
border-bottom: 1px solid #D30102;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_marker-layer .ace_selection {\
|
||||
background: #073642;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_marker-layer .ace_step {\
|
||||
background: rgb(198, 219, 174);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_marker-layer .ace_bracket {\
|
||||
margin: -1px 0 0 -1px;\
|
||||
border: 1px solid rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_marker-layer .ace_active_line {\
|
||||
background: #073642;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
.ace-solarized-dark .ace_invisible {\
|
||||
color: rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_keyword {\
|
||||
color:#859900;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_keyword.ace_operator {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_constant {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_constant.ace_language {\
|
||||
color:#B58900;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_constant.ace_library {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_constant.ace_numeric {\
|
||||
color:#D33682;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_invalid {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_invalid.ace_illegal {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_invalid.ace_deprecated {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_support {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_support.ace_function {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_function.ace_buildin {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_string {\
|
||||
color:#2AA198;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_string.ace_regexp {\
|
||||
color:#D30102;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_comment {\
|
||||
font-style:italic;\
|
||||
color:#657B83;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_comment.ace_doc {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_comment.ace_doc.ace_tag {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_variable {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_variable.ace_language {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_xml_pe {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_collab.ace_user1 {\
|
||||
\
|
||||
}";
|
||||
|
||||
// import CSS once
|
||||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-solarized-dark";
|
||||
});
|
||||
199
lib/ace/theme/solarized_light.js
Normal file
199
lib/ace/theme/solarized_light.js
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/* ***** 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 dom = require("pilot/dom");
|
||||
|
||||
var cssText = ".ace-solarized-light .ace_editor {\
|
||||
border: 2px solid rgb(159, 159, 159);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_editor.ace_focus {\
|
||||
border: 2px solid #327fbd;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_gutter {\
|
||||
width: 50px;\
|
||||
background: #e8e8e8;\
|
||||
color: #333;\
|
||||
overflow : hidden;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_gutter-layer {\
|
||||
width: 100%;\
|
||||
text-align: right;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_gutter-layer .ace_gutter-cell {\
|
||||
padding-right: 6px;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_print_margin {\
|
||||
width: 1px;\
|
||||
background: #e8e8e8;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_scroller {\
|
||||
background-color: #FDF6E3;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_text-layer {\
|
||||
cursor: text;\
|
||||
color: #586E75;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_cursor {\
|
||||
border-left: 2px solid #000000;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_cursor.ace_overwrite {\
|
||||
border-left: 0px;\
|
||||
border-bottom: 1px solid #000000;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_marker-layer .ace_selection {\
|
||||
background: #073642;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_marker-layer .ace_step {\
|
||||
background: rgb(198, 219, 174);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_marker-layer .ace_bracket {\
|
||||
margin: -1px 0 0 -1px;\
|
||||
border: 1px solid rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_marker-layer .ace_active_line {\
|
||||
background: #EEE8D5;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
.ace-solarized-light .ace_invisible {\
|
||||
color: rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_keyword {\
|
||||
color:#859900;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_keyword.ace_operator {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_constant {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_constant.ace_language {\
|
||||
color:#B58900;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_constant.ace_library {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_constant.ace_numeric {\
|
||||
color:#D33682;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_invalid {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_invalid.ace_illegal {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_invalid.ace_deprecated {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_support {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_support.ace_function {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_function.ace_buildin {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_string {\
|
||||
color:#2AA198;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_string.ace_regexp {\
|
||||
color:#D30102;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_comment {\
|
||||
color:#93A1A1;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_comment.ace_doc {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_comment.ace_doc.ace_tag {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_variable {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_variable.ace_language {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_xml_pe {\
|
||||
\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_collab.ace_user1 {\
|
||||
\
|
||||
}";
|
||||
|
||||
// import CSS once
|
||||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-solarized-light";
|
||||
});
|
||||
|
|
@ -106,6 +106,11 @@ define(function(require, exports, module) {
|
|||
color: white;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_fold {\
|
||||
background-color: #E4E4E4;\
|
||||
border-radius: 3px;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_support.ace_function {\
|
||||
color: rgb(60, 76, 114);\
|
||||
}\
|
||||
|
|
|
|||
|
|
@ -41,13 +41,32 @@ var Tokenizer = function(rules) {
|
|||
this.rules = rules;
|
||||
|
||||
this.regExps = {};
|
||||
this.matchMappings = {};
|
||||
for ( var key in this.rules) {
|
||||
var rule = this.rules[key];
|
||||
var state = rule;
|
||||
var ruleRegExps = [];
|
||||
|
||||
for ( var i = 0; i < state.length; i++)
|
||||
ruleRegExps.push(state[i].regex);
|
||||
var matchTotal = 0;
|
||||
var mapping = this.matchMappings[key] = {};
|
||||
|
||||
for ( var i = 0; i < state.length; i++) {
|
||||
// Count number of matching groups. 2 extra groups from the full match
|
||||
// And the catch-all on the end (used to force a match);
|
||||
var matchcount = new RegExp("(?:(" + state[i].regex + ")|(.))").exec("a").length - 2;
|
||||
|
||||
// Replace any backreferences and offset appropriately.
|
||||
var adjustedregex = state[i].regex.replace(/\\([0-9]+)/g, function (match, digit) {
|
||||
return "\\" + (parseInt(digit, 10) + matchTotal + 1);
|
||||
});
|
||||
|
||||
mapping[matchTotal] = {
|
||||
rule: i,
|
||||
len: matchcount
|
||||
};
|
||||
matchTotal += matchcount;
|
||||
|
||||
ruleRegExps.push(adjustedregex);
|
||||
}
|
||||
|
||||
this.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", "g");
|
||||
|
||||
|
|
@ -59,34 +78,40 @@ var Tokenizer = function(rules) {
|
|||
this.getLineTokens = function(line, startState) {
|
||||
var currentState = startState;
|
||||
var state = this.rules[currentState];
|
||||
var mapping = this.matchMappings[currentState];
|
||||
var re = this.regExps[currentState];
|
||||
re.lastIndex = 0;
|
||||
|
||||
|
||||
var match, tokens = [];
|
||||
|
||||
|
||||
var lastIndex = 0;
|
||||
|
||||
|
||||
var token = {
|
||||
type: null,
|
||||
value: ""
|
||||
};
|
||||
|
||||
|
||||
while (match = re.exec(line)) {
|
||||
var type = "text";
|
||||
var value = match[0];
|
||||
var value = [match[0]];
|
||||
|
||||
for ( var i = 0; i < state.length; i++) {
|
||||
if (match[i + 1]) {
|
||||
var rule = state[i];
|
||||
for ( var i = 0; i < match.length-2; i++) {
|
||||
if (match[i + 1] !== undefined) {
|
||||
var rule = state[mapping[i].rule];
|
||||
|
||||
if (mapping[i].len > 1) {
|
||||
value = match.slice(i+2, i+1+mapping[i].len);
|
||||
}
|
||||
|
||||
if (typeof rule.token == "function")
|
||||
type = rule.token(match[0]);
|
||||
type = rule.token.apply(this, value);
|
||||
else
|
||||
type = rule.token;
|
||||
|
||||
if (rule.next && rule.next !== currentState) {
|
||||
currentState = rule.next;
|
||||
state = this.rules[currentState];
|
||||
mapping = this.matchMappings[currentState];
|
||||
lastIndex = re.lastIndex;
|
||||
|
||||
re = this.regExps[currentState];
|
||||
|
|
@ -96,17 +121,26 @@ var Tokenizer = function(rules) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
if (token.type !== type) {
|
||||
if (token.type)
|
||||
tokens.push(token);
|
||||
if (typeof type == "string") {
|
||||
if (typeof value != "string") {
|
||||
value = [value.join("")];
|
||||
}
|
||||
type = [type];
|
||||
}
|
||||
|
||||
for ( var i = 0; i < value.length; i++) {
|
||||
if (token.type !== type[i]) {
|
||||
if (token.type) {
|
||||
tokens.push(token);
|
||||
}
|
||||
|
||||
token = {
|
||||
type: type,
|
||||
value: value
|
||||
};
|
||||
} else {
|
||||
token.value += value;
|
||||
token = {
|
||||
type: type[i],
|
||||
value: value[i]
|
||||
}
|
||||
} else {
|
||||
token.value += value[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (lastIndex == line.length)
|
||||
|
|
|
|||
|
|
@ -49,24 +49,31 @@ var UndoManager = function() {
|
|||
var deltas = options.args[0];
|
||||
this.$doc = options.args[1];
|
||||
this.$undoStack.push(deltas);
|
||||
this.$redoStack = [];
|
||||
};
|
||||
|
||||
this.undo = function() {
|
||||
this.undo = function(dontSelect) {
|
||||
var deltas = this.$undoStack.pop();
|
||||
var undoSelectionRange = null;
|
||||
if (deltas) {
|
||||
this.$doc.undoChanges(deltas);
|
||||
undoSelectionRange =
|
||||
this.$doc.undoChanges(deltas, dontSelect);
|
||||
this.$redoStack.push(deltas);
|
||||
}
|
||||
return undoSelectionRange;
|
||||
};
|
||||
|
||||
this.redo = function() {
|
||||
this.redo = function(dontSelect) {
|
||||
var deltas = this.$redoStack.pop();
|
||||
var redoSelectionRange = null;
|
||||
if (deltas) {
|
||||
this.$doc.redoChanges(deltas);
|
||||
redoSelectionRange =
|
||||
this.$doc.redoChanges(deltas, dontSelect);
|
||||
this.$undoStack.push(deltas);
|
||||
}
|
||||
return redoSelectionRange;
|
||||
};
|
||||
|
||||
|
||||
this.reset = function() {
|
||||
this.$undoStack = [];
|
||||
this.$redoStack = [];
|
||||
|
|
|
|||
|
|
@ -201,13 +201,15 @@ var VirtualRenderer = function(container, theme) {
|
|||
*/
|
||||
this.onResize = function(force) {
|
||||
var changes = this.CHANGE_SIZE;
|
||||
var size = this.$size;
|
||||
|
||||
var height = dom.getInnerHeight(this.container);
|
||||
if (force || this.$size.height != height) {
|
||||
this.$size.height = height;
|
||||
if (force || size.height != height) {
|
||||
size.height = height;
|
||||
|
||||
this.scroller.style.height = height + "px";
|
||||
this.scrollBar.setHeight(this.scroller.clientHeight);
|
||||
size.scrollerHeight = this.scroller.clientHeight;
|
||||
this.scrollBar.setHeight(size.scrollerHeight);
|
||||
|
||||
if (this.session) {
|
||||
this.scrollToY(this.getScrollTop());
|
||||
|
|
@ -216,31 +218,25 @@ var VirtualRenderer = function(container, theme) {
|
|||
}
|
||||
|
||||
var width = dom.getInnerWidth(this.container);
|
||||
if (force || this.$size.width != width) {
|
||||
this.$size.width = width;
|
||||
if (force || size.width != width) {
|
||||
size.width = width;
|
||||
|
||||
var gutterWidth = this.showGutter ? this.$gutter.offsetWidth : 0;
|
||||
this.scroller.style.left = gutterWidth + "px";
|
||||
this.scroller.style.width = Math.max(0, width - gutterWidth - this.scrollBar.getWidth()) + "px";
|
||||
size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth())
|
||||
this.scroller.style.width = size.scrollerWidth + "px";
|
||||
|
||||
if (this.session.getUseWrapMode()) {
|
||||
var availableWidth = this.scroller.clientWidth - this.$padding * 2;
|
||||
var limit = Math.floor(availableWidth / this.characterWidth) - 1;
|
||||
if (this.session.adjustWrapLimit(limit) || force) {
|
||||
changes = changes | this.CHANGE_FULL;
|
||||
}
|
||||
}
|
||||
if (this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
|
||||
changes = changes | this.CHANGE_FULL;
|
||||
}
|
||||
|
||||
this.$size.scrollerWidth = this.scroller.clientWidth;
|
||||
this.$size.scrollerHeight = this.scroller.clientHeight;
|
||||
this.$loop.schedule(changes);
|
||||
};
|
||||
|
||||
this.setTokenizer = function(tokenizer) {
|
||||
this.$tokenizer = tokenizer;
|
||||
this.$textLayer.setTokenizer(tokenizer);
|
||||
this.$loop.schedule(this.CHANGE_TEXT);
|
||||
this.adjustWrapLimit = function(){
|
||||
var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
|
||||
var limit = Math.floor(availableWidth / this.characterWidth) - 1;
|
||||
return this.session.adjustWrapLimit(limit);
|
||||
};
|
||||
|
||||
this.$onGutterClick = function(e) {
|
||||
|
|
@ -281,10 +277,10 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.getPrintMarginColumn = function() {
|
||||
return this.$printMarginColumn;
|
||||
};
|
||||
|
||||
|
||||
this.getShowGutter = function(){
|
||||
return this.showGutter;
|
||||
}
|
||||
};
|
||||
|
||||
this.setShowGutter = function(show){
|
||||
if(this.showGutter === show)
|
||||
|
|
@ -292,10 +288,10 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$gutter.style.display = show ? "block" : "none";
|
||||
this.showGutter = show;
|
||||
this.onResize(true);
|
||||
}
|
||||
};
|
||||
|
||||
this.$updatePrintMargin = function() {
|
||||
var containerEl
|
||||
var containerEl;
|
||||
|
||||
if (!this.$showPrintMargin && !this.$printMarginEl)
|
||||
return;
|
||||
|
|
@ -303,7 +299,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
if (!this.$printMarginEl) {
|
||||
containerEl = dom.createElement("div");
|
||||
containerEl.className = "ace_print_margin_layer";
|
||||
this.$printMarginEl = dom.createElement("div")
|
||||
this.$printMarginEl = dom.createElement("div");
|
||||
this.$printMarginEl.className = "ace_print_margin";
|
||||
containerEl.appendChild(this.$printMarginEl);
|
||||
this.content.insertBefore(containerEl, this.$textLayer.element);
|
||||
|
|
@ -350,8 +346,8 @@ var VirtualRenderer = function(container, theme) {
|
|||
if (!this.layerConfig)
|
||||
return 0;
|
||||
|
||||
return this.layerConfig.firstRow + (this.layerConfig.offset == 0 ? 0 : 1);
|
||||
}
|
||||
return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
|
||||
};
|
||||
|
||||
this.getLastFullyVisibleRow = function() {
|
||||
if (!this.layerConfig)
|
||||
|
|
@ -359,7 +355,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight);
|
||||
return this.layerConfig.firstRow - 1 + flint;
|
||||
}
|
||||
};
|
||||
|
||||
this.getLastVisibleRow = function() {
|
||||
return (this.layerConfig || {}).lastRow || 0;
|
||||
|
|
@ -375,7 +371,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
this.getHScrollBarAlwaysVisible = function() {
|
||||
return this.$horizScrollAlwaysVisible;
|
||||
}
|
||||
};
|
||||
|
||||
this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
|
||||
if (this.$horizScrollAlwaysVisible != alwaysVisible) {
|
||||
|
|
@ -383,19 +379,19 @@ var VirtualRenderer = function(container, theme) {
|
|||
if (!this.$horizScrollAlwaysVisible || !this.$horizScroll)
|
||||
this.$loop.schedule(this.CHANGE_SCROLL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.onScroll = function(e) {
|
||||
this.scrollToY(e.data);
|
||||
};
|
||||
|
||||
this.$updateScrollBar = function() {
|
||||
this.scrollBar.setInnerHeight(this.session.getScreenLength() * this.lineHeight);
|
||||
this.scrollBar.setInnerHeight(this.layerConfig.maxHeight);
|
||||
this.scrollBar.setScrollTop(this.scrollTop);
|
||||
};
|
||||
|
||||
this.$renderChanges = function(changes) {
|
||||
if (!changes || !this.session || !this.$tokenizer)
|
||||
if (!changes || !this.session)
|
||||
return;
|
||||
|
||||
// text, scrolling and resize changes can cause the view port size to change
|
||||
|
|
@ -411,12 +407,12 @@ var VirtualRenderer = function(container, theme) {
|
|||
// full
|
||||
if (changes & this.CHANGE_FULL) {
|
||||
this.$textLayer.update(this.layerConfig);
|
||||
this.showGutter && this.$gutterLayer.update(this.layerConfig);
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(this.layerConfig);
|
||||
this.$markerBack.update(this.layerConfig);
|
||||
this.$markerFront.update(this.layerConfig);
|
||||
this.$cursorLayer.update(this.layerConfig);
|
||||
this.$updateScrollBar();
|
||||
this.scrollCursorIntoView();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -426,7 +422,9 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$textLayer.update(this.layerConfig);
|
||||
else
|
||||
this.$textLayer.scrollLines(this.layerConfig);
|
||||
this.showGutter && this.$gutterLayer.update(this.layerConfig);
|
||||
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(this.layerConfig);
|
||||
this.$markerBack.update(this.layerConfig);
|
||||
this.$markerFront.update(this.layerConfig);
|
||||
this.$cursorLayer.update(this.layerConfig);
|
||||
|
|
@ -436,14 +434,17 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
if (changes & this.CHANGE_TEXT) {
|
||||
this.$textLayer.update(this.layerConfig);
|
||||
this.showGutter && this.$gutterLayer.update(this.layerConfig);
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(this.layerConfig);
|
||||
}
|
||||
else if (changes & this.CHANGE_LINES) {
|
||||
this.$updateLines();
|
||||
this.$updateScrollBar();
|
||||
this.showGutter && this.$gutterLayer.update(this.layerConfig);
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(this.layerConfig);
|
||||
} else if (changes & this.CHANGE_GUTTER) {
|
||||
this.showGutter && this.$gutterLayer.update(this.layerConfig);
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(this.layerConfig);
|
||||
}
|
||||
|
||||
if (changes & this.CHANGE_CURSOR)
|
||||
|
|
@ -476,6 +477,9 @@ var VirtualRenderer = function(container, theme) {
|
|||
if (horizScrollChanged)
|
||||
this.scroller.style.overflowX = horizScroll ? "scroll" : "hidden";
|
||||
|
||||
var maxHeight = this.session.getScreenLength() * this.lineHeight;
|
||||
this.scrollTop = Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight));
|
||||
|
||||
var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
|
||||
var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
|
||||
var lastRow = firstRow + lineCount;
|
||||
|
|
@ -483,17 +487,25 @@ var VirtualRenderer = function(container, theme) {
|
|||
// Map lines on the screen to lines in the document.
|
||||
var firstRowScreen, firstRowHeight;
|
||||
var lineHeight = { lineHeight: this.lineHeight };
|
||||
firstRow = session.screenToDocumentRow(firstRow);
|
||||
firstRowScreen = session.documentToScreenRow(firstRow);
|
||||
firstRow = session.screenToDocumentRow(firstRow, 0);
|
||||
|
||||
// Check if firstRow is inside of a foldLine. If true, then use the first
|
||||
// row of the foldLine.
|
||||
var foldLine = session.getFoldLine(firstRow);
|
||||
if (foldLine) {
|
||||
firstRow = foldLine.start.row;
|
||||
}
|
||||
|
||||
firstRowScreen = session.documentToScreenRow(firstRow, 0);
|
||||
firstRowHeight = session.getRowHeight(lineHeight, firstRow);
|
||||
|
||||
lastRow = Math.min(session.screenToDocumentRow(lastRow), session.getLength() - 1);
|
||||
lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);
|
||||
minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+
|
||||
firstRowHeight;
|
||||
|
||||
offset = this.scrollTop - firstRowScreen * this.lineHeight;
|
||||
|
||||
var layerConfig = this.layerConfig = {
|
||||
this.layerConfig = {
|
||||
width : longestLine,
|
||||
padding : this.$padding,
|
||||
firstRow : firstRow,
|
||||
|
|
@ -502,15 +514,25 @@ var VirtualRenderer = function(container, theme) {
|
|||
lineHeight : this.lineHeight,
|
||||
characterWidth : this.characterWidth,
|
||||
minHeight : minHeight,
|
||||
maxHeight : maxHeight,
|
||||
offset : offset,
|
||||
height : this.$size.scrollerHeight
|
||||
};
|
||||
|
||||
// For debugging.
|
||||
// console.log(JSON.stringify(this.layerConfig));
|
||||
|
||||
this.$gutterLayer.element.style.marginTop = (-offset) + "px";
|
||||
this.content.style.marginTop = (-offset) + "px";
|
||||
this.content.style.width = longestLine + "px";
|
||||
this.content.style.height = minHeight + "px";
|
||||
|
||||
// scroller.scrollWidth was smaller than scrollLeft we needed
|
||||
if (this.$desiredScrollLeft) {
|
||||
this.scrollToX(this.$desiredScrollLeft);
|
||||
this.$desiredScrollLeft = 0;
|
||||
}
|
||||
|
||||
// Horizontal scrollbar visibility may have changed, which changes
|
||||
// the client height of the scroller
|
||||
if (horizScrollChanged)
|
||||
|
|
@ -533,7 +555,8 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
// if the last row is unknown -> redraw everything
|
||||
if (lastRow === Infinity) {
|
||||
this.showGutter && this.$gutterLayer.update(layerConfig);
|
||||
if (this.showGutter)
|
||||
this.$gutterLayer.update(layerConfig);
|
||||
this.$textLayer.update(layerConfig);
|
||||
return;
|
||||
}
|
||||
|
|
@ -563,12 +586,12 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.addGutterDecoration = function(row, className){
|
||||
this.$gutterLayer.addGutterDecoration(row, className);
|
||||
this.$loop.schedule(this.CHANGE_GUTTER);
|
||||
}
|
||||
};
|
||||
|
||||
this.removeGutterDecoration = function(row, className){
|
||||
this.$gutterLayer.removeGutterDecoration(row, className);
|
||||
this.$loop.schedule(this.CHANGE_GUTTER);
|
||||
}
|
||||
};
|
||||
|
||||
this.setBreakpoints = function(rows) {
|
||||
this.$gutterLayer.setBreakpoints(rows);
|
||||
|
|
@ -596,33 +619,33 @@ var VirtualRenderer = function(container, theme) {
|
|||
// the editor is not visible
|
||||
if (this.$size.scrollerHeight === 0)
|
||||
return;
|
||||
|
||||
|
||||
var pos = this.$cursorLayer.getPixelPosition();
|
||||
|
||||
var left = pos.left + this.$padding;
|
||||
var top = pos.top;
|
||||
|
||||
if (this.getScrollTop() > top) {
|
||||
if (this.scrollTop > top) {
|
||||
this.scrollToY(top);
|
||||
}
|
||||
|
||||
if (this.getScrollTop() + this.$size.scrollerHeight < top
|
||||
+ this.lineHeight) {
|
||||
if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {
|
||||
this.scrollToY(top + this.lineHeight - this.$size.scrollerHeight);
|
||||
}
|
||||
|
||||
if (this.scroller.scrollLeft > left) {
|
||||
var scrollLeft = this.scroller.scrollLeft;
|
||||
|
||||
if (scrollLeft > left) {
|
||||
this.scrollToX(left);
|
||||
}
|
||||
|
||||
if (this.scroller.scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
|
||||
|
||||
if (left + this.characterWidth > this.scroller.scrollWidth)
|
||||
this.$renderChanges(this.CHANGE_SIZE);
|
||||
|
||||
this.scrollToX(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
|
||||
if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
|
||||
if (left > this.layerConfig.width)
|
||||
this.$desiredScrollLeft = left + 2 * this.characterWidth;
|
||||
else
|
||||
this.scrollToX(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.getScrollTop = function() {
|
||||
return this.scrollTop;
|
||||
|
|
@ -638,7 +661,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
this.getScrollBottomRow = function() {
|
||||
return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);
|
||||
}
|
||||
};
|
||||
|
||||
this.scrollToRow = function(row) {
|
||||
this.scrollToY(row * this.lineHeight);
|
||||
|
|
@ -650,7 +673,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
for (var l = 1; l < line; l++) {
|
||||
offset += this.session.getRowHeight(lineHeight, l-1);
|
||||
}
|
||||
|
||||
|
||||
if (center) {
|
||||
offset -= this.$size.scrollerHeight / 2;
|
||||
}
|
||||
|
|
@ -658,12 +681,12 @@ var VirtualRenderer = function(container, theme) {
|
|||
};
|
||||
|
||||
this.scrollToY = function(scrollTop) {
|
||||
var maxHeight = this.session.getScreenLength() * this.lineHeight - this.$size.scrollerHeight;
|
||||
var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop));
|
||||
|
||||
// after calling scrollBar.setScrollTop
|
||||
// scrollbar sends us event with same scrollTop. ignore it
|
||||
scrollTop = Math.max(0, scrollTop);
|
||||
if (this.scrollTop !== scrollTop) {
|
||||
this.scrollTop = scrollTop;
|
||||
this.$loop.schedule(this.CHANGE_SCROLL);
|
||||
this.scrollTop = scrollTop;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -700,7 +723,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
return {
|
||||
pageX: canvasPos.left + x - this.getScrollLeft(),
|
||||
pageY: canvasPos.top + y - this.getScrollTop()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.visualizeFocus = function() {
|
||||
|
|
@ -746,6 +769,8 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
this.setTheme = function(theme) {
|
||||
var _self = this;
|
||||
|
||||
this.$themeValue = theme;
|
||||
if (!theme || typeof theme == "string") {
|
||||
theme = theme || "ace/theme/textmate";
|
||||
require([theme], function(theme) {
|
||||
|
|
@ -755,7 +780,6 @@ var VirtualRenderer = function(container, theme) {
|
|||
afterLoad(theme);
|
||||
}
|
||||
|
||||
var _self = this;
|
||||
function afterLoad(theme) {
|
||||
if (_self.$theme)
|
||||
dom.removeCssClass(_self.container, _self.$theme);
|
||||
|
|
@ -773,16 +797,25 @@ var VirtualRenderer = function(container, theme) {
|
|||
}
|
||||
};
|
||||
|
||||
this.getTheme = function() {
|
||||
return this.$themeValue;
|
||||
};
|
||||
|
||||
// Methods allows to add / remove CSS classnames to the editor element.
|
||||
// This feature can be used by plug-ins to provide a visual indication of
|
||||
// a certain mode that editor is in.
|
||||
|
||||
this.setStyle = function setStyle(style) {
|
||||
dom.addCssClass(this.container, style)
|
||||
dom.addCssClass(this.container, style);
|
||||
};
|
||||
|
||||
this.unsetStyle = function unsetStyle(style) {
|
||||
dom.removeCssClass(this.container, style)
|
||||
dom.removeCssClass(this.container, style);
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
this.$textLayer.destroy();
|
||||
this.$cursorLayer.destroy();
|
||||
};
|
||||
|
||||
}).call(VirtualRenderer.prototype);
|
||||
|
|
|
|||
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