Merge branch 'master' of https://github.com/ajaxorg/ace
This commit is contained in:
commit
707346c920
165 changed files with 47150 additions and 8364 deletions
|
|
@ -134,6 +134,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||
};
|
||||
|
||||
this.setPosition = function(row, column, noClip) {
|
||||
var pos;
|
||||
if (noClip) {
|
||||
pos = {
|
||||
row: row,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
.ace_editor {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
|
||||
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
||||
font-family: Monaco, "Menlo", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +80,7 @@
|
|||
opacity: 0;
|
||||
background: transparent;
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
resize: none;
|
||||
outline: none;
|
||||
|
|
@ -97,7 +97,6 @@
|
|||
}
|
||||
|
||||
.ace_text-layer {
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
color: black;
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +108,7 @@
|
|||
.ace_cursor-layer {
|
||||
z-index: 4;
|
||||
cursor: text;
|
||||
pointer-events: none;
|
||||
/* setting pointer-events: none; here will break mouse wheel scrolling in Safari */
|
||||
}
|
||||
|
||||
.ace_cursor {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ var Document = function(text) {
|
|||
|
||||
|
||||
this.$detectNewLine = function(text) {
|
||||
var match = text.match(/^.*?(\r?\n)/m);
|
||||
var match = text.match(/^.*?(\r\n|\r|\n)/m);
|
||||
if (match) {
|
||||
this.$autoNewLine = match[1];
|
||||
} else {
|
||||
|
|
@ -111,7 +111,8 @@ var Document = function(text) {
|
|||
this.$autoNewLine = "\n";
|
||||
this.$newLineMode = "auto";
|
||||
this.setNewLineMode = function(newLineMode) {
|
||||
if (this.$newLineMode === newLineMode) return;
|
||||
if (this.$newLineMode === newLineMode)
|
||||
return;
|
||||
|
||||
this.$newLineMode = newLineMode;
|
||||
};
|
||||
|
|
@ -183,14 +184,12 @@ 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;
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +201,6 @@ 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",
|
||||
|
|
@ -210,7 +208,6 @@ var Document = function(text) {
|
|||
lines: lines
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.end;
|
||||
},
|
||||
|
||||
|
|
@ -218,7 +215,6 @@ var Document = function(text) {
|
|||
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));
|
||||
|
||||
|
|
@ -233,7 +229,6 @@ var Document = function(text) {
|
|||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
@ -244,7 +239,6 @@ var Document = function(text) {
|
|||
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this._dispatchEvent("changeStart");
|
||||
this.$lines[position.row] = line.substring(0, position.column) + text
|
||||
+ line.substring(position.column);
|
||||
|
||||
|
|
@ -259,7 +253,6 @@ var Document = function(text) {
|
|||
text: text
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
@ -275,7 +268,6 @@ 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;
|
||||
|
|
@ -294,7 +286,6 @@ var Document = function(text) {
|
|||
else {
|
||||
this.removeInLine(firstRow, range.start.column, range.end.column);
|
||||
}
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.start;
|
||||
};
|
||||
|
||||
|
|
@ -306,7 +297,6 @@ 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 = {
|
||||
|
|
@ -315,7 +305,6 @@ var Document = function(text) {
|
|||
text: removed
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return range.start;
|
||||
};
|
||||
|
||||
|
|
@ -327,7 +316,6 @@ 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);
|
||||
|
||||
|
|
@ -338,7 +326,6 @@ var Document = function(text) {
|
|||
lines: removed
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
return removed;
|
||||
};
|
||||
|
||||
|
|
@ -349,7 +336,6 @@ 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 = {
|
||||
|
|
@ -358,7 +344,6 @@ var Document = function(text) {
|
|||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._dispatchEvent("change", { data: delta });
|
||||
this._dispatchEvent("changeEnd");
|
||||
};
|
||||
|
||||
this.replace = function(range, text) {
|
||||
|
|
@ -370,7 +355,6 @@ 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);
|
||||
|
|
@ -378,7 +362,6 @@ var Document = function(text) {
|
|||
else {
|
||||
end = range.start;
|
||||
}
|
||||
this._dispatchEvent("changeEnd");
|
||||
|
||||
return end;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ var EditSession = function(text, mode) {
|
|||
this.$backMarkers = {};
|
||||
this.$markerId = 1;
|
||||
this.$rowCache = [];
|
||||
this.$rowCacheSize = 1000;
|
||||
this.$wrapData = [];
|
||||
this.$foldData = [];
|
||||
this.$foldData.toString = function() {
|
||||
|
|
@ -66,7 +65,6 @@ var EditSession = function(text, mode) {
|
|||
});
|
||||
return str;
|
||||
}
|
||||
this.$docChangeCounter = 0;
|
||||
|
||||
if (text instanceof Document) {
|
||||
this.setDocument(text);
|
||||
|
|
@ -92,8 +90,6 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.doc = doc;
|
||||
doc.on("change", this.onChange.bind(this));
|
||||
doc.on("changeStart", this.onChangeStart.bind(this));
|
||||
doc.on("changeEnd", this.onChangeEnd.bind(this));
|
||||
this.on("changeFold", this.onChangeFold.bind(this));
|
||||
};
|
||||
|
||||
|
|
@ -101,10 +97,6 @@ var EditSession = function(text, mode) {
|
|||
return this.doc;
|
||||
};
|
||||
|
||||
this.onChangeStart = function() {
|
||||
this.$docChangeCounter ++;
|
||||
};
|
||||
|
||||
this.$resetRowCache = function(row) {
|
||||
if (row == 0) {
|
||||
this.$rowCache = [];
|
||||
|
|
@ -117,29 +109,6 @@ var EditSession = function(text, mode) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.onChangeEnd = function() {
|
||||
this.$docChangeCounter --;
|
||||
if (this.$docChangeCounter == 0
|
||||
&& !this.$fromUndo && this.$undoManager)
|
||||
{
|
||||
if (this.$deltasFold.length) {
|
||||
this.$deltas.push({
|
||||
group: "fold",
|
||||
deltas: this.$deltasFold
|
||||
});
|
||||
this.$deltasFold = [];
|
||||
}
|
||||
if (this.$deltasDoc) {
|
||||
this.$deltas.push({
|
||||
group: "doc",
|
||||
deltas: this.$deltasDoc
|
||||
});
|
||||
this.$deltasDoc = [];
|
||||
}
|
||||
this.$informUndoManager.schedule();
|
||||
}
|
||||
};
|
||||
|
||||
this.onChangeFold = function(e) {
|
||||
|
|
@ -162,6 +131,8 @@ var EditSession = function(text, mode) {
|
|||
folds: removedFolds
|
||||
});
|
||||
}
|
||||
|
||||
this.$informUndoManager.schedule();
|
||||
}
|
||||
|
||||
this.bgTokenizer.start(delta.range.start.row);
|
||||
|
|
@ -170,6 +141,9 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.setValue = function(text) {
|
||||
this.doc.setValue(text);
|
||||
this.selection.moveCursorTo(0, 0);
|
||||
this.selection.clearSelection();
|
||||
|
||||
this.$resetRowCache(0);
|
||||
this.$deltas = [];
|
||||
this.$deltasDoc = [];
|
||||
|
|
@ -201,19 +175,37 @@ var EditSession = function(text, mode) {
|
|||
this.$deltasDoc = [];
|
||||
this.$deltasFold = [];
|
||||
|
||||
if (this.$informUndoManager) {
|
||||
if (this.$informUndoManager)
|
||||
this.$informUndoManager.cancel();
|
||||
}
|
||||
|
||||
if (undoManager) {
|
||||
var self = this;
|
||||
this.$syncInformUndoManager = function() {
|
||||
self.$informUndoManager.cancel();
|
||||
if (self.$deltas.length > 0)
|
||||
undoManager.execute({
|
||||
action : "aceupdate",
|
||||
args : [self.$deltas, self]
|
||||
|
||||
if (self.$deltasFold.length) {
|
||||
self.$deltas.push({
|
||||
group: "fold",
|
||||
deltas: self.$deltasFold
|
||||
});
|
||||
self.$deltasFold = [];
|
||||
}
|
||||
|
||||
if (self.$deltasDoc.length) {
|
||||
self.$deltas.push({
|
||||
group: "doc",
|
||||
deltas: self.$deltasDoc
|
||||
});
|
||||
self.$deltasDoc = [];
|
||||
}
|
||||
|
||||
if (self.$deltas.length > 0) {
|
||||
undoManager.execute({
|
||||
action: "aceupdate",
|
||||
args: [self.$deltas, self]
|
||||
});
|
||||
}
|
||||
|
||||
self.$deltas = [];
|
||||
}
|
||||
this.$informUndoManager =
|
||||
|
|
@ -392,9 +384,6 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
this.tokenRe = /^[\w\d]+/g;
|
||||
this.nonTokenRe = /^(?:[^\w\d]|[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF])+/g;
|
||||
|
||||
this.getWordRange = function(row, column) {
|
||||
var line = this.getLine(row);
|
||||
|
||||
|
|
@ -485,6 +474,9 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.bgTokenizer.setDocument(this.getDocument());
|
||||
this.bgTokenizer.start(0);
|
||||
|
||||
this.tokenRe = mode.tokenRe;
|
||||
this.nonTokenRe = mode.nonTokenRe;
|
||||
|
||||
this._dispatchEvent("changeMode");
|
||||
};
|
||||
|
|
@ -898,6 +890,28 @@ var EditSession = function(text, mode) {
|
|||
this.$clipRowToDocument = function(row) {
|
||||
return Math.max(0, Math.min(row, this.doc.getLength()-1));
|
||||
};
|
||||
|
||||
this.$clipPositionToDocument = function(row, column) {
|
||||
column = Math.max(0, column);
|
||||
|
||||
if (row < 0) {
|
||||
row = 0;
|
||||
column = 0;
|
||||
} else {
|
||||
var len = this.doc.getLength();
|
||||
if (row >= len) {
|
||||
row = len - 1;
|
||||
column = this.doc.getLine(len-1).length;
|
||||
} else {
|
||||
column = Math.min(this.doc.getLine(row).length, column);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
row: row,
|
||||
column: column
|
||||
};
|
||||
};
|
||||
|
||||
// WRAPMODE
|
||||
this.$wrapLimit = 80;
|
||||
|
|
@ -1352,6 +1366,9 @@ var EditSession = function(text, mode) {
|
|||
return [screenColumn, column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows required to render this row on the screen
|
||||
*/
|
||||
this.getRowLength = function(row) {
|
||||
if (!this.$useWrapMode || !this.$wrapData[row]) {
|
||||
return 1;
|
||||
|
|
@ -1360,15 +1377,16 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height in pixels required to render this row on the screen
|
||||
**/
|
||||
this.getRowHeight = function(config, row) {
|
||||
return this.getRowLength(row) * config.lineHeight;
|
||||
}
|
||||
|
||||
this.getScreenLastRowColumn = function(screenRow) {
|
||||
// Note: This won't work if someone has more then
|
||||
// 1.7976931348623158e+307 characters in one row. But I think we can
|
||||
// live with this limitation ;)
|
||||
return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
|
||||
//return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
|
||||
return this.documentToScreenColumn(screenRow, this.doc.getLine(screenRow).length);
|
||||
};
|
||||
|
||||
this.getDocumentLastRowColumn = function(docRow, docColumn) {
|
||||
|
|
@ -1405,6 +1423,13 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
|
||||
this.screenToDocumentPosition = function(screenRow, screenColumn) {
|
||||
if (screenRow < 0) {
|
||||
return {
|
||||
row: 0,
|
||||
column: 0
|
||||
}
|
||||
}
|
||||
|
||||
var line;
|
||||
var docRow = 0;
|
||||
var docColumn = 0;
|
||||
|
|
@ -1412,45 +1437,44 @@ var EditSession = function(text, mode) {
|
|||
var foldLineRowLength;
|
||||
var row = 0;
|
||||
var rowLength = 0;
|
||||
var splits = null;
|
||||
|
||||
var rowCache = this.$rowCache;
|
||||
var doCache = !rowCache.length;
|
||||
for (var i = 0; i < rowCache.length; i++) {
|
||||
if (rowCache[i].screenRow < screenRow) {
|
||||
row = rowCache[i].screenRow;
|
||||
docRow = rowCache[i].docRow;
|
||||
doCache = i == rowCache.length - 1;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var docRowCacheLast = docRow;
|
||||
var doCache = !rowCache.length || i == rowCache.length;
|
||||
|
||||
// clamp row before clamping column, for selection on last line
|
||||
var maxRow = this.getLength() - 1;
|
||||
|
||||
var foldLine = this.getNextFold(docRow);
|
||||
var foldStart = foldLine ?foldLine.start.row :Infinity;
|
||||
var foldStart = foldLine ? foldLine.start.row : Infinity;
|
||||
|
||||
while (row <= screenRow) {
|
||||
if (doCache
|
||||
&& docRow - docRowCacheLast > this.$rowCacheSize) {
|
||||
rowCache.push({
|
||||
docRow: docRow,
|
||||
screenRow: row
|
||||
});
|
||||
docRowCacheLast = docRow;
|
||||
}
|
||||
rowLength = this.getRowLength(docRow);
|
||||
if (row + rowLength - 1 >= screenRow || docRow >= maxRow) {
|
||||
break;
|
||||
} else {
|
||||
row += rowLength;
|
||||
docRow++;
|
||||
if(docRow > foldStart) {
|
||||
if (docRow > foldStart) {
|
||||
docRow = foldLine.end.row+1;
|
||||
foldLine = this.getNextFold(docRow);
|
||||
foldStart = foldLine ?foldLine.start.row :Infinity;
|
||||
foldStart = foldLine ? foldLine.start.row : Infinity;
|
||||
}
|
||||
}
|
||||
if (doCache) {
|
||||
rowCache.push({
|
||||
docRow: docRow,
|
||||
screenRow: row
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (foldLine && foldLine.start.row <= docRow)
|
||||
|
|
@ -1460,6 +1484,7 @@ var EditSession = function(text, mode) {
|
|||
foldLine = null;
|
||||
}
|
||||
|
||||
var splits = [];
|
||||
if (this.$useWrapMode) {
|
||||
splits = this.$wrapData[docRow];
|
||||
if (splits) {
|
||||
|
|
@ -1473,6 +1498,10 @@ var EditSession = function(text, mode) {
|
|||
|
||||
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
|
||||
|
||||
// clip row at the end of the document
|
||||
if (row + splits.length < screenRow)
|
||||
docColumn = Number.MAX_VALUE;
|
||||
|
||||
// Need to do some clamping action here.
|
||||
if (this.$useWrapMode) {
|
||||
if (docColumn >= column) {
|
||||
|
|
@ -1488,7 +1517,7 @@ var EditSession = function(text, mode) {
|
|||
if (foldLine) {
|
||||
return foldLine.idxToPosition(docColumn);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
row: docRow,
|
||||
column: docColumn
|
||||
|
|
@ -1497,10 +1526,15 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.documentToScreenPosition = function(docRow, docColumn) {
|
||||
// Normalize the passed in arguments.
|
||||
if (docColumn == null) {
|
||||
docColumn = docRow.column;
|
||||
docRow = docRow.row;
|
||||
}
|
||||
if (typeof docColumn === "undefined")
|
||||
var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
|
||||
else
|
||||
pos = this.$clipPositionToDocument(docRow, docColumn);
|
||||
|
||||
docRow = pos.row;
|
||||
docColumn = pos.column;
|
||||
|
||||
var LL = this.$rowCache.length;
|
||||
|
||||
var wrapData;
|
||||
// Special case in wrapMode if the doc is at the end of the document.
|
||||
|
|
@ -1530,16 +1564,16 @@ var EditSession = function(text, mode) {
|
|||
|
||||
var rowEnd, row = 0;
|
||||
var rowCache = this.$rowCache;
|
||||
//
|
||||
var doCache = !rowCache.length;
|
||||
|
||||
for (var i = 0; i < rowCache.length; i++) {
|
||||
if (rowCache[i].docRow < docRow) {
|
||||
screenRow = rowCache[i].screenRow;
|
||||
row = rowCache[i].docRow;
|
||||
doCache = i == rowCache.length - 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var docRowCacheLast = row;
|
||||
var doCache = !rowCache.length || i == rowCache.length;
|
||||
|
||||
var foldLine = this.getNextFold(row);
|
||||
var foldStart = foldLine ?foldLine.start.row :Infinity;
|
||||
|
|
@ -1551,20 +1585,20 @@ var EditSession = function(text, mode) {
|
|||
break;
|
||||
foldLine = this.getNextFold(rowEnd);
|
||||
foldStart = foldLine ?foldLine.start.row :Infinity;
|
||||
} else {
|
||||
rowEnd = row + 1;
|
||||
}
|
||||
if (doCache
|
||||
&& row - docRowCacheLast > this.$rowCacheSize) {
|
||||
rowCache.push({
|
||||
docRow: row,
|
||||
screenRow: screenRow
|
||||
});
|
||||
docRowCacheLast = row;
|
||||
else {
|
||||
rowEnd = row + 1;
|
||||
}
|
||||
|
||||
screenRow += this.getRowLength(row);
|
||||
row = rowEnd;
|
||||
|
||||
if (doCache) {
|
||||
rowCache.push({
|
||||
docRow: row,
|
||||
screenRow: screenRow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the text line that is displayed in docRow on the screen.
|
||||
|
|
@ -1586,7 +1620,8 @@ var EditSession = function(text, mode) {
|
|||
screenRowOffset++;
|
||||
}
|
||||
textLine = textLine.substring(
|
||||
wrapRow[screenRowOffset - 1] || 0, textLine.length);
|
||||
wrapRow[screenRowOffset - 1] || 0, textLine.length
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
79
lib/ace/edit_session/fold.js
Normal file
79
lib/ace/edit_session/fold.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* 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) {
|
||||
|
||||
/**
|
||||
* Simple fold-data struct.
|
||||
**/
|
||||
var Fold = exports.Fold = function(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 = [];
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
this.toString = function() {
|
||||
return '"' + this.placeholder + '" ' + this.range.toString();
|
||||
};
|
||||
|
||||
this.setFoldLine = function(foldLine) {
|
||||
this.foldLine = foldLine;
|
||||
this.subFolds.forEach(function(fold) {
|
||||
fold.setFoldLine(foldLine);
|
||||
});
|
||||
};
|
||||
|
||||
this.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;
|
||||
};
|
||||
|
||||
}).call(Fold.prototype);
|
||||
|
||||
});
|
||||
|
|
@ -40,40 +40,7 @@ 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;
|
||||
}
|
||||
var Fold = require("ace/edit_session/fold").Fold;
|
||||
|
||||
function Folding() {
|
||||
/**
|
||||
|
|
@ -83,25 +50,22 @@ function Folding() {
|
|||
*/
|
||||
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 {
|
||||
if (!foldLine)
|
||||
return null;
|
||||
|
||||
var folds = foldLine.folds;
|
||||
for (var i = 0; i < folds.length; i++) {
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all folds in the given range. Note, that this will return folds
|
||||
|
|
@ -109,33 +73,30 @@ function Folding() {
|
|||
*/
|
||||
this.getFoldsInRange = function(range) {
|
||||
range = range.clone();
|
||||
var start = range.start,
|
||||
end = range.end;
|
||||
var foldLines = this.$foldData,
|
||||
folds,
|
||||
fold;
|
||||
var cmp,
|
||||
foundFolds = [];
|
||||
var start = range.start;
|
||||
var end = range.end;
|
||||
var foldLines = this.$foldData;
|
||||
var 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.
|
||||
var cmp = foldLines[i].range.compareRange(range);
|
||||
if (cmp == 2) {
|
||||
// Range is before foldLine. No intersection. This means,
|
||||
// there might be other foldLines that intersect.
|
||||
continue;
|
||||
} else
|
||||
// Range is after foldLine. There can't be any other foldLines then,
|
||||
// so let's give up.
|
||||
if (cmp == -2) {
|
||||
}
|
||||
else if (cmp == -2) {
|
||||
// Range is after foldLine. There can't be any other foldLines then,
|
||||
// so let's give up.
|
||||
break;
|
||||
}
|
||||
|
||||
folds = foldLines[i].folds;
|
||||
var folds = foldLines[i].folds;
|
||||
for (var j = 0; j < folds.length; j++) {
|
||||
fold = folds[j];
|
||||
var fold = folds[j];
|
||||
cmp = fold.range.compareRange(range);
|
||||
if (cmp == -2) {
|
||||
break;
|
||||
|
|
@ -171,46 +132,44 @@ function Folding() {
|
|||
*/
|
||||
this.getFoldStringAt = function(row, column, trim, foldLine) {
|
||||
var foldLine = foldLine || this.getFoldLine(row);
|
||||
if (!foldLine) {
|
||||
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;
|
||||
|
||||
var lastFold = {
|
||||
end: { column: 0 }
|
||||
};
|
||||
// TODO: Refactor to use getNextFoldTo function.
|
||||
for (var i = 0; i < foldLine.folds.length; i++) {
|
||||
var fold = foldLine.folds[i];
|
||||
var cmp = fold.range.compareEnd(row, column);
|
||||
if (cmp == -1) {
|
||||
var str = this
|
||||
.getLine(fold.start.row)
|
||||
.substring(lastFold.end.column, fold.start.column);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
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)
|
||||
if (startFoldLine)
|
||||
i = foldData.indexOf(startFoldLine);
|
||||
if(i == -1)
|
||||
if (i == -1)
|
||||
i = 0;
|
||||
for (i; i < foldData.length; i++) {
|
||||
var foldLine = foldData[i];
|
||||
|
|
@ -227,9 +186,9 @@ function Folding() {
|
|||
this.getNextFold = function(docRow, startFoldLine) {
|
||||
var foldData = this.$foldData, ans;
|
||||
var i = 0;
|
||||
if(startFoldLine)
|
||||
if (startFoldLine)
|
||||
i = foldData.indexOf(startFoldLine);
|
||||
if(i == -1)
|
||||
if (i == -1)
|
||||
i = 0;
|
||||
for (i; i < foldData.length; i++) {
|
||||
var foldLine = foldData[i];
|
||||
|
|
@ -246,7 +205,7 @@ function Folding() {
|
|||
var foldLine = foldData[i],
|
||||
end = foldLine.end.row,
|
||||
start = foldLine.start.row;
|
||||
if(end >= last) {
|
||||
if (end >= last) {
|
||||
if(start < last) {
|
||||
if(start >= first)
|
||||
rowCount -= last-start;
|
||||
|
|
@ -279,76 +238,52 @@ function Folding() {
|
|||
* 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;
|
||||
this.addFold = function(placeholder, 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;
|
||||
}
|
||||
if (placeholder instanceof Fold)
|
||||
var fold = placeholder;
|
||||
else
|
||||
fold = new Fold(range, placeholder);
|
||||
|
||||
var startRow = fold.start.row;
|
||||
var startColumn = fold.start.column;
|
||||
var endRow = fold.end.row;
|
||||
var endColumn = fold.end.column;
|
||||
|
||||
// --- Some checking ---
|
||||
if (placeholder.length < 2) {
|
||||
if (fold.placeholder.length < 2)
|
||||
throw "Placeholder has to be at least 2 characters";
|
||||
}
|
||||
|
||||
if (startRow == endRow && endColumn - startColumn < 2) {
|
||||
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))
|
||||
{
|
||||
var existingFold = this.getFoldAt(startRow, startColumn, 1);
|
||||
if (
|
||||
existingFold
|
||||
&& existingFold.range.isEnd(endRow, endColumn)
|
||||
&& existingFold.range.isStart(startRow, startColumn)
|
||||
) {
|
||||
return fold;
|
||||
}
|
||||
|
||||
fold = this.getFoldAt(startRow, startColumn, 1);
|
||||
if (fold && !fold.range.isStart(startRow, startColumn)) {
|
||||
existingFold = this.getFoldAt(startRow, startColumn, 1);
|
||||
if (existingFold && !existingFold.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)) {
|
||||
existingFold = this.getFoldAt(endRow, endColumn, -1);
|
||||
if (existingFold && !existingFold.range.isEnd(endRow, endColumn))
|
||||
throw "A fold can't end inside of an already existing fold";
|
||||
}
|
||||
|
||||
if (endRow >= this.doc.getLength()) {
|
||||
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)
|
||||
{
|
||||
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);
|
||||
var folds = this.getFoldsInRange(fold.range);
|
||||
if (folds.length > 0) {
|
||||
// Remove the folds from fold data.
|
||||
this.removeFolds(folds);
|
||||
|
|
@ -357,12 +292,13 @@ function Folding() {
|
|||
}
|
||||
|
||||
for (var i = 0; i < foldData.length; i++) {
|
||||
foldLine = foldData[i];
|
||||
var foldLine = foldData[i];
|
||||
if (endRow == foldLine.start.row) {
|
||||
foldLine.addFold(fold);
|
||||
added = true;
|
||||
break;
|
||||
} else if (startRow == foldLine.end.row) {
|
||||
}
|
||||
else if (startRow == foldLine.end.row) {
|
||||
foldLine.addFold(fold);
|
||||
added = true;
|
||||
if (!fold.sameRow) {
|
||||
|
|
@ -375,18 +311,17 @@ function Folding() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
} else if (endRow <= foldLine.start.row) {
|
||||
}
|
||||
else if (endRow <= foldLine.start.row) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
if (!added)
|
||||
foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
|
||||
}
|
||||
|
||||
if (this.$useWrapMode) {
|
||||
if (this.$useWrapMode)
|
||||
this.$updateWrapData(foldLine.start.row, foldLine.start.row);
|
||||
}
|
||||
|
||||
// Notify that fold data has changed.
|
||||
this.$modified = true;
|
||||
|
|
|
|||
|
|
@ -155,6 +155,18 @@ module.exports = {
|
|||
assert.equal(session.getValue(), ["1", "1", "2", "3"].join("\n"));
|
||||
},
|
||||
|
||||
"test: getScreenLastRowColumn": function() {
|
||||
var session = new EditSession([
|
||||
"juhu",
|
||||
"12\t\t34",
|
||||
"ぁぁa"
|
||||
]);
|
||||
|
||||
assert.equal(session.getScreenLastRowColumn(0), 4);
|
||||
assert.equal(session.getScreenLastRowColumn(1), 10);
|
||||
assert.equal(session.getScreenLastRowColumn(2), 5);
|
||||
},
|
||||
|
||||
"test: convert document to screen coordinates" : function() {
|
||||
var session = new EditSession("01234\t567890\t1234");
|
||||
session.setTabSize(4);
|
||||
|
|
@ -187,9 +199,20 @@ module.exports = {
|
|||
assert.equal(session.documentToScreenColumn(0, 3), 9);
|
||||
},
|
||||
|
||||
"test: documentToScreen with soft wrap and multibyte characters": function() {
|
||||
var tabSize = 4;
|
||||
var wrapLimit = 12;
|
||||
"test: documentToScreen without soft wrap": function() {
|
||||
var session = new EditSession([
|
||||
"juhu",
|
||||
"12\t\t34",
|
||||
"ぁぁa"
|
||||
]);
|
||||
|
||||
assert.position(session.documentToScreenPosition(0, 3), 0, 3);
|
||||
assert.position(session.documentToScreenPosition(1, 3), 1, 4);
|
||||
assert.position(session.documentToScreenPosition(1, 4), 1, 8);
|
||||
assert.position(session.documentToScreenPosition(2, 2), 2, 4);
|
||||
},
|
||||
|
||||
"test: documentToScreen with soft wrap": function() {
|
||||
var session = new EditSession(["foo bar foo bar"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(12, 12);
|
||||
|
|
@ -197,6 +220,9 @@ module.exports = {
|
|||
|
||||
assert.position(session.documentToScreenPosition(0, 11), 0, 11);
|
||||
assert.position(session.documentToScreenPosition(0, 12), 1, 0);
|
||||
},
|
||||
|
||||
"test: documentToScreen with soft wrap and multibyte characters": function() {
|
||||
|
||||
session = new EditSession(["ぁぁa"]);
|
||||
session.setUseWrapMode(true);
|
||||
|
|
@ -208,6 +234,13 @@ module.exports = {
|
|||
assert.position(session.documentToScreenPosition(0, 4), 2, 1);
|
||||
},
|
||||
|
||||
"test: documentToScreen should clip position to the document boundaries": function() {
|
||||
var session = new EditSession("foo bar\njuhu kinners");
|
||||
|
||||
assert.position(session.documentToScreenPosition(-1, 4), 0, 0);
|
||||
assert.position(session.documentToScreenPosition(3, 0), 1, 12);
|
||||
},
|
||||
|
||||
"test: convert screen to document coordinates" : function() {
|
||||
var session = new EditSession("01234\t567890\t1234");
|
||||
session.setTabSize(4);
|
||||
|
|
@ -233,9 +266,7 @@ module.exports = {
|
|||
assert.equal(session.screenToDocumentColumn(0, 14), 13);
|
||||
},
|
||||
|
||||
"test: screenToDocument with soft wrap and multi byte characters": function() {
|
||||
var tabSize = 4;
|
||||
var wrapLimit = 12;
|
||||
"test: screenToDocument with soft wrap": function() {
|
||||
var session = new EditSession(["foo bar foo bar"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(12, 12);
|
||||
|
|
@ -246,7 +277,9 @@ module.exports = {
|
|||
// 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);
|
||||
|
||||
},
|
||||
|
||||
"test: screenToDocument with soft wrap and multi byte characters": function() {
|
||||
session = new EditSession(["ぁ a"]);
|
||||
session.setUseWrapMode(true);
|
||||
session.adjustWrapLimit(80);
|
||||
|
|
@ -257,6 +290,18 @@ module.exports = {
|
|||
assert.position(session.screenToDocumentPosition(0, 4), 0, 3);
|
||||
assert.position(session.screenToDocumentPosition(0, 5), 0, 3);
|
||||
},
|
||||
|
||||
"test: screenToDocument should clip position to the document boundaries": function() {
|
||||
var session = new EditSession("foo bar\njuhu kinners");
|
||||
|
||||
assert.position(session.screenToDocumentPosition(-1, 4), 0, 0);
|
||||
assert.position(session.screenToDocumentPosition(0, -1), 0, 0);
|
||||
assert.position(session.screenToDocumentPosition(0, 30), 0, 7);
|
||||
assert.position(session.screenToDocumentPosition(2, 4), 1, 12);
|
||||
assert.position(session.screenToDocumentPosition(1, 30), 1, 12);
|
||||
assert.position(session.screenToDocumentPosition(20, 50), 1, 12);
|
||||
assert.position(session.screenToDocumentPosition(20, 5), 1, 12);
|
||||
},
|
||||
|
||||
"test: wrapLine split function" : function() {
|
||||
var splits;
|
||||
|
|
@ -526,9 +571,10 @@ module.exports = {
|
|||
|
||||
"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;
|
||||
var session = createFoldTestSession();
|
||||
var undoManager = session.getUndoManager();
|
||||
var foldLines = session.$foldData;
|
||||
|
||||
function insert(row, column, text) {
|
||||
session.insert({row: row, column: column}, text);
|
||||
|
||||
|
|
@ -731,45 +777,45 @@ module.exports = {
|
|||
|
||||
// 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);
|
||||
session.addFold("woot", new Range(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);
|
||||
session.addFold("woot", new Range(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);
|
||||
session.addFold("woot", new Range(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);
|
||||
session.addFold("woot", new Range(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);
|
||||
session.addFold("woot0123456789", new Range(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);
|
||||
session.addFold("woot0123456789", new Range(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);
|
||||
session.addFold("woot0123456789", new Range(0, 6, 0, 8));
|
||||
session.addFold("woot0123456789", new Range(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);
|
||||
session.addFold("woot0123456789", new Range(0, 7, 0, 9));
|
||||
session.addFold("woot0123456789", new Range(0, 13, 0, 15));
|
||||
assertWrap([7, 21, 25], [8], [8]);
|
||||
session.removeFold(session.getFoldAt(0, 7));
|
||||
removeFoldAssertWrap(0, 14, [8], [8], [8]);
|
||||
|
|
@ -778,15 +824,15 @@ module.exports = {
|
|||
|
||||
// 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);
|
||||
session.addFold("woot", new Range(0, 8, 1, 15));
|
||||
assertWrap([8], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 8, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot", 0, 9, 1, 11);
|
||||
session.addFold("woot", new Range(0, 9, 1, 11));
|
||||
assertWrap([8, 14], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 9, [8], [8], [8]);
|
||||
|
||||
session.addFold("woot", 0, 9, 1, 15);
|
||||
session.addFold("woot", new Range(0, 9, 1, 15));
|
||||
assertWrap([8], [8 /* See comments */], [8]);
|
||||
removeFoldAssertWrap(0, 9, [8], [8], [8]);
|
||||
|
||||
|
|
@ -797,14 +843,10 @@ module.exports = {
|
|||
var session = createFoldTestSession();
|
||||
var fold;
|
||||
|
||||
function tryAddFold(
|
||||
placeholder,
|
||||
startRow, startColumn, endRow, endColumn, shouldFail)
|
||||
{
|
||||
function tryAddFold(placeholder, range, shouldFail) {
|
||||
var fail = false;
|
||||
try {
|
||||
fold = session.addFold(placeholder,
|
||||
startRow, startColumn, endRow, endColumn);
|
||||
fold = session.addFold(placeholder, range);
|
||||
} catch (e) {
|
||||
fail = true;
|
||||
}
|
||||
|
|
@ -813,19 +855,19 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
tryAddFold("foo", 0, 13, 0, 17, true);
|
||||
tryAddFold("foo", 0, 14, 0, 18, true);
|
||||
tryAddFold("foo", 0, 13, 0, 18, false);
|
||||
tryAddFold("foo", new Range(0, 13, 0, 17), true);
|
||||
tryAddFold("foo", new Range(0, 14, 0, 18), true);
|
||||
tryAddFold("foo", new Range(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);
|
||||
tryAddFold("f", new Range(0, 13, 0, 18), true);
|
||||
tryAddFold("foo", new Range(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);
|
||||
tryAddFold("foo", new Range(0, 18, 0, 22), true);
|
||||
tryAddFold("foo", new Range(0, 18, 0, 19), true);
|
||||
tryAddFold("foo", new Range(0, 22, 1, 10), true);
|
||||
},
|
||||
|
||||
"test add subfolds": function() {
|
||||
|
|
@ -835,7 +877,7 @@ module.exports = {
|
|||
|
||||
oldFold = foldData[0].folds[0];
|
||||
|
||||
fold = session.addFold("fold0", 0, 10, 0, 21);
|
||||
fold = session.addFold("fold0", new Range(0, 10, 0, 21));
|
||||
assert.equal(foldData[0].folds.length, 1);
|
||||
assert.equal(fold.subFolds.length, 1);
|
||||
assert.equal(fold.subFolds[0], oldFold);
|
||||
|
|
@ -845,7 +887,7 @@ module.exports = {
|
|||
assert.equal(foldData[0].folds[0], oldFold);
|
||||
assert.equal(fold.subFolds.length, 0);
|
||||
|
||||
fold = session.addFold("fold0", 0, 13, 2, 10);
|
||||
fold = session.addFold("fold0", new Range(0, 13, 2, 10));
|
||||
assert.equal(foldData.length, 1);
|
||||
assert.equal(fold.subFolds.length, 2);
|
||||
assert.equal(fold.subFolds[0], oldFold);
|
||||
|
|
@ -861,5 +903,5 @@ module.exports = {
|
|||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs/test").testcase(module.exports).exec()
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -115,7 +115,8 @@ var Editor =function(renderer, session) {
|
|||
};
|
||||
|
||||
this.setSession = function(session) {
|
||||
if (this.session == session) return;
|
||||
if (this.session == session)
|
||||
return;
|
||||
|
||||
if (this.session) {
|
||||
var oldSession = this.session;
|
||||
|
|
@ -253,7 +254,7 @@ var Editor =function(renderer, session) {
|
|||
var pos = self.session.findMatchingBracket(self.getCursorPosition());
|
||||
if (pos) {
|
||||
var range = new Range(pos.row, pos.column, pos.row, pos.column+1);
|
||||
self.session.$bracketHighlight = self.session.addMarker(range, "ace_bracket");
|
||||
self.session.$bracketHighlight = self.session.addMarker(range, "ace_bracket", "text");
|
||||
}
|
||||
}, 10);
|
||||
};
|
||||
|
|
@ -271,6 +272,10 @@ var Editor =function(renderer, session) {
|
|||
}
|
||||
this.textInput.focus();
|
||||
};
|
||||
|
||||
this.isFocused = function() {
|
||||
return this.textInput.isFocused();
|
||||
};
|
||||
|
||||
this.blur = function() {
|
||||
this.textInput.blur();
|
||||
|
|
@ -339,7 +344,7 @@ var Editor =function(renderer, session) {
|
|||
} else {
|
||||
range = new Range(cursor.row, 0, cursor.row+1, 0);
|
||||
}
|
||||
session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "line");
|
||||
session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "background");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -426,14 +431,14 @@ var Editor =function(renderer, 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
|
||||
|
|
@ -449,13 +454,13 @@ var Editor =function(renderer, session) {
|
|||
|
||||
this.clearSelection();
|
||||
|
||||
var start = cursor.column;
|
||||
var lineState = session.getState(cursor.row);
|
||||
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 line = session.getLine(cursor.row);
|
||||
var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
|
||||
var end = session.insert(cursor, text);
|
||||
|
||||
if (transform && transform.selection) {
|
||||
if (transform.selection.length == 2) { // Transform relative to the current column
|
||||
this.selection.setSelectionRange(
|
||||
|
|
@ -469,7 +474,7 @@ var Editor =function(renderer, session) {
|
|||
transform.selection[3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var lineState = session.getState(cursor.row);
|
||||
|
||||
// TODO disabled multiline auto indent
|
||||
|
|
@ -515,8 +520,27 @@ var Editor =function(renderer, session) {
|
|||
}
|
||||
};
|
||||
|
||||
this.onTextInput = function(text) {
|
||||
this.keyBinding.onTextInput(text);
|
||||
this.onTextInput = function(text, notPasted) {
|
||||
// In case the text was not pasted and we got only one character, then
|
||||
// handel it as a command key stroke.
|
||||
if (notPasted && text.length == 1) {
|
||||
// Note: The `null` as `keyCode` is important here, as there are
|
||||
// some checks in the code for `keyCode == 0` meaning the text comes
|
||||
// from the keyBinding.onTextInput code path.
|
||||
var handled = this.keyBinding.onCommandKey({}, 0, null, text);
|
||||
|
||||
// Check if the text was handled. If not, then handled it as "normal"
|
||||
// text and insert it to the editor directly. This shouldn't be done
|
||||
// using the this.keyBinding.onTextInput(text) function, as it would
|
||||
// make the `text` get sent to the keyboardHandler twice, which might
|
||||
// turn out to be a bad thing in case there is a custome keyboard
|
||||
// handler like the StateHandler.
|
||||
if (!handled) {
|
||||
this.insert(text);
|
||||
}
|
||||
} else {
|
||||
this.keyBinding.onTextInput(text);
|
||||
}
|
||||
};
|
||||
|
||||
this.onCommandKey = function(e, hashId, keyCode) {
|
||||
|
|
@ -619,12 +643,12 @@ var Editor =function(renderer, session) {
|
|||
this.getReadOnly = function() {
|
||||
return this.$readOnly;
|
||||
};
|
||||
|
||||
this.$modeBehaviours = false;
|
||||
|
||||
this.$modeBehaviours = true;
|
||||
this.setBehavioursEnabled = function (enabled) {
|
||||
this.$modeBehaviours = enabled;
|
||||
}
|
||||
|
||||
|
||||
this.getBehavioursEnabled = function () {
|
||||
return this.$modeBehaviours;
|
||||
}
|
||||
|
|
@ -646,7 +670,7 @@ var Editor =function(renderer, session) {
|
|||
|
||||
if (this.selection.isEmpty())
|
||||
this.selection.selectLeft();
|
||||
|
||||
|
||||
var range = this.getSelectionRange();
|
||||
if (this.getBehavioursEnabled()) {
|
||||
var session = this.session;
|
||||
|
|
@ -798,7 +822,14 @@ var Editor =function(renderer, session) {
|
|||
return;
|
||||
|
||||
var rows = this.$getSelectedRows();
|
||||
this.session.remove(new Range(rows.first, 0, rows.last+1, 0));
|
||||
if (rows.last == 0 || rows.last+1 < this.session.getLength())
|
||||
var range = new Range(rows.first, 0, rows.last+1, 0)
|
||||
else
|
||||
var range = new Range(
|
||||
rows.first-1, this.session.getLine(rows.first).length,
|
||||
rows.last, this.session.getLine(rows.last).length
|
||||
);
|
||||
this.session.remove(range);
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
|
@ -1001,11 +1032,11 @@ var Editor =function(renderer, session) {
|
|||
};
|
||||
|
||||
|
||||
this.gotoLine = function(lineNumber, row) {
|
||||
this.gotoLine = function(lineNumber, column) {
|
||||
this.selection.clearSelection();
|
||||
|
||||
this.$blockScrolling += 1;
|
||||
this.moveCursorTo(lineNumber-1, row || 0);
|
||||
this.moveCursorTo(lineNumber-1, column || 0);
|
||||
this.$blockScrolling -= 1;
|
||||
|
||||
if (!this.isRowVisible(this.getCursorPosition().row)) {
|
||||
|
|
@ -1093,6 +1124,9 @@ var Editor =function(renderer, session) {
|
|||
this.$search.set(options);
|
||||
|
||||
var range = this.$search.find(this.session);
|
||||
if (!range)
|
||||
return;
|
||||
|
||||
this.$tryReplace(range, replacement);
|
||||
if (range !== null)
|
||||
this.selection.setSelectionRange(range);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,16 @@ module.exports = {
|
|||
|
||||
editor.navigateUp();
|
||||
assert.position(editor.getCursorPosition(), 0, 1);
|
||||
},
|
||||
|
||||
"test: typing text should update the desired column": function() {
|
||||
var editor = new Editor(new MockRenderer(), new EditSession(["1234", "1234567890"]));
|
||||
|
||||
editor.navigateTo(0, 3);
|
||||
editor.insert("juhu");
|
||||
|
||||
editor.navigateDown();
|
||||
assert.position(editor.getCursorPosition(), 1, 7);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ module.exports = {
|
|||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(session.toString(), "a\n");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
assert.equal(session.toString(), "a");
|
||||
assert.position(editor.getCursorPosition(), 0, 1);
|
||||
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(session.toString(), "a\n");
|
||||
assert.position(editor.getCursorPosition(), 1, 0);
|
||||
assert.equal(session.toString(), "");
|
||||
assert.position(editor.getCursorPosition(), 0, 0);
|
||||
},
|
||||
|
||||
"test: delete multiple selected lines" : function() {
|
||||
|
|
@ -98,15 +98,15 @@ module.exports = {
|
|||
assert.position(editor.getCursorPosition(), 0, 0);
|
||||
},
|
||||
|
||||
"test: delete last" : function() {
|
||||
"test: delete last should also delete the new line of the previous line" : function() {
|
||||
var session = new EditSession(["a", "b", "c"].join("\n"));
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
|
||||
editor.moveCursorTo(2, 1);
|
||||
editor.removeLines();
|
||||
|
||||
assert.equal(session.toString(), "a\nb\n");
|
||||
assert.position(editor.getCursorPosition(), 2, 0);
|
||||
assert.equal(session.toString(), "a\nb");
|
||||
assert.position(editor.getCursorPosition(), 1, 1);
|
||||
},
|
||||
|
||||
"test: indent block" : function() {
|
||||
|
|
@ -382,33 +382,32 @@ module.exports = {
|
|||
editor.removeLines();
|
||||
var step1 = session.toString();
|
||||
assert.equal(step1, "222\n333");
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
|
||||
editor.removeLines();
|
||||
var step2 = session.toString();
|
||||
assert.equal(step2, "333");
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
|
||||
editor.removeLines();
|
||||
var step3 = session.toString();
|
||||
assert.equal(step3, "");
|
||||
session.$informUndoManager.call();
|
||||
|
||||
session.$syncInformUndoManager();
|
||||
|
||||
undoManager.undo();
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
assert.equal(session.toString(), step2);
|
||||
|
||||
undoManager.undo();
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
assert.equal(session.toString(), step1);
|
||||
|
||||
undoManager.undo();
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
assert.equal(session.toString(), initialText);
|
||||
|
||||
undoManager.undo();
|
||||
session.$informUndoManager.call();
|
||||
session.$syncInformUndoManager();
|
||||
assert.equal(session.toString(), initialText);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -88,22 +88,27 @@ var KeyBinding = function(editor) {
|
|||
}
|
||||
}
|
||||
|
||||
var success = false;
|
||||
if (toExecute) {
|
||||
var success = canon.exec(toExecute.command,
|
||||
success = canon.exec(toExecute.command,
|
||||
env, "editor", toExecute.args);
|
||||
if (success) {
|
||||
return event.stopEvent(e);
|
||||
event.stopEvent(e);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
};
|
||||
|
||||
this.onCommandKey = function(e, hashId, keyCode) {
|
||||
var keyString = keyUtil.keyCodeToString(keyCode);
|
||||
this.$callKeyboardHandler(e, hashId, keyString, keyCode);
|
||||
this.onCommandKey = function(e, hashId, keyCode, keyString) {
|
||||
// In case there is no keyString, try to interprete the keyCode.
|
||||
if (!keyString) {
|
||||
keyString = keyUtil.keyCodeToString(keyCode);
|
||||
}
|
||||
return this.$callKeyboardHandler(e, hashId, keyString, keyCode);
|
||||
};
|
||||
|
||||
this.onTextInput = function(text) {
|
||||
this.$callKeyboardHandler({}, 0, text, 0);
|
||||
return this.$callKeyboardHandler({}, 0, text, 0);
|
||||
}
|
||||
|
||||
}).call(KeyBinding.prototype);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ var vimStates = {
|
|||
key: "i",
|
||||
then: "insertMode"
|
||||
},
|
||||
{
|
||||
key: "d",
|
||||
then: "deleteMode"
|
||||
},
|
||||
{
|
||||
key: "a",
|
||||
exec: "gotoright",
|
||||
|
|
@ -160,6 +164,13 @@ var vimStates = {
|
|||
exec: "overwrite",
|
||||
then: "start"
|
||||
}
|
||||
],
|
||||
deleteMode: [
|
||||
{
|
||||
key: "d",
|
||||
exec: "removeline",
|
||||
then: "start"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ var TextInput = function(parentNode, host) {
|
|||
|
||||
var inCompostion = false;
|
||||
var copied = false;
|
||||
var pasted = false;
|
||||
var tempStyle = '';
|
||||
|
||||
function sendText(valueToSend) {
|
||||
|
|
@ -63,16 +64,21 @@ var TextInput = function(parentNode, host) {
|
|||
if (value.charCodeAt(value.length-1) == PLACEHOLDER.charCodeAt(0)) {
|
||||
value = value.slice(0, -1);
|
||||
if (value)
|
||||
host.onTextInput(value);
|
||||
} else
|
||||
host.onTextInput(value);
|
||||
host.onTextInput(value, !pasted);
|
||||
}
|
||||
else {
|
||||
host.onTextInput(value, !pasted);
|
||||
}
|
||||
|
||||
// If editor is no longer focused we quit immediately, since
|
||||
// it means that something else like CLI is in charge now.
|
||||
if (!isFocused()) return false;
|
||||
// it means that something else is in charge now.
|
||||
if (!isFocused())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
copied = false;
|
||||
pasted = false;
|
||||
|
||||
// Safari doesn't fire copy events if no text is selected
|
||||
text.value = PLACEHOLDER;
|
||||
|
|
@ -80,6 +86,13 @@ var TextInput = function(parentNode, host) {
|
|||
}
|
||||
|
||||
var onTextInput = function(e) {
|
||||
setTimeout(function () {
|
||||
if (!inCompostion)
|
||||
sendText(e.data);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
var onKeyPress = function(e) {
|
||||
if (useragent.isIE && text.value.charCodeAt(0) > 128) return;
|
||||
setTimeout(function() {
|
||||
if (!inCompostion)
|
||||
|
|
@ -89,10 +102,6 @@ var TextInput = function(parentNode, host) {
|
|||
|
||||
var onCompositionStart = function(e) {
|
||||
inCompostion = true;
|
||||
if (!useragent.isIE) {
|
||||
sendText();
|
||||
text.value = "";
|
||||
};
|
||||
host.onCompositionStart();
|
||||
if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0);
|
||||
};
|
||||
|
|
@ -105,14 +114,6 @@ var TextInput = function(parentNode, host) {
|
|||
var onCompositionEnd = function(e) {
|
||||
inCompostion = false;
|
||||
host.onCompositionEnd();
|
||||
if (useragent.isGecko) {
|
||||
sendText();
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
if (!inCompostion)
|
||||
sendText();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
var onCopy = function(e) {
|
||||
|
|
@ -143,7 +144,6 @@ var TextInput = function(parentNode, host) {
|
|||
};
|
||||
|
||||
event.addCommandKeyListener(text, host.onCommandKey.bind(host));
|
||||
event.addListener(text, "keypress", onTextInput);
|
||||
if (useragent.isIE) {
|
||||
var keytable = { 13:1, 27:1 };
|
||||
event.addListener(text, "keyup", function (e) {
|
||||
|
|
@ -155,26 +155,41 @@ var TextInput = function(parentNode, host) {
|
|||
inCompostion ? onCompositionUpdate() : onCompositionStart();
|
||||
});
|
||||
};
|
||||
event.addListener(text, "textInput", onTextInput);
|
||||
|
||||
if (text.attachEvent) {
|
||||
// Old IE + Opera
|
||||
event.addListener(text, "propertychange", onKeyPress);
|
||||
}
|
||||
else {
|
||||
if (useragent.isChrome || useragent.isSafari)
|
||||
event.addListener(text, "textInput", onTextInput);
|
||||
else if (useragent.isIE)
|
||||
// IE9
|
||||
event.addListener(text, "textinput", onTextInput);
|
||||
else
|
||||
// All browsers except old IE
|
||||
event.addListener(text, "input", onTextInput);
|
||||
}
|
||||
|
||||
|
||||
event.addListener(text, "paste", function(e) {
|
||||
// Mark that the next input text comes from past.
|
||||
pasted = true;
|
||||
// Some browsers support the event.clipboardData API. Use this to get
|
||||
// the pasted content which increases speed if pasting a lot of lines.
|
||||
if (e.clipboardData && e.clipboardData.getData) {
|
||||
sendText(e.clipboardData.getData("text/plain"));
|
||||
e.preventDefault();
|
||||
} else
|
||||
// If a browser doesn't support any of the things above, use the regular
|
||||
// method to detect the pasted input.
|
||||
{
|
||||
onTextInput();
|
||||
}
|
||||
else {
|
||||
// If a browser doesn't support any of the things above, use the regular
|
||||
// method to detect the pasted input.
|
||||
onKeyPress();
|
||||
}
|
||||
});
|
||||
if (!useragent.isIE) {
|
||||
event.addListener(text, "propertychange", onTextInput);
|
||||
};
|
||||
|
||||
if (useragent.isIE) {
|
||||
event.addListener(text, "beforecopy", function(e) {
|
||||
event.addListener(text, "beforecopy", function(e) {
|
||||
var copyText = host.getCopyText();
|
||||
if(copyText)
|
||||
clipboardData.setData("Text", copyText);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ var Cursor = function(parentEl) {
|
|||
|
||||
(function() {
|
||||
|
||||
this.$padding = 0;
|
||||
this.setPadding = function(padding) {
|
||||
this.$padding = padding;
|
||||
};
|
||||
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
|
@ -66,7 +71,7 @@ var Cursor = function(parentEl) {
|
|||
};
|
||||
|
||||
this.showCursor = function() {
|
||||
this.isVisible = true;
|
||||
this.isVisible = true;
|
||||
dom.removeCssClass(this.cursor, "ace_hidden");
|
||||
this.cursor.style.visibility = "visible";
|
||||
this.restartTimer();
|
||||
|
|
@ -97,7 +102,8 @@ var Cursor = function(parentEl) {
|
|||
|
||||
var position = this.session.selection.getCursor();
|
||||
var pos = this.session.documentToScreenPosition(position);
|
||||
var cursorLeft = Math.round(pos.column * this.config.characterWidth);
|
||||
var cursorLeft = Math.round(this.$padding +
|
||||
pos.column * this.config.characterWidth);
|
||||
var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
|
||||
this.config.lineHeight;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ var Marker = function(parentEl) {
|
|||
|
||||
(function() {
|
||||
|
||||
this.$padding = 0;
|
||||
|
||||
this.setPadding = function(padding) {
|
||||
this.$padding = padding;
|
||||
};
|
||||
this.setSession = function(session) {
|
||||
this.session = session;
|
||||
};
|
||||
|
|
@ -65,7 +70,8 @@ var Marker = function(parentEl) {
|
|||
|
||||
this.config = config;
|
||||
|
||||
var html = [];
|
||||
|
||||
var html = [];
|
||||
for ( var key in this.markers) {
|
||||
var marker = this.markers[key];
|
||||
|
||||
|
|
@ -73,21 +79,28 @@ var Marker = function(parentEl) {
|
|||
if (range.isEmpty()) continue;
|
||||
|
||||
range = range.toScreenRange(this.session);
|
||||
|
||||
if (marker.renderer) {
|
||||
var top = this.$getTop(range.start.row, config);
|
||||
var left = Math.round(range.start.column * config.characterWidth);
|
||||
var left = Math.round(
|
||||
this.$padding + range.start.column * config.characterWidth
|
||||
);
|
||||
marker.renderer(html, range, left, top, config);
|
||||
}
|
||||
else if (range.isMultiLine()) {
|
||||
if (marker.type == "text") {
|
||||
this.drawTextMarker(html, range, marker.clazz, config);
|
||||
} else {
|
||||
this.drawMultiLineMarker(html, range, marker.clazz, config);
|
||||
this.drawMultiLineMarker(
|
||||
html, range, marker.clazz, config,
|
||||
marker.type
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.drawSingleLineMarker(html, range, marker.clazz, config);
|
||||
this.drawSingleLineMarker(
|
||||
html, range, marker.clazz, config,
|
||||
null, marker.type
|
||||
);
|
||||
}
|
||||
}
|
||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||
|
|
@ -97,33 +110,44 @@ var Marker = function(parentEl) {
|
|||
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a marker, which spans a range of text in a single line
|
||||
*/
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
// selection start
|
||||
var row = range.start.row;
|
||||
|
||||
var lineRange = new Range(row, range.start.column,
|
||||
row, this.session.getScreenLastRowColumn(row));
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||
var lineRange = new Range(
|
||||
row, range.start.column,
|
||||
row, this.session.getScreenLastRowColumn(row)
|
||||
);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text");
|
||||
|
||||
// selection end
|
||||
var row = range.end.row;
|
||||
var lineRange = new Range(row, 0, row, range.end.column);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig);
|
||||
row = range.end.row;
|
||||
lineRange = new Range(row, 0, row, range.end.column);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, "text");
|
||||
|
||||
for (var row = range.start.row + 1; row < range.end.row; row++) {
|
||||
for (row = range.start.row + 1; row < range.end.row; row++) {
|
||||
lineRange.start.row = row;
|
||||
lineRange.end.row = row;
|
||||
lineRange.end.column = this.session.getScreenLastRowColumn(row);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text");
|
||||
}
|
||||
};
|
||||
|
||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
/**
|
||||
* Draws a multi line marker, where lines span the full width
|
||||
*/
|
||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig, type) {
|
||||
// from selection start to the end of the line
|
||||
var padding = type === "background" ? 0 : this.$padding;
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
|
||||
var top = this.$getTop(range.start.row, layerConfig);
|
||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||
var left = Math.round(
|
||||
padding + range.start.column * layerConfig.characterWidth
|
||||
);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
|
|
@ -134,35 +158,49 @@ var Marker = function(parentEl) {
|
|||
);
|
||||
|
||||
// from start of the last line to the selection end
|
||||
var top = this.$getTop(range.end.row, layerConfig);
|
||||
var width = Math.round(range.end.column * layerConfig.characterWidth);
|
||||
top = this.$getTop(range.end.row, layerConfig);
|
||||
width = Math.round(range.end.column * layerConfig.characterWidth);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
"height:", height, "px;",
|
||||
"width:", width, "px;",
|
||||
"top:", top, "px;",
|
||||
"width:", width, "px;'></div>"
|
||||
"left:", padding, "px;'></div>"
|
||||
);
|
||||
|
||||
// all the complete lines
|
||||
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
|
||||
height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
|
||||
if (height < 0)
|
||||
return;
|
||||
var top = this.$getTop(range.start.row + 1, layerConfig);
|
||||
top = this.$getTop(range.start.row + 1, layerConfig);
|
||||
width = layerConfig.width;
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
"height:", height, "px;",
|
||||
"width:", layerConfig.width, "px;",
|
||||
"top:", top, "px;'></div>"
|
||||
"width:", width, "px;",
|
||||
"top:", top, "px;",
|
||||
"left:", padding, "px;'></div>"
|
||||
);
|
||||
};
|
||||
|
||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) {
|
||||
/**
|
||||
* Draws a marker which covers one single full line
|
||||
*/
|
||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) {
|
||||
var padding = type === "background" ? 0 : this.$padding;
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
|
||||
|
||||
if (type === "background")
|
||||
var width = layerConfig.width;
|
||||
else
|
||||
width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
|
||||
|
||||
var top = this.$getTop(range.start.row, layerConfig);
|
||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||
var left = Math.round(
|
||||
padding + range.start.column * layerConfig.characterWidth
|
||||
);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
|||
var Text = function(parentEl) {
|
||||
this.element = dom.createElement("div");
|
||||
this.element.className = "ace_layer ace_text-layer";
|
||||
this.element.style.width = "auto";
|
||||
parentEl.appendChild(this.element);
|
||||
|
||||
this.$characterSize = this.$measureSizes() || {width: 0, height: 0};
|
||||
|
|
@ -63,6 +64,12 @@ var Text = function(parentEl) {
|
|||
this.EOL_CHAR = "¬";
|
||||
this.TAB_CHAR = "→";
|
||||
this.SPACE_CHAR = "·";
|
||||
this.$padding = 0;
|
||||
|
||||
this.setPadding = function(padding) {
|
||||
this.$padding = padding;
|
||||
this.element.style.padding = "0 " + padding + "px";
|
||||
};
|
||||
|
||||
this.getLineHeight = function() {
|
||||
return this.$characterSize.height || 1;
|
||||
|
|
@ -186,8 +193,8 @@ var Text = function(parentEl) {
|
|||
var first = Math.max(firstRow, config.firstRow);
|
||||
var last = Math.min(lastRow, config.lastRow);
|
||||
|
||||
var lineElements = this.element.childNodes,
|
||||
lineElementsIdx = 0;
|
||||
var lineElements = this.element.childNodes;
|
||||
var lineElementsIdx = 0;
|
||||
|
||||
for (var row = config.firstRow; row < first; row++) {
|
||||
var foldLine = this.session.getFoldLine(row);
|
||||
|
|
@ -208,7 +215,7 @@ var Text = function(parentEl) {
|
|||
|
||||
var html = [];
|
||||
var tokens = this.session.getTokens(i, i);
|
||||
this.$renderLine(html, i, tokens[0].tokens);
|
||||
this.$renderLine(html, i, tokens[0].tokens, true);
|
||||
lineElement = dom.setInnerHtml(lineElement, html.join(""));
|
||||
|
||||
i = this.session.getRowFoldEnd(i);
|
||||
|
|
@ -264,9 +271,7 @@ var Text = function(parentEl) {
|
|||
if(row > lastRow)
|
||||
break;
|
||||
|
||||
var lineEl = dom.createElement("div");
|
||||
|
||||
lineEl.className = "ace_line";
|
||||
var container = dom.createElement("div");
|
||||
|
||||
var html = [];
|
||||
// Get the tokens per line as there might be some lines in between
|
||||
|
|
@ -275,11 +280,13 @@ var Text = function(parentEl) {
|
|||
// 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);
|
||||
this.$renderLine(html, row, tokens[0].tokens, false);
|
||||
|
||||
// don't use setInnerHtml since we are working with an empty DIV
|
||||
lineEl.innerHTML = html.join("");
|
||||
fragment.appendChild(lineEl);
|
||||
container.innerHTML = html.join("");
|
||||
var lines = container.childNodes
|
||||
while(lines.length)
|
||||
fragment.appendChild(lines[0]);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
|
@ -306,15 +313,13 @@ var Text = function(parentEl) {
|
|||
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>");
|
||||
this.$renderLine(html, row, tokens[0].tokens, false);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
|
@ -344,6 +349,14 @@ var Text = function(parentEl) {
|
|||
return "&";
|
||||
} else if (c == "<") {
|
||||
return "<";
|
||||
} else if (c == "\u3000") {
|
||||
// U+3000 is both invisible AND full-width, so must be handled uniquely
|
||||
var classToUse = self.showInvisibles ? "ace_cjk ace_invisible" : "ace_cjk";
|
||||
var space = self.showInvisibles ? self.SPACE_CHAR : "";
|
||||
screenColumn += 1;
|
||||
return "<span class='" + classToUse + "' style='width:" +
|
||||
(self.config.characterWidth * 2) +
|
||||
"px'>" + space + "</span>";
|
||||
} 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);
|
||||
|
|
@ -371,7 +384,7 @@ var Text = function(parentEl) {
|
|||
return screenColumn + value.length;
|
||||
};
|
||||
|
||||
this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits) {
|
||||
this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits, onlyContents) {
|
||||
var chars = 0;
|
||||
var split = 0;
|
||||
var splitChars;
|
||||
|
|
@ -379,36 +392,44 @@ var Text = function(parentEl) {
|
|||
var screenColumn = 0;
|
||||
var self = this;
|
||||
|
||||
function addToken(token, value) {
|
||||
screenColumn = self.$renderToken(
|
||||
stringBuilder, screenColumn, token, value);
|
||||
}
|
||||
|
||||
if (!splits || splits.length == 0) {
|
||||
if (!splits || splits.length == 0)
|
||||
splitChars = Number.MAX_VALUE;
|
||||
} else {
|
||||
else
|
||||
splitChars = splits[0];
|
||||
}
|
||||
|
||||
stringBuilder.push("<div style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>");
|
||||
if (!onlyContents) {
|
||||
stringBuilder.push("<div class='ace_line' style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>"
|
||||
);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
var value = token.value;
|
||||
|
||||
if (chars + value.length < splitChars) {
|
||||
addToken(token, value);
|
||||
screenColumn = self.$renderToken(
|
||||
stringBuilder, screenColumn, token, value
|
||||
);
|
||||
chars += value.length;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
while (chars + value.length >= splitChars) {
|
||||
addToken(token, value.substring(0, splitChars - chars));
|
||||
screenColumn = self.$renderToken(
|
||||
stringBuilder, screenColumn,
|
||||
token, value.substring(0, splitChars - chars)
|
||||
);
|
||||
value = value.substring(splitChars - chars);
|
||||
chars = splitChars;
|
||||
stringBuilder.push("</div>",
|
||||
"<div style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>");
|
||||
|
||||
if (!onlyContents) {
|
||||
stringBuilder.push("</div>",
|
||||
"<div class='ace_line' style='height:",
|
||||
this.config.lineHeight, "px",
|
||||
"'>"
|
||||
);
|
||||
}
|
||||
|
||||
split ++;
|
||||
screenColumn = 0;
|
||||
|
|
@ -416,33 +437,35 @@ var Text = function(parentEl) {
|
|||
}
|
||||
if (value.length != 0) {
|
||||
chars += value.length;
|
||||
addToken(token, value);
|
||||
screenColumn = self.$renderToken(
|
||||
stringBuilder, screenColumn, token, value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showInvisibles) {
|
||||
if (lastRow !== this.session.getLength() - 1) {
|
||||
if (lastRow !== this.session.getLength() - 1)
|
||||
stringBuilder.push("<span class='ace_invisible'>" + this.EOL_CHAR + "</span>");
|
||||
} else {
|
||||
else
|
||||
stringBuilder.push("<span class='ace_invisible'>" + this.EOF_CHAR + "</span>");
|
||||
}
|
||||
}
|
||||
stringBuilder.push("</div>");
|
||||
if (!onlyContents)
|
||||
stringBuilder.push("</div>");
|
||||
};
|
||||
|
||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||
this.$renderLine = function(stringBuilder, row, tokens, onlyContents) {
|
||||
// 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);
|
||||
this.$renderLineCore(stringBuilder, row, tokens, splits, onlyContents);
|
||||
} else {
|
||||
this.$renderFoldLine(stringBuilder, row, tokens);
|
||||
this.$renderFoldLine(stringBuilder, row, tokens, onlyContents);
|
||||
}
|
||||
};
|
||||
|
||||
this.$renderFoldLine = function(stringBuilder, row, tokens) {
|
||||
this.$renderFoldLine = function(stringBuilder, row, tokens, onlyContents) {
|
||||
var session = this.session,
|
||||
foldLine = session.getFoldLine(row),
|
||||
renderTokens = [];
|
||||
|
|
@ -505,11 +528,14 @@ var Text = function(parentEl) {
|
|||
|
||||
// TODO: Build a fake splits array!
|
||||
var splits = this.session.$useWrapMode?this.session.$wrapData[row]:null;
|
||||
this.$renderLineCore(stringBuilder, row, renderTokens, splits);
|
||||
this.$renderLineCore(stringBuilder, row, renderTokens, splits, onlyContents);
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
clearInterval(this.$pollSizeChangesTimer);
|
||||
if (this.$measureNode)
|
||||
this.$measureNode.parentNode.removeChild(this.$measureNode);
|
||||
delete this.$measureNode;
|
||||
};
|
||||
|
||||
}).call(Text.prototype);
|
||||
|
|
|
|||
|
|
@ -49,29 +49,52 @@ var JavaScriptMode = require("ace/mode/javascript").Mode;
|
|||
|
||||
module.exports = {
|
||||
|
||||
"test: render line with hard tabs should render the same as lines with soft tabs" : function() {
|
||||
var session = new EditSession("a\ta\ta\t\na a a \n");
|
||||
session.setMode(new JavaScriptMode());
|
||||
var textLayer = new TextLayer(document.createElement("div"));
|
||||
textLayer.setSession(session);
|
||||
textLayer.$computeTabString();
|
||||
textLayer.config = {
|
||||
setUp: function(next) {
|
||||
this.session = new EditSession("");
|
||||
this.session.setMode(new JavaScriptMode());
|
||||
this.textLayer = new TextLayer(document.createElement("div"));
|
||||
this.textLayer.setSession(this.session);
|
||||
this.textLayer.config = {
|
||||
characterWidth: 10,
|
||||
lineHeight: 20
|
||||
};
|
||||
next()
|
||||
},
|
||||
|
||||
"test: render line with hard tabs should render the same as lines with soft tabs" : function() {
|
||||
this.session.setValue("a\ta\ta\t\na a a \n");
|
||||
this.textLayer.$computeTabString();
|
||||
|
||||
// row with hard tabs
|
||||
var row = 0;
|
||||
var tokens = session.getTokens(row, row)[0].tokens;
|
||||
var tokens = this.session.getTokens(row, row)[0].tokens;
|
||||
var stringBuilder = [];
|
||||
textLayer.$renderLine(stringBuilder, row, tokens);
|
||||
this.textLayer.$renderLine(stringBuilder, row, tokens);
|
||||
|
||||
// row with soft tabs
|
||||
row = 1;
|
||||
tokens = session.getTokens(row, row)[0].tokens;
|
||||
tokens = this.session.getTokens(row, row)[0].tokens;
|
||||
var stringBuilder2 = [];
|
||||
textLayer.$renderLine(stringBuilder2, row, tokens);
|
||||
this.textLayer.$renderLine(stringBuilder2, row, tokens);
|
||||
assert.equal(stringBuilder.join(""), stringBuilder2.join(""));
|
||||
},
|
||||
|
||||
"test rendering width of ideographic space (U+3000)" : function() {
|
||||
this.session.setValue("\u3000");
|
||||
|
||||
var tokens = this.session.getTokens(0, 0)[0].tokens;
|
||||
var stringBuilder = [];
|
||||
this.textLayer.$renderLine(stringBuilder, 0, tokens, true);
|
||||
assert.equal(stringBuilder.join(""), "<span class='ace_cjk' style='width:20px'></span>");
|
||||
|
||||
this.textLayer.setShowInvisibles(true);
|
||||
var stringBuilder = [];
|
||||
this.textLayer.$renderLine(stringBuilder, 0, tokens, true);
|
||||
assert.equal(
|
||||
stringBuilder.join(""),
|
||||
"<span class='ace_cjk ace_invisible' style='width:20px'>" + this.textLayer.SPACE_CHAR + "</span>"
|
||||
+ "<span class='ace_invisible'>¶</span>"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ 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();
|
||||
|
|
@ -76,11 +76,13 @@ var CstyleBehaviour = function () {
|
|||
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 openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1});
|
||||
if (!openBracePos)
|
||||
return false;
|
||||
|
||||
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]
|
||||
|
|
@ -89,15 +91,15 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
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);
|
||||
range.end.column++;
|
||||
return range;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -134,15 +136,15 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
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);
|
||||
range.end.column++;
|
||||
return range;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -161,17 +163,17 @@ var CstyleBehaviour = function () {
|
|||
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") {
|
||||
|
|
@ -184,7 +186,7 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
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 {
|
||||
|
|
@ -205,20 +207,20 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
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);
|
||||
range.end.column++;
|
||||
return range;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
oop.inherits(CstyleBehaviour, Behaviour);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,96 +67,102 @@ var c_cppHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant", // <CONSTANT>
|
||||
regex : "<[a-zA-Z0-9.]+>"
|
||||
}, {
|
||||
}, {
|
||||
token : "keyword", // pre-compiler directivs
|
||||
regex : "(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,78 +49,78 @@ 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(" ")
|
||||
'*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(" ")
|
||||
'throw try var').split(" ")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
|
|
@ -133,98 +133,82 @@ var ClojureHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
|
||||
{
|
||||
token : "comment",
|
||||
regex : ";.*$"
|
||||
}, {
|
||||
{
|
||||
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", //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";
|
||||
}, {
|
||||
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"
|
||||
},
|
||||
{
|
||||
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'
|
||||
}
|
||||
}, {
|
||||
token : "string.regexp", //Regular Expressions
|
||||
regex : '/#"(?:\.|(\\\")|[^\""\n])*"/g'
|
||||
}
|
||||
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : "^\=end$",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -37,146 +37,158 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
require("pilot/oop").inherits(
|
||||
CoffeeHighlightRules,
|
||||
require("ace/mode/text_highlight_rules").TextHighlightRules);
|
||||
require("pilot/oop").inherits(CoffeeHighlightRules,
|
||||
require("ace/mode/text_highlight_rules").TextHighlightRules);
|
||||
|
||||
function CoffeeHighlightRules() {
|
||||
var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"
|
||||
, keywordend = "(?![$\\w]|\\s*:)"
|
||||
, stringfill = {token: "string", regex: ".+"}
|
||||
;
|
||||
this.$rules =
|
||||
{ start:
|
||||
[ { token: "identifier"
|
||||
, regex: "(?:@|(?:\\.|::)\\s*)" + identifier
|
||||
}
|
||||
, { token: "keyword"
|
||||
, regex: "(?:t(?:h(?:is|row|en)|ry|ypeof)|s(?:uper|witch)|return|b(?:reak|y)|c(?:ontinue|atch|lass)|i(?:n(?:stanceof)?|s(?:nt)?|f)|e(?:lse|xtends)|f(?:or (?:own)?|inally|unction)|wh(?:ile|en)|n(?:ew|ot?)|d(?:e(?:lete|bugger)|o)|loop|o(?:ff?|[rn])|un(?:less|til)|and|yes)" + keywordend
|
||||
}
|
||||
, { token: "constant.language"
|
||||
, regex: "(?:true|false|null|undefined)" + keywordend
|
||||
}
|
||||
, { token: "invalid.illegal"
|
||||
, regex: "(?:c(?:ase|onst)|default|function|v(?:ar|oid)|with|e(?:num|xport)|i(?:mplements|nterface)|let|p(?:ackage|r(?:ivate|otected)|ublic)|static|yield|__(?:hasProp|extends|slice|bind|indexOf))" + keywordend
|
||||
}
|
||||
, { token: "language.support.class"
|
||||
, regex: "(?:Array|Boolean|Date|Function|Number|Object|R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|TypeError|URIError)" + keywordend
|
||||
}
|
||||
, { token: "language.support.function"
|
||||
, regex: "(?:Math|JSON|is(?:NaN|Finite)|parse(?:Int|Float)|encodeURI(?:Component)?|decodeURI(?:Component)?)" + keywordend
|
||||
}
|
||||
, { token: "identifier"
|
||||
, regex: identifier
|
||||
}
|
||||
, { token: "constant.numeric"
|
||||
, regex: "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "'''"
|
||||
, next : "qdoc"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: '"""'
|
||||
, next : "qqdoc"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "'"
|
||||
, next : "qstring"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: '"'
|
||||
, next : "qqstring"
|
||||
}
|
||||
, { token: "string"
|
||||
, regex: "`"
|
||||
, next : "js"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "///"
|
||||
, next : "heregex"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: "###(?!#)"
|
||||
, next : "comment"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: "#.*"
|
||||
}
|
||||
, { token: "lparen"
|
||||
, regex: "[({[]"
|
||||
}
|
||||
, { token: "rparen"
|
||||
, regex: "[\\]})]"
|
||||
}
|
||||
, { token: "keyword.operator"
|
||||
, regex: "\\S+"
|
||||
}
|
||||
, { token: "text"
|
||||
, regex: "\\s+"
|
||||
}
|
||||
]
|
||||
, qdoc:
|
||||
[ { token: "string"
|
||||
, regex: ".*?'''"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qqdoc:
|
||||
[ { token: "string"
|
||||
, regex: '.*?"""'
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qstring:
|
||||
[ { token: "string"
|
||||
, regex: "[^\\\\']*(?:\\\\.[^\\\\']*)*'"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, qqstring:
|
||||
[ { token: "string"
|
||||
, regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"'
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, js:
|
||||
[ { token: "string"
|
||||
, regex: "[^\\\\`]*(?:\\\\.[^\\\\`]*)*`"
|
||||
, next : "start"
|
||||
}
|
||||
, stringfill
|
||||
]
|
||||
, heregex:
|
||||
[ { token: "string.regex"
|
||||
, regex: '.*?///[imgy]{0,4}'
|
||||
, next : "start"
|
||||
}
|
||||
, { token: "comment.regex"
|
||||
, regex: "\\s+(?:#.*)?"
|
||||
}
|
||||
, { token: "string.regex"
|
||||
, regex: "\\S+"
|
||||
}
|
||||
]
|
||||
, comment:
|
||||
[ { token: "comment"
|
||||
, regex: '.*?###'
|
||||
, next : "start"
|
||||
}
|
||||
, { token: "comment"
|
||||
, regex: ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
function CoffeeHighlightRules() {
|
||||
var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
|
||||
var keywordend = "(?![$\\w]|\\s*:)";
|
||||
var stringfill = {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
};
|
||||
|
||||
this.$rules = {
|
||||
start : [
|
||||
{
|
||||
token : "identifier",
|
||||
regex : "(?:@|(?:\\.|::)\\s*)" + identifier
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "(?:t(?:h(?:is|row|en)|ry|ypeof)|s(?:uper|witch)|return|b(?:reak|y)|c(?:ontinue|atch|lass)|i(?:n(?:stanceof)?|s(?:nt)?|f)|e(?:lse|xtends)|f(?:or (?:own)?|inally|unction)|wh(?:ile|en)|n(?:ew|ot?)|d(?:e(?:lete|bugger)|o)|loop|o(?:ff?|[rn])|un(?:less|til)|and|yes)"
|
||||
+ keywordend
|
||||
}, {
|
||||
token : "constant.language",
|
||||
regex : "(?:true|false|null|undefined)" + keywordend
|
||||
}, {
|
||||
token : "invalid.illegal",
|
||||
regex : "(?:c(?:ase|onst)|default|function|v(?:ar|oid)|with|e(?:num|xport)|i(?:mplements|nterface)|let|p(?:ackage|r(?:ivate|otected)|ublic)|static|yield|__(?:hasProp|extends|slice|bind|indexOf))"
|
||||
+ keywordend
|
||||
}, {
|
||||
token : "language.support.class",
|
||||
regex : "(?:Array|Boolean|Date|Function|Number|Object|R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|TypeError|URIError)"
|
||||
+ keywordend
|
||||
}, {
|
||||
token : "language.support.function",
|
||||
regex : "(?:Math|JSON|is(?:NaN|Finite)|parse(?:Int|Float)|encodeURI(?:Component)?|decodeURI(?:Component)?)"
|
||||
+ keywordend
|
||||
}, {
|
||||
token : "identifier",
|
||||
regex : identifier
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : "'''",
|
||||
next : "qdoc"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '"""',
|
||||
next : "qqdoc"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : "'",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '"',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : "`",
|
||||
next : "js"
|
||||
}, {
|
||||
token : "string.regex",
|
||||
merge : true,
|
||||
regex : "///",
|
||||
next : "heregex"
|
||||
}, {
|
||||
token : "string.regex",
|
||||
regex : "/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : "###(?!#)",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "#.*"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[({[]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\]})]"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\S+"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}],
|
||||
|
||||
qdoc : [{
|
||||
token : "string",
|
||||
regex : ".*?'''",
|
||||
next : "start"
|
||||
}, stringfill],
|
||||
|
||||
qqdoc : [{
|
||||
token : "string",
|
||||
regex : '.*?"""',
|
||||
next : "start"
|
||||
}, stringfill],
|
||||
|
||||
qstring : [{
|
||||
token : "string",
|
||||
regex : "[^\\\\']*(?:\\\\.[^\\\\']*)*'",
|
||||
next : "start"
|
||||
}, stringfill],
|
||||
|
||||
qqstring : [{
|
||||
token : "string",
|
||||
regex : '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',
|
||||
next : "start"
|
||||
}, stringfill],
|
||||
|
||||
js : [{
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : "[^\\\\`]*(?:\\\\.[^\\\\`]*)*`",
|
||||
next : "start"
|
||||
}, stringfill],
|
||||
|
||||
heregex : [{
|
||||
token : "string.regex",
|
||||
regex : '.*?///[imgy]{0,4}',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment.regex",
|
||||
regex : "\\s+(?:#.*)?"
|
||||
}, {
|
||||
token : "string.regex",
|
||||
merge : true,
|
||||
regex : "\\S+"
|
||||
}],
|
||||
|
||||
comment : [{
|
||||
token : "comment",
|
||||
regex : '.*?###',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
exports.CoffeeHighlightRules = CoffeeHighlightRules;
|
||||
exports.CoffeeHighlightRules = CoffeeHighlightRules;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
var CSharpHighlightRules = function() {
|
||||
|
||||
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("|")
|
||||
("abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
|
|
@ -21,94 +21,72 @@ var CSharpHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*",
|
||||
merge : true,
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -125,6 +125,7 @@ var CssHighlightRules = function() {
|
|||
var base_ruleset = [
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "ruleset_comment"
|
||||
},{
|
||||
|
|
@ -212,66 +213,56 @@ var CssHighlightRules = function() {
|
|||
}
|
||||
];
|
||||
|
||||
var ruleset = lang.copyArray( base_ruleset );
|
||||
ruleset.unshift(
|
||||
{
|
||||
var ruleset = lang.copyArray(base_ruleset);
|
||||
ruleset.unshift({
|
||||
token : "rparen",
|
||||
regex : "\}",
|
||||
regex : "\\}",
|
||||
next: "start"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var media_ruleset = lang.copyArray( base_ruleset );
|
||||
media_ruleset.unshift(
|
||||
{
|
||||
media_ruleset.unshift({
|
||||
token : "rparen",
|
||||
regex : "\}",
|
||||
regex : "\\}",
|
||||
next: "media"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var base_comment = [
|
||||
{
|
||||
var base_comment = [{
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
];
|
||||
}];
|
||||
|
||||
var comment = lang.copyArray( base_comment );
|
||||
comment.unshift(
|
||||
{
|
||||
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(
|
||||
{
|
||||
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(
|
||||
{
|
||||
var ruleset_comment = lang.copyArray(base_comment);
|
||||
ruleset_comment.unshift({
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "ruleset"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
"start" : [{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token: "lparen",
|
||||
regex: "{",
|
||||
regex: "\\{",
|
||||
next: "ruleset"
|
||||
}, {
|
||||
token: "string",
|
||||
|
|
@ -293,15 +284,16 @@ var CssHighlightRules = function() {
|
|||
|
||||
"media" : [ {
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "media_comment"
|
||||
}, {
|
||||
token: "lparen",
|
||||
regex: "{",
|
||||
regex: "\\{",
|
||||
next: "media_ruleset"
|
||||
},{
|
||||
token: "string",
|
||||
regex: "}",
|
||||
regex: "\\}",
|
||||
next: "start"
|
||||
},{
|
||||
token: "keyword",
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ var CssMode = require("ace/mode/css").Mode;
|
|||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "CSS",
|
||||
|
||||
setUp : function() {
|
||||
this.mode = new CssMode();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ var CssMode = require("ace/mode/css").Mode;
|
|||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "CSS Tokenizer",
|
||||
|
||||
setUp : function() {
|
||||
this.tokenizer = new CssMode().getTokenizer();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ oop.inherits(Worker, Mirror);
|
|||
var value = this.doc.getValue();
|
||||
|
||||
result = CSSLint.verify(value);
|
||||
this.sender.emit("csslint", result.messages);
|
||||
this.sender.emit("csslint", result.messages.map(function(msg) {
|
||||
delete msg.rule;
|
||||
return msg;
|
||||
}));
|
||||
};
|
||||
|
||||
}).call(Worker.prototype);
|
||||
|
|
|
|||
|
|
@ -48,15 +48,19 @@ var DocCommentHighlightRules = function() {
|
|||
regex : "@[\\w\\d_]+" // TODO: fix email addresses
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
merge : true,
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
merge : true,
|
||||
regex : "TODO"
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
merge : true,
|
||||
regex : "[^@\\*]+"
|
||||
}, {
|
||||
token : "comment.doc",
|
||||
merge : true,
|
||||
regex : "."
|
||||
}]
|
||||
};
|
||||
|
|
@ -69,14 +73,16 @@ oop.inherits(DocCommentHighlightRules, TextHighlightRules);
|
|||
this.getStartRule = function(start) {
|
||||
return {
|
||||
token : "comment.doc", // doc comment
|
||||
merge : true,
|
||||
regex : "\\/\\*(?=\\*)",
|
||||
next: start
|
||||
next : start
|
||||
};
|
||||
};
|
||||
|
||||
this.getEndRule = function (start) {
|
||||
return {
|
||||
token : "comment.doc", // closing comment
|
||||
merge : true,
|
||||
regex : "\\*\\/",
|
||||
next : start
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
|||
var GroovyHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("assert|with|abstract|continue|for|new|switch|" +
|
||||
"assert|default|goto|package|synchronized|" +
|
||||
"boolean|do|if|private|this|" +
|
||||
"break|double|implements|protected|throw|" +
|
||||
"byte|else|import|public|throws|" +
|
||||
"case|enum|instanceof|return|transient|" +
|
||||
"catch|extends|int|short|try|" +
|
||||
"char|final|interface|static|void|" +
|
||||
"class|finally|long|strictfp|volatile|" +
|
||||
"def|float|native|super|while").split("|")
|
||||
("assert|with|abstract|continue|for|new|switch|" +
|
||||
"assert|default|goto|package|synchronized|" +
|
||||
"boolean|do|if|private|this|" +
|
||||
"break|double|implements|protected|throw|" +
|
||||
"byte|else|import|public|throws|" +
|
||||
"case|enum|instanceof|return|transient|" +
|
||||
"catch|extends|int|short|try|" +
|
||||
"char|final|interface|static|void|" +
|
||||
"class|finally|long|strictfp|volatile|" +
|
||||
"def|float|native|super|while").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
|
|
@ -59,98 +59,76 @@ var GroovyHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (langClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (importClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ var HtmlHighlightRules = function() {
|
|||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*$',
|
||||
next : state + "-qqstring"
|
||||
}, {
|
||||
|
|
@ -61,6 +62,7 @@ var HtmlHighlightRules = function() {
|
|||
regex : "'.*?'"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*$",
|
||||
next : state + "-qstring"
|
||||
}]
|
||||
|
|
@ -69,10 +71,12 @@ var HtmlHighlightRules = function() {
|
|||
function multiLineString(quote, state) {
|
||||
return [{
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : ".*" + quote,
|
||||
next : state
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}]
|
||||
}
|
||||
|
|
@ -80,6 +84,7 @@ var HtmlHighlightRules = function() {
|
|||
this.$rules = {
|
||||
start : [ {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : "<\\!\\[CDATA\\[",
|
||||
next : "cdata"
|
||||
}, {
|
||||
|
|
@ -87,6 +92,7 @@ var HtmlHighlightRules = function() {
|
|||
regex : "<\\?.*?\\?>"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : "<\\!--",
|
||||
next : "comment"
|
||||
}, {
|
||||
|
|
@ -158,9 +164,11 @@ var HtmlHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
} ],
|
||||
|
||||
|
|
@ -170,6 +178,7 @@ var HtmlHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
} ]
|
||||
};
|
||||
|
|
@ -194,4 +203,4 @@ var HtmlHighlightRules = function() {
|
|||
oop.inherits(HtmlHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.HtmlHighlightRules = HtmlHighlightRules;
|
||||
});
|
||||
});
|
||||
|
|
@ -9,16 +9,16 @@ var JavaHighlightRules = function() {
|
|||
|
||||
// taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
|
||||
var keywords = lang.arrayToMap(
|
||||
("abstract|continue|for|new|switch|" +
|
||||
"assert|default|goto|package|synchronized|" +
|
||||
"boolean|do|if|private|this|" +
|
||||
"break|double|implements|protected|throw|" +
|
||||
"byte|else|import|public|throws|" +
|
||||
"case|enum|instanceof|return|transient|" +
|
||||
"catch|extends|int|short|try|" +
|
||||
"char|final|interface|static|void|" +
|
||||
"class|finally|long|strictfp|volatile|" +
|
||||
"const|float|native|super|while").split("|")
|
||||
("abstract|continue|for|new|switch|" +
|
||||
"assert|default|goto|package|synchronized|" +
|
||||
"boolean|do|if|private|this|" +
|
||||
"break|double|implements|protected|throw|" +
|
||||
"byte|else|import|public|throws|" +
|
||||
"case|enum|instanceof|return|transient|" +
|
||||
"catch|extends|int|short|try|" +
|
||||
"char|final|interface|static|void|" +
|
||||
"class|finally|long|strictfp|volatile|" +
|
||||
"const|float|native|super|while").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
|
|
@ -60,98 +60,76 @@ var JavaHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (langClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (importClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ oop.inherits(Mode, TextMode);
|
|||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
var match = line.match(/^.*[\{\(\[\:]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var unicode = require("ace/unicode");
|
||||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
|
|
@ -60,6 +61,13 @@ var JavaScriptHighlightRules = function() {
|
|||
"public|interface|package|protected|static").split("|")
|
||||
);
|
||||
|
||||
// TODO: Unicode escape sequences
|
||||
var identifierRe = "[" + unicode.packages.L + "\\$_]["
|
||||
+ unicode.packages.L
|
||||
+ unicode.packages.Mn + unicode.packages.Mc
|
||||
+ unicode.packages.Nd
|
||||
+ unicode.packages.Pc + "\\$_]*\\b";
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
|
|
@ -72,16 +80,15 @@ var JavaScriptHighlightRules = function() {
|
|||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
|
|
@ -89,6 +96,7 @@ var JavaScriptHighlightRules = function() {
|
|||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
|
|
@ -115,18 +123,22 @@ var JavaScriptHighlightRules = function() {
|
|||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
regex : identifierRe
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
regex : "[[({]",
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\/=?",
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: "^#!.*$"
|
||||
|
|
@ -135,6 +147,26 @@ var JavaScriptHighlightRules = function() {
|
|||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
// regular expressions are only allowed after certain tokens. This
|
||||
// makes sure we don't mix up regexps with the divison operator
|
||||
"regex_allowed": [
|
||||
{
|
||||
token: "string.regexp",
|
||||
regex: "\\/(?:(?:\\[(?:\\\\]|[^\\]])+\\])"
|
||||
+ "|(?:\\\\/|[^\\]/]))*"
|
||||
+ "[/]\\w*",
|
||||
next: "start"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
// immediately return to the start mode without matching
|
||||
// anything
|
||||
token: "empty",
|
||||
regex: "",
|
||||
next: "start"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
|
|
@ -142,6 +174,7 @@ var JavaScriptHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
|
|
@ -152,6 +185,7 @@ var JavaScriptHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
|
|
@ -162,6 +196,7 @@ var JavaScriptHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -75,12 +75,12 @@ module.exports = {
|
|||
},
|
||||
|
||||
"test: toggle comment lines twice should return the original text" : function() {
|
||||
var session = new EditSession([" abc", "cde", "fg"]);
|
||||
|
||||
this.mode.toggleCommentLines("start", session, 0, 2);
|
||||
this.mode.toggleCommentLines("start", session, 0, 2);
|
||||
assert.equal([" abc", "cde", "fg"].join("\n"), session.toString());
|
||||
},
|
||||
var session = new EditSession([" abc", "cde", "fg"]);
|
||||
|
||||
this.mode.toggleCommentLines("start", session, 0, 2);
|
||||
this.mode.toggleCommentLines("start", session, 0, 2);
|
||||
assert.equal([" abc", "cde", "fg"].join("\n"), session.toString());
|
||||
},
|
||||
|
||||
"test: toggle comment on multiple lines with one commented line prepend '//' to each line" : function() {
|
||||
var session = new EditSession(["// abc", "//cde", "fg"]);
|
||||
|
|
@ -99,6 +99,10 @@ module.exports = {
|
|||
"test: auto indent after opening brace" : function() {
|
||||
assert.equal(" ", this.mode.getNextLineIndent("start", "if () {", " "));
|
||||
},
|
||||
|
||||
"test: auto indent after case" : function() {
|
||||
assert.equal(" ", this.mode.getNextLineIndent("start", "case 'juhu':", " "));
|
||||
},
|
||||
|
||||
"test: no auto indent after opening brace in multi line comment" : function() {
|
||||
assert.equal("", this.mode.getNextLineIndent("start", "/*if () {", " "));
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ var JavaScriptMode = require("ace/mode/javascript").Mode;
|
|||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "JavaScript Tokenizer",
|
||||
|
||||
setUp : function() {
|
||||
this.tokenizer = new JavaScriptMode().getTokenizer();
|
||||
},
|
||||
|
|
@ -91,22 +94,54 @@ module.exports = {
|
|||
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
assert.equal(3, tokens.length);
|
||||
assert.equal(7, tokens.length);
|
||||
assert.equal("lparen", tokens[0].type);
|
||||
assert.equal("text", tokens[1].type);
|
||||
assert.equal("rparen", tokens[2].type);
|
||||
assert.equal("lparen", tokens[1].type);
|
||||
assert.equal("lparen", tokens[2].type);
|
||||
assert.equal("text", tokens[3].type);
|
||||
assert.equal("rparen", tokens[4].type);
|
||||
assert.equal("rparen", tokens[5].type);
|
||||
assert.equal("rparen", tokens[6].type);
|
||||
},
|
||||
|
||||
|
||||
"test for last rule in ruleset to catch capturing group bugs" : function() {
|
||||
var tokens = this.tokenizer.getLineTokens("}", "start").tokens;
|
||||
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal("rparen", tokens[0].type);
|
||||
},
|
||||
|
||||
"test tokenize regular expressions": function() {
|
||||
|
||||
"test tokenize arithmetic expression which looks like a regexp": function() {
|
||||
var tokens = this.tokenizer.getLineTokens("a/b/c", "start").tokens;
|
||||
assert.equal(5, tokens.length);
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens("a/=b/c", "start").tokens;
|
||||
assert.equal(5, tokens.length);
|
||||
},
|
||||
|
||||
"test tokenize reg exps" : function() {
|
||||
var tokens = this.tokenizer.getLineTokens("a=/b/g", "start").tokens;
|
||||
assert.equal(3, tokens.length);
|
||||
assert.equal("string.regexp", tokens[2].type);
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens("a+/b/g", "start").tokens;
|
||||
assert.equal(3, tokens.length);
|
||||
assert.equal("string.regexp", tokens[2].type);
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens("a = 1 + /2 + 1/b", "start").tokens;
|
||||
assert.equal(9, tokens.length);
|
||||
assert.equal("string.regexp", tokens[8].type);
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens("a=/a/ / /a/", "start").tokens;
|
||||
assert.equal(7, tokens.length);
|
||||
assert.equal("string.regexp", tokens[2].type);
|
||||
assert.equal("string.regexp", tokens[6].type);
|
||||
},
|
||||
|
||||
|
||||
"test tokenize identifier with umlauts": function() {
|
||||
var tokens = this.tokenizer.getLineTokens("füße", "start").tokens;
|
||||
assert.equal(1, tokens.length);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -237,9 +237,8 @@ var OcamlHighlightRules = function() {
|
|||
"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("|"));
|
||||
"Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak"
|
||||
).split("|"));
|
||||
|
||||
var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
|
||||
var octInteger = "(?:0[oO]?[0-7]+)";
|
||||
|
|
@ -262,6 +261,7 @@ var OcamlHighlightRules = function() {
|
|||
},
|
||||
{
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : '\\(\\*.*',
|
||||
next : "comment"
|
||||
},
|
||||
|
|
@ -275,6 +275,7 @@ var OcamlHighlightRules = function() {
|
|||
},
|
||||
{
|
||||
token : "string", // " string
|
||||
merge : true,
|
||||
regex : '"',
|
||||
next : "qstring"
|
||||
},
|
||||
|
|
@ -328,6 +329,7 @@ var OcamlHighlightRules = function() {
|
|||
},
|
||||
{
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
|
|
@ -339,6 +341,7 @@ var OcamlHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ var PerlHighlightRules = function() {
|
|||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
|
|
@ -100,6 +101,7 @@ var PerlHighlightRules = function() {
|
|||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
|
|
@ -141,6 +143,7 @@ var PerlHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
|
|
@ -151,6 +154,7 @@ var PerlHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -96,6 +96,7 @@ var PythonHighlightRules = function() {
|
|||
regex : strPre + '"{3}(?:[^\\\\]|\\\\.)*?"{3}'
|
||||
}, {
|
||||
token : "string", // multi line """ string start
|
||||
merge : true,
|
||||
regex : strPre + '"{3}.*$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
|
|
@ -106,6 +107,7 @@ var PythonHighlightRules = function() {
|
|||
regex : strPre + "'{3}(?:[^\\\\]|\\\\.)*?'{3}"
|
||||
}, {
|
||||
token : "string", // multi line ''' string start
|
||||
merge : true,
|
||||
regex : strPre + "'{3}.*$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
|
|
@ -158,14 +160,16 @@ var PythonHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
} ],
|
||||
"qstring" : [ {
|
||||
token : "string", // multi line ''' string end
|
||||
token : "string", // multi line ''' string end
|
||||
regex : "(?:[^\\\\]|\\\\.)*?'{3}",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
} ]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,86 +98,91 @@ var RubyHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
{
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "^\=begin$",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
}, {
|
||||
token : "string", // backtick string
|
||||
regex : "[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"
|
||||
}, {
|
||||
}, {
|
||||
token : "text", // namespaces aren't symbols
|
||||
regex : "::"
|
||||
}, {
|
||||
token : "variable.instancce", // instance variable
|
||||
regex : "@{1,2}(?:[a-zA-Z_]|\d)+"
|
||||
}, {
|
||||
}, {
|
||||
token : "variable.class", // class name
|
||||
regex : "[A-Z](?:[a-zA-Z_]|\d)+"
|
||||
}, {
|
||||
}, {
|
||||
token : "string", // symbol
|
||||
regex : "[:](?:[a-zA-Z]|\d)+"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "self")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
regex : "[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "self")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (builtinVariables.hasOwnProperty(value))
|
||||
return "variable.language";
|
||||
else if (builtinFunctions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : "^\=end$",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
|
|
|||
115
lib/ace/mode/ruby_tokenizer_test.js
Normal file
115
lib/ace/mode/ruby_tokenizer_test.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/* ***** 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>
|
||||
* Trent Ogren <me AT trentogren 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");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var RubyMode = require("ace/mode/ruby").Mode;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "Ruby Tokenizer",
|
||||
|
||||
setUp : function() {
|
||||
this.tokenizer = new RubyMode().getTokenizer();
|
||||
},
|
||||
|
||||
"test: symbol tokenizer" : function() {
|
||||
// https://gist.github.com/1072693
|
||||
assertValidTokens(this.tokenizer, "string",
|
||||
[":@thing", ":$thing", ":_thing", ":thing", ":Thing", ":thing1", ":thing_a",
|
||||
":THING", ":thing!", ":thing=", ":thing?", ":t?"]);
|
||||
assertInvalidTokens(this.tokenizer, "string",
|
||||
[":", ":@", ":$", ":1", ":1thing", ":th?ing", ":thi=ng", ":1thing",
|
||||
":th!ing", ":thing#"]);
|
||||
},
|
||||
|
||||
"test: namespaces aren't symbols" : function() {
|
||||
var line = "Namespaced::Class";
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
assert.equal(3, tokens.length);
|
||||
assert.equal("variable.class", tokens[0].type);
|
||||
assert.equal("text", tokens[1].type);
|
||||
assert.equal("variable.class", tokens[2].type);
|
||||
},
|
||||
|
||||
"test: hex tokenizer" : function() {
|
||||
assertValidTokens(this.tokenizer, "constant.numeric",
|
||||
["0x9a", "0XA1", "0x9_a"]);
|
||||
assertInvalidTokens(this.tokenizer, "constant.numeric",
|
||||
["0x", "0x_9a", "0x9a_"]);
|
||||
},
|
||||
|
||||
"test: float tokenizer" : function() {
|
||||
assertValidTokens(this.tokenizer, "constant.numeric",
|
||||
["1", "+1", "-1", "12_345", "0.000_1"]);
|
||||
assertInvalidTokens(this.tokenizer, "constant.numeric",
|
||||
["_", "_1", "1_", "1_.0", "0._1"]);
|
||||
}
|
||||
};
|
||||
|
||||
function assertValidTokens(tokenizer, tokenType, validTokens) {
|
||||
for (var i = 0, length = validTokens.length; i < length; i++) {
|
||||
var validToken = validTokens[i],
|
||||
tokens = tokenizer.getLineTokens(validToken, "start").tokens;
|
||||
assert.equal(tokens[0].value, validToken,
|
||||
'"' + validToken + '" should be one token');
|
||||
assert.equal(tokens[0].type, tokenType,
|
||||
'"' + validToken + '" should be a "' + tokenType + '" token');
|
||||
}
|
||||
}
|
||||
|
||||
function assertInvalidTokens(tokenizer, tokenType, invalidTokens) {
|
||||
for (var i = 0, length = invalidTokens.length; i < length; i++) {
|
||||
var invalidToken = invalidTokens[i],
|
||||
tokens = tokenizer.getLineTokens(invalidToken, "start").tokens;
|
||||
assert.ok(tokens[0].type !== tokenType || tokens[0].value !== invalidToken,
|
||||
'"' + invalidToken + '" is not a valid "' + tokenType + '"');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
130
lib/ace/mode/scad.js
Normal file
130
lib/ace/mode/scad.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Ajax.org Code Editor (ACE).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ajax.org B.V.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Gastón Kleiman <gaston.kleiman AT gmail DOT com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var TextMode = require("ace/mode/text").Mode;
|
||||
var Tokenizer = require("ace/tokenizer").Tokenizer;
|
||||
var scadHighlightRules = require("ace/mode/scad_highlight_rules").scadHighlightRules;
|
||||
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 scadHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = new CstyleBehaviour();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)\/\//;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, "//");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
} else if (state == "doc-start") {
|
||||
if (endState == "start") {
|
||||
return "";
|
||||
}
|
||||
var match = line.match(/^\s*(\/?)\*/);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
indent += " ";
|
||||
}
|
||||
indent += "* ";
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
167
lib/ace/mode/scad_highlight_rules.js
Normal file
167
lib/ace/mode/scad_highlight_rules.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Ajax.org Code Editor (ACE).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ajax.org B.V.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
* Gastón Kleiman <gaston.kleiman AT gmail DOT com>
|
||||
*
|
||||
* Based on Bespin's C/C++ Syntax Plugin by Marc McIntyre.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var lang = require("pilot/lang");
|
||||
var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var scadHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("module|if|else|for").split("|")
|
||||
);
|
||||
|
||||
var buildinConstants = lang.arrayToMap(
|
||||
("NULL").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant", // <CONSTANT>
|
||||
regex : "<[a-zA-Z0-9.]+>"
|
||||
}, {
|
||||
token : "keyword", // pre-compiler directivs
|
||||
regex : "(?:use|include)"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
||||
oop.inherits(scadHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.scadHighlightRules = scadHighlightRules;
|
||||
});
|
||||
|
|
@ -9,7 +9,7 @@ var ScalaHighlightRules = function() {
|
|||
|
||||
// taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
|
||||
var keywords = lang.arrayToMap(
|
||||
(
|
||||
(
|
||||
"case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|" +
|
||||
"abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|" +
|
||||
"override|package|private|protected|sealed|super|this|trait|type|val|var|with"
|
||||
|
|
@ -60,98 +60,76 @@ var ScalaHighlightRules = function() {
|
|||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "\\/\\*\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
token : "string.regexp",
|
||||
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (value == "this")
|
||||
return "variable.language";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (langClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (importClasses.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
// TODO: Unicode escape sequences
|
||||
// TODO: Unicode identifiers
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
|
||||
}, {
|
||||
token : "lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [
|
||||
{
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
}
|
||||
token : "comment", // closing comment
|
||||
regex : ".*?\\*\\/",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ var lang = require("pilot/lang");
|
|||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var ScssHighlightRules = function() {
|
||||
|
||||
var properties = lang.arrayToMap( (function () {
|
||||
|
||||
var properties = lang.arrayToMap( (function () {
|
||||
|
||||
var browserPrefix = ("-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-").split("|");
|
||||
|
||||
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|" +
|
||||
|
|
@ -97,20 +97,20 @@ var ScssHighlightRules = function() {
|
|||
//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("|"))
|
||||
);
|
||||
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;
|
||||
|
||||
})() );
|
||||
|
||||
|
||||
return ret;
|
||||
|
||||
})() );
|
||||
|
||||
|
||||
|
||||
var functions = lang.arrayToMap(
|
||||
|
|
@ -151,19 +151,19 @@ var ScssHighlightRules = function() {
|
|||
);
|
||||
|
||||
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("|")
|
||||
("@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("|")
|
||||
("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.
|
||||
|
|
@ -197,6 +197,7 @@ var ScssHighlightRules = function() {
|
|||
},
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
next : "comment"
|
||||
}, {
|
||||
|
|
@ -204,6 +205,7 @@ var ScssHighlightRules = function() {
|
|||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*\\\\$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
|
|
@ -211,6 +213,7 @@ var ScssHighlightRules = function() {
|
|||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
|
|
@ -272,8 +275,8 @@ var ScssHighlightRules = function() {
|
|||
regex : numRe
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (properties.hasOwnProperty(value.toLowerCase()))
|
||||
return "support.type";
|
||||
if (properties.hasOwnProperty(value.toLowerCase()))
|
||||
return "support.type";
|
||||
if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (constants.hasOwnProperty(value))
|
||||
|
|
@ -283,9 +286,9 @@ var ScssHighlightRules = function() {
|
|||
else if (colors.hasOwnProperty(value.toLowerCase()))
|
||||
return "support.constant.color";
|
||||
else if (tags.hasOwnProperty(value.toLowerCase()))
|
||||
return "variable.language";
|
||||
return "variable.language";
|
||||
else
|
||||
return "text";
|
||||
return "text";
|
||||
},
|
||||
regex : "\\-?[@a-zA-Z_][@a-zA-Z0-9_\\-]*"
|
||||
}, {
|
||||
|
|
@ -324,6 +327,7 @@ var ScssHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
}
|
||||
],
|
||||
|
|
@ -334,6 +338,7 @@ var ScssHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
],
|
||||
|
|
@ -344,11 +349,11 @@ var ScssHighlightRules = function() {
|
|||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
oop.inherits(ScssHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ 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 unicode = require("ace/unicode");
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());
|
||||
|
|
@ -51,6 +52,20 @@ var Mode = function() {
|
|||
|
||||
(function() {
|
||||
|
||||
this.tokenRe = new RegExp("^["
|
||||
+ unicode.packages.L
|
||||
+ unicode.packages.Mn + unicode.packages.Mc
|
||||
+ unicode.packages.Nd
|
||||
+ unicode.packages.Pc + "\\$_]+", "g"
|
||||
);
|
||||
|
||||
this.nonTokenRe = new RegExp("^(?:[^"
|
||||
+ unicode.packages.L
|
||||
+ unicode.packages.Mn + unicode.packages.Mc
|
||||
+ unicode.packages.Nd
|
||||
+ unicode.packages.Pc + "\\$_]|\s])+", "g"
|
||||
);
|
||||
|
||||
this.getTokenizer = function() {
|
||||
return this.$tokenizer;
|
||||
};
|
||||
|
|
@ -125,7 +140,7 @@ var Mode = function() {
|
|||
var ranges = editor.$search.findAll(session);
|
||||
ranges.forEach(function(range) {
|
||||
if (!range.contains(cursor.row, cursor.column)) {
|
||||
var marker = session.addMarker(range, "ace_selected_word");
|
||||
var marker = session.addMarker(range, "ace_selected_word", "text");
|
||||
session.$selectionOccurrences.push(marker);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ var TextHighlightRules = function() {
|
|||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
"start" : [{
|
||||
token : "empty_line",
|
||||
regex : '^$'
|
||||
}, {
|
||||
token : "text",
|
||||
regex : ".+"
|
||||
} ]
|
||||
}]
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,23 +40,7 @@ define(function(require, exports, module) {
|
|||
var oop = require("pilot/oop");
|
||||
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var TextileHighlightRules = function()
|
||||
{
|
||||
/*
|
||||
var phraseModifiers = lang.arrayToMap(
|
||||
("_|*|__|**|??|-|+|^|%|@").split("|")
|
||||
);
|
||||
|
||||
var blockModifiers = lang.arrayToMap(
|
||||
("h1|h2|h3|h4|h5|h6|bq|p|bc|pre").split("|")
|
||||
);
|
||||
*/
|
||||
/*
|
||||
var punctuation = lang.arrayToMap(
|
||||
("-|--|(tm)|(r)|(c)").split("|")
|
||||
);
|
||||
*/
|
||||
|
||||
var TextileHighlightRules = function() {
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
|
|
@ -77,13 +61,13 @@ var TextileHighlightRules = function()
|
|||
{
|
||||
token : "keyword",
|
||||
regex : "\\. ",
|
||||
next : "start",
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "keyword",
|
||||
regex : "\\(",
|
||||
next : "blocktagproperties"
|
||||
},
|
||||
}
|
||||
],
|
||||
"blocktagproperties" : [
|
||||
{
|
||||
|
|
@ -98,7 +82,7 @@ var TextileHighlightRules = function()
|
|||
{
|
||||
token : "keyword",
|
||||
regex : "#"
|
||||
},
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ var XmlHighlightRules = function() {
|
|||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
start : [ {
|
||||
start : [{
|
||||
token : "text",
|
||||
regex : "<\\!\\[CDATA\\[",
|
||||
next : "cdata"
|
||||
|
|
@ -55,6 +55,7 @@ var XmlHighlightRules = function() {
|
|||
regex : "<\\?.*?\\?>"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : "<\\!--",
|
||||
next : "comment"
|
||||
}, {
|
||||
|
|
@ -67,9 +68,9 @@ var XmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "[^<]+"
|
||||
} ],
|
||||
}],
|
||||
|
||||
tag : [ {
|
||||
tag : [{
|
||||
token : "text",
|
||||
regex : ">",
|
||||
next : "start"
|
||||
|
|
@ -84,6 +85,7 @@ var XmlHighlightRules = function() {
|
|||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : '["].*$',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
|
|
@ -91,6 +93,7 @@ var XmlHighlightRules = function() {
|
|||
regex : "'.*?'"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
merge : true,
|
||||
regex : "['].*$",
|
||||
next : "qstring"
|
||||
}],
|
||||
|
|
@ -101,6 +104,7 @@ var XmlHighlightRules = function() {
|
|||
next : "tag"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}],
|
||||
|
||||
|
|
@ -110,10 +114,11 @@ var XmlHighlightRules = function() {
|
|||
next : "tag"
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
}],
|
||||
|
||||
cdata : [ {
|
||||
cdata : [{
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
next : "start"
|
||||
|
|
@ -123,16 +128,17 @@ var XmlHighlightRules = function() {
|
|||
}, {
|
||||
token : "text",
|
||||
regex : "(?:[^\\]]|\\](?!\\]>))+"
|
||||
} ],
|
||||
}],
|
||||
|
||||
comment : [ {
|
||||
comment : [{
|
||||
token : "comment",
|
||||
regex : ".*?-->",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
} ]
|
||||
}]
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,12 +45,14 @@ var XmlMode = require("ace/mode/xml").Mode;
|
|||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "XML Tokenizer",
|
||||
|
||||
setUp : function() {
|
||||
this.tokenizer = new XmlMode().getTokenizer();
|
||||
},
|
||||
|
||||
"test: tokenize1" : function() {
|
||||
|
||||
var line = "<Juhu>//Juhu Kinners</Kinners>";
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var event = require("pilot/event");
|
||||
var dom = require("pilot/dom");
|
||||
var BrowserFocus = require("pilot/browser_focus").BrowserFocus;
|
||||
|
||||
var STATE_UNKNOWN = 0;
|
||||
var STATE_SELECT = 1;
|
||||
|
|
@ -51,6 +52,8 @@ var DRAG_OFFSET = 5; // pixels
|
|||
|
||||
var MouseHandler = function(editor) {
|
||||
this.editor = editor;
|
||||
|
||||
this.browserFocus = new BrowserFocus();
|
||||
event.addListener(editor.container, "mousedown", function(e) {
|
||||
editor.focus();
|
||||
return event.preventDefault(e);
|
||||
|
|
@ -91,6 +94,15 @@ var MouseHandler = function(editor) {
|
|||
};
|
||||
|
||||
this.onMouseDown = function(e) {
|
||||
// if this click caused the editor to be focused ignore the click
|
||||
// for selection and cursor placement
|
||||
if (
|
||||
!this.browserFocus.isFocused()
|
||||
|| new Date().getTime() - this.browserFocus.lastFocus < 20
|
||||
|| !this.editor.isFocused()
|
||||
)
|
||||
return;
|
||||
|
||||
var pageX = event.getDocumentX(e);
|
||||
var pageY = event.getDocumentY(e);
|
||||
var pos = this.$getEventPosition(e);
|
||||
|
|
|
|||
|
|
@ -52,324 +52,628 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
exports.options = {
|
||||
version: 185,
|
||||
};
|
||||
|
||||
(function() {
|
||||
exports.hostGlobal = this
|
||||
})();
|
||||
|
||||
var tokens = [
|
||||
// End of source.
|
||||
"END",
|
||||
|
||||
// Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
|
||||
// and (UNARY_PLUS, UNARY_MINUS).
|
||||
"\n", ";",
|
||||
",",
|
||||
"=",
|
||||
"?", ":", "CONDITIONAL",
|
||||
"||",
|
||||
"&&",
|
||||
"|",
|
||||
"^",
|
||||
"&",
|
||||
"==", "!=", "===", "!==",
|
||||
"<", "<=", ">=", ">",
|
||||
"<<", ">>", ">>>",
|
||||
"+", "-",
|
||||
"*", "/", "%",
|
||||
"!", "~", "UNARY_PLUS", "UNARY_MINUS",
|
||||
"++", "--",
|
||||
".",
|
||||
"[", "]",
|
||||
"{", "}",
|
||||
"(", ")",
|
||||
|
||||
// Nonterminal tree node type codes.
|
||||
"SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
|
||||
"ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
|
||||
"GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
|
||||
|
||||
// Terminals.
|
||||
"IDENTIFIER", "NUMBER", "STRING", "REGEXP",
|
||||
|
||||
// Keywords.
|
||||
"break",
|
||||
"case", "catch", "const", "continue",
|
||||
"debugger", "default", "delete", "do",
|
||||
"else",
|
||||
"false", "finally", "for", "function",
|
||||
"if", "in", "instanceof",
|
||||
"let",
|
||||
"new", "null",
|
||||
"return",
|
||||
"switch",
|
||||
"this", "throw", "true", "try", "typeof",
|
||||
"var", "void",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
var statementStartTokens = [
|
||||
"break",
|
||||
"const", "continue",
|
||||
"debugger", "do",
|
||||
"for",
|
||||
"if",
|
||||
"return",
|
||||
"switch",
|
||||
"throw", "try",
|
||||
"var",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
// Operator and punctuator mapping from token to tree node type name.
|
||||
// NB: because the lexer doesn't backtrack, all token prefixes must themselves
|
||||
// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
|
||||
// tokens != and !).
|
||||
var opTypeNames = {
|
||||
'\n': "NEWLINE",
|
||||
';': "SEMICOLON",
|
||||
',': "COMMA",
|
||||
'?': "HOOK",
|
||||
':': "COLON",
|
||||
'||': "OR",
|
||||
'&&': "AND",
|
||||
'|': "BITWISE_OR",
|
||||
'^': "BITWISE_XOR",
|
||||
'&': "BITWISE_AND",
|
||||
'===': "STRICT_EQ",
|
||||
'==': "EQ",
|
||||
'=': "ASSIGN",
|
||||
'!==': "STRICT_NE",
|
||||
'!=': "NE",
|
||||
'<<': "LSH",
|
||||
'<=': "LE",
|
||||
'<': "LT",
|
||||
'>>>': "URSH",
|
||||
'>>': "RSH",
|
||||
'>=': "GE",
|
||||
'>': "GT",
|
||||
'++': "INCREMENT",
|
||||
'--': "DECREMENT",
|
||||
'+': "PLUS",
|
||||
'-': "MINUS",
|
||||
'*': "MUL",
|
||||
'/': "DIV",
|
||||
'%': "MOD",
|
||||
'!': "NOT",
|
||||
'~': "BITWISE_NOT",
|
||||
'.': "DOT",
|
||||
'[': "LEFT_BRACKET",
|
||||
']': "RIGHT_BRACKET",
|
||||
'{': "LEFT_CURLY",
|
||||
'}': "RIGHT_CURLY",
|
||||
'(': "LEFT_PAREN",
|
||||
')': "RIGHT_PAREN"
|
||||
};
|
||||
|
||||
// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
|
||||
// avoid toString, etc. namespace pollution.
|
||||
var keywords = {__proto__: null};
|
||||
|
||||
// Define const END, etc., based on the token names. Also map name to index.
|
||||
var tokenIds = {};
|
||||
|
||||
// Building up a string to be eval'd in different contexts.
|
||||
var consts = "const ";
|
||||
for (var i = 0, j = tokens.length; i < j; i++) {
|
||||
if (i > 0)
|
||||
consts += ", ";
|
||||
var t = tokens[i];
|
||||
var name;
|
||||
if (/^[a-z]/.test(t)) {
|
||||
name = t.toUpperCase();
|
||||
keywords[t] = i;
|
||||
} else {
|
||||
name = (/^\W/.test(t) ? opTypeNames[t] : t);
|
||||
}
|
||||
consts += name + " = " + i;
|
||||
tokenIds[name] = i;
|
||||
tokens[t] = i;
|
||||
}
|
||||
consts += ";";
|
||||
|
||||
var isStatementStartCode = {__proto__: null};
|
||||
for (i = 0, j = statementStartTokens.length; i < j; i++)
|
||||
isStatementStartCode[keywords[statementStartTokens[i]]] = true;
|
||||
|
||||
// Map assignment operators to their indexes in the tokens array.
|
||||
var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
|
||||
|
||||
for (i = 0, j = assignOps.length; i < j; i++) {
|
||||
t = assignOps[i];
|
||||
assignOps[t] = tokens[t];
|
||||
}
|
||||
|
||||
function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ get: fn, configurable: !dontDelete, enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ value: val, writable: !readOnly, configurable: !dontDelete,
|
||||
enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
// Returns true if fn is a native function. (Note: SpiderMonkey specific.)
|
||||
function isNativeCode(fn) {
|
||||
// Relies on the toString method to identify native code.
|
||||
return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
|
||||
}
|
||||
|
||||
function getPropertyDescriptor(obj, name) {
|
||||
while (obj) {
|
||||
if (({}).hasOwnProperty.call(obj, name))
|
||||
return Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function getOwnProperties(obj) {
|
||||
var map = {};
|
||||
for (var name in Object.getOwnPropertyNames(obj))
|
||||
map[name] = Object.getOwnPropertyDescriptor(obj, name);
|
||||
return map;
|
||||
}
|
||||
|
||||
function makePassthruHandler(obj) {
|
||||
// Handler copied from
|
||||
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||
return {
|
||||
getOwnPropertyDescriptor: function(name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
var narcissus = {
|
||||
options: {
|
||||
version: 185,
|
||||
// Global variables to hide from the interpreter
|
||||
hiddenHostGlobals: { Narcissus: true },
|
||||
// Desugar SpiderMonkey language extensions?
|
||||
desugarExtensions: false
|
||||
},
|
||||
getPropertyDescriptor: function(name) {
|
||||
var desc = getPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getOwnPropertyNames: function() {
|
||||
return Object.getOwnPropertyNames(obj);
|
||||
},
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(obj, name, desc);
|
||||
},
|
||||
"delete": function(name) { return delete obj[name]; },
|
||||
fix: function() {
|
||||
if (Object.isFrozen(obj)) {
|
||||
return getOwnProperties(obj);
|
||||
hostSupportsEvalConst: (function() {
|
||||
try {
|
||||
return eval("(function(s) { eval(s); return x })('const x = true;')");
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// As long as obj is not frozen, the proxy won't allow itself to be fixed.
|
||||
return undefined; // will cause a TypeError to be thrown
|
||||
},
|
||||
|
||||
has: function(name) { return name in obj; },
|
||||
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
||||
get: function(receiver, name) { return obj[name]; },
|
||||
|
||||
// bad behavior when set fails in non-strict mode
|
||||
set: function(receiver, name, val) { obj[name] = val; return true; },
|
||||
enumerate: function() {
|
||||
var result = [];
|
||||
for (name in obj) { result.push(name); };
|
||||
return result;
|
||||
},
|
||||
keys: function() { return Object.keys(obj); }
|
||||
})(),
|
||||
hostGlobal: this
|
||||
};
|
||||
}
|
||||
Narcissus = narcissus;
|
||||
|
||||
// default function used when looking for a property in the global object
|
||||
function noPropFound() { return undefined; }
|
||||
var tokens = [
|
||||
// End of source.
|
||||
"END",
|
||||
|
||||
var hasOwnProperty = ({}).hasOwnProperty;
|
||||
// Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
|
||||
// and (UNARY_PLUS, UNARY_MINUS).
|
||||
"\n", ";",
|
||||
",",
|
||||
"=",
|
||||
"?", ":", "CONDITIONAL",
|
||||
"||",
|
||||
"&&",
|
||||
"|",
|
||||
"^",
|
||||
"&",
|
||||
"==", "!=", "===", "!==",
|
||||
"<", "<=", ">=", ">",
|
||||
"<<", ">>", ">>>",
|
||||
"+", "-",
|
||||
"*", "/", "%",
|
||||
"!", "~", "UNARY_PLUS", "UNARY_MINUS",
|
||||
"++", "--",
|
||||
".",
|
||||
"[", "]",
|
||||
"{", "}",
|
||||
"(", ")",
|
||||
|
||||
function StringMap() {
|
||||
this.table = Object.create(null, {});
|
||||
this.size = 0;
|
||||
}
|
||||
// Nonterminal tree node type codes.
|
||||
"SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
|
||||
"ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
|
||||
"GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
|
||||
|
||||
StringMap.prototype = {
|
||||
has: function(x) { return hasOwnProperty.call(this.table, x); },
|
||||
set: function(x, v) {
|
||||
if (!hasOwnProperty.call(this.table, x))
|
||||
this.size++;
|
||||
this.table[x] = v;
|
||||
},
|
||||
get: function(x) { return this.table[x]; },
|
||||
getDef: function(x, thunk) {
|
||||
if (!hasOwnProperty.call(this.table, x)) {
|
||||
this.size++;
|
||||
this.table[x] = thunk();
|
||||
// Terminals.
|
||||
"IDENTIFIER", "NUMBER", "STRING", "REGEXP",
|
||||
|
||||
// Keywords.
|
||||
"break",
|
||||
"case", "catch", "const", "continue",
|
||||
"debugger", "default", "delete", "do",
|
||||
"else", "export",
|
||||
"false", "finally", "for", "function",
|
||||
"if", "import", "in", "instanceof",
|
||||
"let", "module",
|
||||
"new", "null",
|
||||
"return",
|
||||
"switch",
|
||||
"this", "throw", "true", "try", "typeof",
|
||||
"var", "void",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
var statementStartTokens = [
|
||||
"break",
|
||||
"const", "continue",
|
||||
"debugger", "do",
|
||||
"for",
|
||||
"if",
|
||||
"return",
|
||||
"switch",
|
||||
"throw", "try",
|
||||
"var",
|
||||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
// Whitespace characters (see ECMA-262 7.2)
|
||||
var whitespaceChars = [
|
||||
// normal whitespace:
|
||||
"\u0009", "\u000B", "\u000C", "\u0020", "\u00A0", "\uFEFF",
|
||||
|
||||
// high-Unicode whitespace:
|
||||
"\u1680", "\u180E",
|
||||
"\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006",
|
||||
"\u2007", "\u2008", "\u2009", "\u200A",
|
||||
"\u202F", "\u205F", "\u3000"
|
||||
];
|
||||
|
||||
var whitespace = {};
|
||||
for (var i = 0; i < whitespaceChars.length; i++) {
|
||||
whitespace[whitespaceChars[i]] = true;
|
||||
}
|
||||
|
||||
// Operator and punctuator mapping from token to tree node type name.
|
||||
// NB: because the lexer doesn't backtrack, all token prefixes must themselves
|
||||
// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
|
||||
// tokens != and !).
|
||||
var opTypeNames = {
|
||||
'\n': "NEWLINE",
|
||||
';': "SEMICOLON",
|
||||
',': "COMMA",
|
||||
'?': "HOOK",
|
||||
':': "COLON",
|
||||
'||': "OR",
|
||||
'&&': "AND",
|
||||
'|': "BITWISE_OR",
|
||||
'^': "BITWISE_XOR",
|
||||
'&': "BITWISE_AND",
|
||||
'===': "STRICT_EQ",
|
||||
'==': "EQ",
|
||||
'=': "ASSIGN",
|
||||
'!==': "STRICT_NE",
|
||||
'!=': "NE",
|
||||
'<<': "LSH",
|
||||
'<=': "LE",
|
||||
'<': "LT",
|
||||
'>>>': "URSH",
|
||||
'>>': "RSH",
|
||||
'>=': "GE",
|
||||
'>': "GT",
|
||||
'++': "INCREMENT",
|
||||
'--': "DECREMENT",
|
||||
'+': "PLUS",
|
||||
'-': "MINUS",
|
||||
'*': "MUL",
|
||||
'/': "DIV",
|
||||
'%': "MOD",
|
||||
'!': "NOT",
|
||||
'~': "BITWISE_NOT",
|
||||
'.': "DOT",
|
||||
'[': "LEFT_BRACKET",
|
||||
']': "RIGHT_BRACKET",
|
||||
'{': "LEFT_CURLY",
|
||||
'}': "RIGHT_CURLY",
|
||||
'(': "LEFT_PAREN",
|
||||
')': "RIGHT_PAREN"
|
||||
};
|
||||
|
||||
// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
|
||||
// avoid toString, etc. namespace pollution.
|
||||
var keywords = {__proto__: null};
|
||||
|
||||
// Define const END, etc., based on the token names. Also map name to index.
|
||||
var tokenIds = {};
|
||||
|
||||
// Building up a string to be eval'd in different contexts.
|
||||
var consts = Narcissus.hostSupportsEvalConst ? "const " : "var ";
|
||||
for (var i = 0, j = tokens.length; i < j; i++) {
|
||||
if (i > 0)
|
||||
consts += ", ";
|
||||
var t = tokens[i];
|
||||
var name;
|
||||
if (/^[a-z]/.test(t)) {
|
||||
name = t.toUpperCase();
|
||||
keywords[t] = i;
|
||||
} else {
|
||||
name = (/^\W/.test(t) ? opTypeNames[t] : t);
|
||||
}
|
||||
return this.table[x];
|
||||
},
|
||||
forEach: function(f) {
|
||||
var table = this.table;
|
||||
for (var key in table)
|
||||
f.call(this, key, table[key]);
|
||||
},
|
||||
toString: function() { return "[object StringMap]" }
|
||||
};
|
||||
consts += name + " = " + i;
|
||||
tokenIds[name] = i;
|
||||
tokens[t] = i;
|
||||
}
|
||||
consts += ";";
|
||||
|
||||
// non-destructive stack
|
||||
function Stack(elts) {
|
||||
this.elts = elts || null;
|
||||
}
|
||||
var isStatementStartCode = {__proto__: null};
|
||||
for (i = 0, j = statementStartTokens.length; i < j; i++)
|
||||
isStatementStartCode[keywords[statementStartTokens[i]]] = true;
|
||||
|
||||
Stack.prototype = {
|
||||
push: function(x) {
|
||||
return new Stack({ top: x, rest: this.elts });
|
||||
},
|
||||
top: function() {
|
||||
if (!this.elts)
|
||||
throw new Error("empty stack");
|
||||
return this.elts.top;
|
||||
},
|
||||
isEmpty: function() {
|
||||
return this.top === null;
|
||||
},
|
||||
find: function(test) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
if (test(elts.top))
|
||||
return elts.top;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
has: function(x) {
|
||||
return Boolean(this.find(function(elt) { return elt === x }));
|
||||
},
|
||||
forEach: function(f) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
f(elts.top);
|
||||
// Map assignment operators to their indexes in the tokens array.
|
||||
var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
|
||||
|
||||
for (i = 0, j = assignOps.length; i < j; i++) {
|
||||
t = assignOps[i];
|
||||
assignOps[t] = tokens[t];
|
||||
}
|
||||
|
||||
function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ get: fn, configurable: !dontDelete, enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
function defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop, {
|
||||
get: getter,
|
||||
set: setter,
|
||||
configurable: !dontDelete,
|
||||
enumerable: !dontEnum
|
||||
});
|
||||
}
|
||||
|
||||
function defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop, {
|
||||
get: function() {
|
||||
var val = fn();
|
||||
defineProperty(obj, prop, val, dontDelete, true, dontEnum);
|
||||
return val;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: !dontEnum
|
||||
});
|
||||
}
|
||||
|
||||
function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
|
||||
Object.defineProperty(obj, prop,
|
||||
{ value: val, writable: !readOnly, configurable: !dontDelete,
|
||||
enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
// Returns true if fn is a native function. (Note: SpiderMonkey specific.)
|
||||
function isNativeCode(fn) {
|
||||
// Relies on the toString method to identify native code.
|
||||
return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
|
||||
}
|
||||
|
||||
function getPropertyDescriptor(obj, name) {
|
||||
while (obj) {
|
||||
if (({}).hasOwnProperty.call(obj, name))
|
||||
return Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.tokens = tokens;
|
||||
exports.opTypeNames = opTypeNames;
|
||||
exports.keywords = keywords;
|
||||
exports.isStatementStartCode = isStatementStartCode;
|
||||
exports.tokenIds = tokenIds;
|
||||
exports.consts = consts;
|
||||
exports.assignOps = assignOps;
|
||||
exports.defineGetter = defineGetter;
|
||||
exports.defineProperty = defineProperty;
|
||||
exports.isNativeCode = isNativeCode;
|
||||
exports.makePassthruHandler = makePassthruHandler;
|
||||
exports.noPropFound = noPropFound;
|
||||
exports.StringMap = StringMap;
|
||||
exports.Stack = Stack;
|
||||
function getPropertyNames(obj) {
|
||||
var table = Object.create(null, {});
|
||||
while (obj) {
|
||||
var names = Object.getOwnPropertyNames(obj);
|
||||
for (var i = 0, n = names.length; i < n; i++)
|
||||
table[names[i]] = true;
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
return Object.keys(table);
|
||||
}
|
||||
|
||||
function getOwnProperties(obj) {
|
||||
var map = {};
|
||||
for (var name in Object.getOwnPropertyNames(obj))
|
||||
map[name] = Object.getOwnPropertyDescriptor(obj, name);
|
||||
return map;
|
||||
}
|
||||
|
||||
function blacklistHandler(target, blacklist) {
|
||||
var mask = Object.create(null, {});
|
||||
var redirect = StringMap.create(blacklist).mapObject(function(name) { return mask; });
|
||||
return mixinHandler(redirect, target);
|
||||
}
|
||||
|
||||
function whitelistHandler(target, whitelist) {
|
||||
var catchall = Object.create(null, {});
|
||||
var redirect = StringMap.create(whitelist).mapObject(function(name) { return target; });
|
||||
return mixinHandler(redirect, catchall);
|
||||
}
|
||||
|
||||
function mirrorHandler(target, writable) {
|
||||
var handler = makePassthruHandler(target);
|
||||
|
||||
var defineProperty = handler.defineProperty;
|
||||
handler.defineProperty = function(name, desc) {
|
||||
if (!desc.enumerable)
|
||||
throw new Error("mirror property must be enumerable");
|
||||
if (!desc.configurable)
|
||||
throw new Error("mirror property must be configurable");
|
||||
if (desc.writable !== writable)
|
||||
throw new Error("mirror property must " + (writable ? "" : "not ") + "be writable");
|
||||
defineProperty(name, desc);
|
||||
};
|
||||
|
||||
handler.fix = function() { };
|
||||
handler.getOwnPropertyDescriptor = handler.getPropertyDescriptor;
|
||||
handler.getOwnPropertyNames = getPropertyNames.bind(handler, target);
|
||||
handler.keys = handler.enumerate;
|
||||
handler["delete"] = function() { return false; };
|
||||
handler.hasOwn = handler.has;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mixin proxies break the single-inheritance model of prototypes, so
|
||||
* the handler treats all properties as own-properties:
|
||||
*
|
||||
* X
|
||||
* |
|
||||
* +------------+------------+
|
||||
* | O |
|
||||
* | | |
|
||||
* | O O O |
|
||||
* | | | | |
|
||||
* | O O O O |
|
||||
* | | | | | |
|
||||
* | O O O O O |
|
||||
* | | | | | | |
|
||||
* +-(*)--(w)--(x)--(y)--(z)-+
|
||||
*/
|
||||
|
||||
function mixinHandler(redirect, catchall) {
|
||||
function targetFor(name) {
|
||||
return hasOwn(redirect, name) ? redirect[name] : catchall;
|
||||
}
|
||||
|
||||
function getMuxPropertyDescriptor(name) {
|
||||
var desc = getPropertyDescriptor(targetFor(name), name);
|
||||
if (desc)
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
}
|
||||
|
||||
function getMuxPropertyNames() {
|
||||
var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) {
|
||||
return name in redirect[name];
|
||||
});
|
||||
var names2 = getPropertyNames(catchall).filter(function(name) {
|
||||
return !hasOwn(redirect, name);
|
||||
});
|
||||
return names1.concat(names2);
|
||||
}
|
||||
|
||||
function enumerateMux() {
|
||||
var result = Object.getOwnPropertyNames(redirect).filter(function(name) {
|
||||
return name in redirect[name];
|
||||
});
|
||||
for (name in catchall) {
|
||||
if (!hasOwn(redirect, name))
|
||||
result.push(name);
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
function hasMux(name) {
|
||||
return name in targetFor(name);
|
||||
}
|
||||
|
||||
return {
|
||||
getOwnPropertyDescriptor: getMuxPropertyDescriptor,
|
||||
getPropertyDescriptor: getMuxPropertyDescriptor,
|
||||
getOwnPropertyNames: getMuxPropertyNames,
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(targetFor(name), name, desc);
|
||||
},
|
||||
"delete": function(name) {
|
||||
var target = targetFor(name);
|
||||
return delete target[name];
|
||||
},
|
||||
// FIXME: ha ha ha
|
||||
fix: function() { },
|
||||
has: hasMux,
|
||||
hasOwn: hasMux,
|
||||
get: function(receiver, name) {
|
||||
var target = targetFor(name);
|
||||
return target[name];
|
||||
},
|
||||
set: function(receiver, name, val) {
|
||||
var target = targetFor(name);
|
||||
target[name] = val;
|
||||
return true;
|
||||
},
|
||||
enumerate: enumerateMux,
|
||||
keys: enumerateMux
|
||||
};
|
||||
}
|
||||
|
||||
function makePassthruHandler(obj) {
|
||||
// Handler copied from
|
||||
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||
return {
|
||||
getOwnPropertyDescriptor: function(name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getPropertyDescriptor: function(name) {
|
||||
var desc = getPropertyDescriptor(obj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getOwnPropertyNames: function() {
|
||||
return Object.getOwnPropertyNames(obj);
|
||||
},
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(obj, name, desc);
|
||||
},
|
||||
"delete": function(name) { return delete obj[name]; },
|
||||
fix: function() {
|
||||
if (Object.isFrozen(obj)) {
|
||||
return getOwnProperties(obj);
|
||||
}
|
||||
|
||||
// As long as obj is not frozen, the proxy won't allow itself to be fixed.
|
||||
return undefined; // will cause a TypeError to be thrown
|
||||
},
|
||||
|
||||
has: function(name) { return name in obj; },
|
||||
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
||||
get: function(receiver, name) { return obj[name]; },
|
||||
|
||||
// bad behavior when set fails in non-strict mode
|
||||
set: function(receiver, name, val) { obj[name] = val; return true; },
|
||||
enumerate: function() {
|
||||
var result = [];
|
||||
for (name in obj) { result.push(name); };
|
||||
return result;
|
||||
},
|
||||
keys: function() { return Object.keys(obj); }
|
||||
};
|
||||
}
|
||||
|
||||
var hasOwnProperty = ({}).hasOwnProperty;
|
||||
|
||||
function hasOwn(obj, name) {
|
||||
return hasOwnProperty.call(obj, name);
|
||||
}
|
||||
|
||||
function StringMap(table, size) {
|
||||
this.table = table || Object.create(null, {});
|
||||
this.size = size || 0;
|
||||
}
|
||||
|
||||
StringMap.create = function(table) {
|
||||
var init = Object.create(null, {});
|
||||
var size = 0;
|
||||
var names = Object.getOwnPropertyNames(table);
|
||||
for (var i = 0, n = names.length; i < n; i++) {
|
||||
var name = names[i];
|
||||
init[name] = table[name];
|
||||
size++;
|
||||
}
|
||||
return new StringMap(init, size);
|
||||
};
|
||||
|
||||
StringMap.prototype = {
|
||||
has: function(x) { return hasOwnProperty.call(this.table, x); },
|
||||
set: function(x, v) {
|
||||
if (!hasOwnProperty.call(this.table, x))
|
||||
this.size++;
|
||||
this.table[x] = v;
|
||||
},
|
||||
get: function(x) { return this.table[x]; },
|
||||
getDef: function(x, thunk) {
|
||||
if (!hasOwnProperty.call(this.table, x)) {
|
||||
this.size++;
|
||||
this.table[x] = thunk();
|
||||
}
|
||||
return this.table[x];
|
||||
},
|
||||
forEach: function(f) {
|
||||
var table = this.table;
|
||||
for (var key in table)
|
||||
f.call(this, key, table[key]);
|
||||
},
|
||||
map: function(f) {
|
||||
var table1 = this.table;
|
||||
var table2 = Object.create(null, {});
|
||||
this.forEach(function(key, val) {
|
||||
table2[key] = f.call(this, val, key);
|
||||
});
|
||||
return new StringMap(table2, this.size);
|
||||
},
|
||||
mapObject: function(f) {
|
||||
var table1 = this.table;
|
||||
var table2 = Object.create(null, {});
|
||||
this.forEach(function(key, val) {
|
||||
table2[key] = f.call(this, val, key);
|
||||
});
|
||||
return table2;
|
||||
},
|
||||
toObject: function() {
|
||||
return this.mapObject(function(val) { return val; });
|
||||
},
|
||||
choose: function() {
|
||||
return Object.getOwnPropertyNames(this.table)[0];
|
||||
},
|
||||
remove: function(x) {
|
||||
if (hasOwnProperty.call(this.table, x)) {
|
||||
this.size--;
|
||||
delete this.table[x];
|
||||
}
|
||||
},
|
||||
copy: function() {
|
||||
var table = Object.create(null, {});
|
||||
for (var key in this.table)
|
||||
table[key] = this.table[key];
|
||||
return new StringMap(table, this.size);
|
||||
},
|
||||
toString: function() { return "[object StringMap]" }
|
||||
};
|
||||
|
||||
// an object-key table with poor asymptotics (replace with WeakMap when possible)
|
||||
function ObjectMap(array) {
|
||||
this.array = array || [];
|
||||
}
|
||||
|
||||
function searchMap(map, key, found, notFound) {
|
||||
var a = map.array;
|
||||
for (var i = 0, n = a.length; i < n; i++) {
|
||||
var pair = a[i];
|
||||
if (pair.key === key)
|
||||
return found(pair, i);
|
||||
}
|
||||
return notFound();
|
||||
}
|
||||
|
||||
ObjectMap.prototype = {
|
||||
has: function(x) {
|
||||
return searchMap(this, x, function() { return true }, function() { return false });
|
||||
},
|
||||
set: function(x, v) {
|
||||
var a = this.array;
|
||||
searchMap(this, x,
|
||||
function(pair) { pair.value = v },
|
||||
function() { a.push({ key: x, value: v }) });
|
||||
},
|
||||
get: function(x) {
|
||||
return searchMap(this, x,
|
||||
function(pair) { return pair.value },
|
||||
function() { return null });
|
||||
},
|
||||
getDef: function(x, thunk) {
|
||||
var a = this.array;
|
||||
return searchMap(this, x,
|
||||
function(pair) { return pair.value },
|
||||
function() {
|
||||
var v = thunk();
|
||||
a.push({ key: x, value: v });
|
||||
return v;
|
||||
});
|
||||
},
|
||||
forEach: function(f) {
|
||||
var a = this.array;
|
||||
for (var i = 0, n = a.length; i < n; i++) {
|
||||
var pair = a[i];
|
||||
f.call(this, pair.key, pair.value);
|
||||
}
|
||||
},
|
||||
choose: function() {
|
||||
return this.array[0].key;
|
||||
},
|
||||
get size() {
|
||||
return this.array.length;
|
||||
},
|
||||
remove: function(x) {
|
||||
var a = this.array;
|
||||
searchMap(this, x,
|
||||
function(pair, i) { a.splice(i, 1) },
|
||||
function() { });
|
||||
},
|
||||
copy: function() {
|
||||
return new ObjectMap(this.array.map(function(pair) {
|
||||
return { key: pair.key, value: pair.value }
|
||||
}));
|
||||
},
|
||||
clear: function() {
|
||||
this.array = [];
|
||||
},
|
||||
toString: function() { return "[object ObjectMap]" }
|
||||
};
|
||||
|
||||
// non-destructive stack
|
||||
function Stack(elts) {
|
||||
this.elts = elts || null;
|
||||
}
|
||||
|
||||
Stack.prototype = {
|
||||
push: function(x) {
|
||||
return new Stack({ top: x, rest: this.elts });
|
||||
},
|
||||
top: function() {
|
||||
if (!this.elts)
|
||||
throw new Error("empty stack");
|
||||
return this.elts.top;
|
||||
},
|
||||
isEmpty: function() {
|
||||
return this.top === null;
|
||||
},
|
||||
find: function(test) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
if (test(elts.top))
|
||||
return elts.top;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
has: function(x) {
|
||||
return Boolean(this.find(function(elt) { return elt === x }));
|
||||
},
|
||||
forEach: function(f) {
|
||||
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||
f(elts.top);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
tokens: tokens,
|
||||
whitespace: whitespace,
|
||||
opTypeNames: opTypeNames,
|
||||
keywords: keywords,
|
||||
isStatementStartCode: isStatementStartCode,
|
||||
tokenIds: tokenIds,
|
||||
consts: consts,
|
||||
assignOps: assignOps,
|
||||
defineGetter: defineGetter,
|
||||
defineGetterSetter: defineGetterSetter,
|
||||
defineMemoGetter: defineMemoGetter,
|
||||
defineProperty: defineProperty,
|
||||
isNativeCode: isNativeCode,
|
||||
mirrorHandler: mirrorHandler,
|
||||
mixinHandler: mixinHandler,
|
||||
whitelistHandler: whitelistHandler,
|
||||
blacklistHandler: blacklistHandler,
|
||||
makePassthruHandler: makePassthruHandler,
|
||||
StringMap: StringMap,
|
||||
ObjectMap: ObjectMap,
|
||||
Stack: Stack
|
||||
};
|
||||
});
|
||||
|
|
@ -47,416 +47,503 @@
|
|||
* Lexical scanner.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var definitions = require("ace/narcissus/jsdefs");
|
||||
var definitions = require("ace/narcissus/jsdefs");
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(definitions.consts);
|
||||
// Set constants in the local scope.
|
||||
eval(definitions.consts);
|
||||
|
||||
// Build up a trie of operator tokens.
|
||||
var opTokens = {};
|
||||
for (var op in definitions.opTypeNames) {
|
||||
if (op === '\n' || op === '.')
|
||||
continue;
|
||||
// Banned keywords by language version
|
||||
const blackLists = { 160: {}, 185: {}, harmony: {} };
|
||||
blackLists[160][LET] = true;
|
||||
blackLists[160][MODULE] = true;
|
||||
blackLists[160][YIELD] = true;
|
||||
blackLists[185][MODULE] = true;
|
||||
|
||||
var node = opTokens;
|
||||
for (var i = 0; i < op.length; i++) {
|
||||
var ch = op[i];
|
||||
if (!(ch in node))
|
||||
node[ch] = {};
|
||||
node = node[ch];
|
||||
node.op = op;
|
||||
// Build up a trie of operator tokens.
|
||||
var opTokens = {};
|
||||
for (var op in definitions.opTypeNames) {
|
||||
if (op === '\n' || op === '.')
|
||||
continue;
|
||||
|
||||
var node = opTokens;
|
||||
for (var i = 0; i < op.length; i++) {
|
||||
var ch = op[i];
|
||||
if (!(ch in node))
|
||||
node[ch] = {};
|
||||
node = node[ch];
|
||||
node.op = op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenizer :: (source, filename, line number) -> Tokenizer
|
||||
*/
|
||||
function Tokenizer(s, f, l) {
|
||||
this.cursor = 0;
|
||||
this.source = String(s);
|
||||
this.tokens = [];
|
||||
this.tokenIndex = 0;
|
||||
this.lookahead = 0;
|
||||
this.scanNewlines = false;
|
||||
this.unexpectedEOF = false;
|
||||
this.filename = f || "";
|
||||
this.lineno = l || 1;
|
||||
}
|
||||
|
||||
Tokenizer.prototype = {
|
||||
get done() {
|
||||
// We need to set scanOperand to true here because the first thing
|
||||
// might be a regexp.
|
||||
return this.peek(true) === END;
|
||||
},
|
||||
|
||||
get token() {
|
||||
return this.tokens[this.tokenIndex];
|
||||
},
|
||||
|
||||
match: function (tt, scanOperand) {
|
||||
return this.get(scanOperand) === tt || this.unget();
|
||||
},
|
||||
|
||||
mustMatch: function (tt) {
|
||||
if (!this.match(tt)) {
|
||||
throw this.newSyntaxError("Missing " +
|
||||
definitions.tokens[tt].toLowerCase());
|
||||
}
|
||||
return this.token;
|
||||
},
|
||||
|
||||
peek: function (scanOperand) {
|
||||
var tt, next;
|
||||
if (this.lookahead) {
|
||||
next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
|
||||
tt = (this.scanNewlines && next.lineno !== this.lineno)
|
||||
? NEWLINE
|
||||
: next.type;
|
||||
} else {
|
||||
tt = this.get(scanOperand);
|
||||
this.unget();
|
||||
}
|
||||
return tt;
|
||||
},
|
||||
|
||||
peekOnSameLine: function (scanOperand) {
|
||||
this.scanNewlines = true;
|
||||
var tt = this.peek(scanOperand);
|
||||
/*
|
||||
* Tokenizer :: (source, filename, line number) -> Tokenizer
|
||||
*/
|
||||
function Tokenizer(s, f, l) {
|
||||
this.cursor = 0;
|
||||
this.source = String(s);
|
||||
this.tokens = [];
|
||||
this.tokenIndex = 0;
|
||||
this.lookahead = 0;
|
||||
this.scanNewlines = false;
|
||||
return tt;
|
||||
},
|
||||
this.unexpectedEOF = false;
|
||||
this.filename = f || "";
|
||||
this.lineno = l || 1;
|
||||
this.blackList = blackLists[Narcissus.options.version];
|
||||
this.blockComments = null;
|
||||
}
|
||||
|
||||
// Eat comments and whitespace.
|
||||
skip: function () {
|
||||
var input = this.source;
|
||||
for (;;) {
|
||||
var ch = input[this.cursor++];
|
||||
var next = input[this.cursor];
|
||||
if (ch === '\n' && !this.scanNewlines) {
|
||||
this.lineno++;
|
||||
} else if (ch === '/' && next === '*') {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated comment");
|
||||
Tokenizer.prototype = {
|
||||
get done() {
|
||||
// We need to set scanOperand to true here because the first thing
|
||||
// might be a regexp.
|
||||
return this.peek(true) === END;
|
||||
},
|
||||
|
||||
if (ch === '*') {
|
||||
get token() {
|
||||
return this.tokens[this.tokenIndex];
|
||||
},
|
||||
|
||||
match: function (tt, scanOperand) {
|
||||
return this.get(scanOperand) === tt || this.unget();
|
||||
},
|
||||
|
||||
mustMatch: function (tt) {
|
||||
if (!this.match(tt)) {
|
||||
throw this.newSyntaxError("Missing " +
|
||||
definitions.tokens[tt].toLowerCase());
|
||||
}
|
||||
return this.token;
|
||||
},
|
||||
|
||||
peek: function (scanOperand) {
|
||||
var tt, next;
|
||||
if (this.lookahead) {
|
||||
next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
|
||||
tt = (this.scanNewlines && next.lineno !== this.lineno)
|
||||
? NEWLINE
|
||||
: next.type;
|
||||
} else {
|
||||
tt = this.get(scanOperand);
|
||||
this.unget();
|
||||
}
|
||||
return tt;
|
||||
},
|
||||
|
||||
peekOnSameLine: function (scanOperand) {
|
||||
this.scanNewlines = true;
|
||||
var tt = this.peek(scanOperand);
|
||||
this.scanNewlines = false;
|
||||
return tt;
|
||||
},
|
||||
|
||||
lastBlockComment: function() {
|
||||
var length = this.blockComments.length;
|
||||
return length ? this.blockComments[length - 1] : null;
|
||||
},
|
||||
|
||||
// Eat comments and whitespace.
|
||||
skip: function () {
|
||||
var input = this.source;
|
||||
this.blockComments = [];
|
||||
for (;;) {
|
||||
var ch = input[this.cursor++];
|
||||
var next = input[this.cursor];
|
||||
// handle \r, \r\n and (always preferable) \n
|
||||
if (ch === '\r') {
|
||||
// if the next character is \n, we don't care about this at all
|
||||
if (next === '\n') continue;
|
||||
|
||||
// otherwise, we want to consider this as a newline
|
||||
ch = '\n';
|
||||
}
|
||||
|
||||
if (ch === '\n' && !this.scanNewlines) {
|
||||
this.lineno++;
|
||||
} else if (ch === '/' && next === '*') {
|
||||
var commentStart = ++this.cursor;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated comment");
|
||||
|
||||
if (ch === '*') {
|
||||
next = input[this.cursor];
|
||||
if (next === '/') {
|
||||
var commentEnd = this.cursor - 1;
|
||||
this.cursor++;
|
||||
break;
|
||||
}
|
||||
} else if (ch === '\n') {
|
||||
this.lineno++;
|
||||
}
|
||||
}
|
||||
this.blockComments.push(input.substring(commentStart, commentEnd));
|
||||
} else if (ch === '/' && next === '/') {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
next = input[this.cursor];
|
||||
if (next === '/') {
|
||||
this.cursor++;
|
||||
if (ch === undefined)
|
||||
return;
|
||||
|
||||
if (ch === '\r') {
|
||||
// check for \r\n
|
||||
if (next !== '\n') ch = '\n';
|
||||
}
|
||||
|
||||
if (ch === '\n') {
|
||||
if (this.scanNewlines) {
|
||||
this.cursor--;
|
||||
} else {
|
||||
this.lineno++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (ch === '\n') {
|
||||
this.lineno++;
|
||||
}
|
||||
} else if (!(ch in definitions.whitespace)) {
|
||||
this.cursor--;
|
||||
return;
|
||||
}
|
||||
} else if (ch === '/' && next === '/') {
|
||||
}
|
||||
},
|
||||
|
||||
// Lex the exponential part of a number, if present. Return true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
var input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next === 'e' || next === 'E') {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
return;
|
||||
|
||||
if (ch === '\n') {
|
||||
this.lineno++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ch !== ' ' && ch !== '\t') {
|
||||
this.cursor--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
// Lex the exponential part of a number, if present. Return true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
var input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next === 'e' || next === 'E') {
|
||||
this.cursor++;
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else if (ch === 'x' || ch === 'X') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||
(ch >= 'A' && ch <= 'F'));
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else if (ch >= '0' && ch <= '7') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '7');
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else {
|
||||
this.cursor--;
|
||||
this.lexExponent(); // 0E1, &c.
|
||||
token.value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
lexNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
var floating = false;
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.' && !floating) {
|
||||
floating = true;
|
||||
ch = input[this.cursor++];
|
||||
}
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
var exponent = this.lexExponent();
|
||||
floating = floating || exponent;
|
||||
|
||||
var str = input.substring(token.start, this.cursor);
|
||||
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||
},
|
||||
|
||||
lexDot: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next >= '0' && next <= '9') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
|
||||
token.type = NUMBER;
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else {
|
||||
token.type = DOT;
|
||||
token.assignOp = null;
|
||||
token.value = '.';
|
||||
}
|
||||
},
|
||||
|
||||
lexString: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = STRING;
|
||||
|
||||
var hasEscapes = false;
|
||||
var delim = ch;
|
||||
if (input.length <= this.cursor)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
while ((ch = input[this.cursor++]) !== delim) {
|
||||
if (this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (ch === '\\') {
|
||||
hasEscapes = true;
|
||||
if (++this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
}
|
||||
}
|
||||
|
||||
token.value = hasEscapes
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
this.cursor++;
|
||||
} else if (ch === '[') {
|
||||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
do {
|
||||
return false;
|
||||
},
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.cursor--;
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else if (ch === 'x' || ch === 'X') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||
(ch >= 'A' && ch <= 'F'));
|
||||
this.cursor--;
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else if (ch >= '0' && ch <= '7') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '7');
|
||||
this.cursor--;
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else {
|
||||
this.cursor--;
|
||||
this.lexExponent(); // 0E1, &c.
|
||||
token.value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||
// for only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
var next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
lexNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
var floating = false;
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.' && !floating) {
|
||||
floating = true;
|
||||
ch = input[this.cursor++];
|
||||
}
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
var exponent = this.lexExponent();
|
||||
floating = floating || exponent;
|
||||
|
||||
var str = input.substring(token.start, this.cursor);
|
||||
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||
},
|
||||
|
||||
lexDot: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next >= '0' && next <= '9') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
|
||||
token.type = NUMBER;
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else {
|
||||
token.type = DOT;
|
||||
token.assignOp = null;
|
||||
token.value = '.';
|
||||
}
|
||||
},
|
||||
|
||||
lexString: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = STRING;
|
||||
|
||||
var hasEscapes = false;
|
||||
var delim = ch;
|
||||
if (input.length <= this.cursor)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
while ((ch = input[this.cursor++]) !== delim) {
|
||||
if (this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (ch === '\\') {
|
||||
hasEscapes = true;
|
||||
if (++this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
}
|
||||
}
|
||||
|
||||
token.value = hasEscapes
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
this.cursor++;
|
||||
} else if (ch === '[') {
|
||||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||
// for only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
var next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var op = node.op;
|
||||
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
token.type = ASSIGN;
|
||||
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
op += '=';
|
||||
} else {
|
||||
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
var op = node.op;
|
||||
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
token.type = ASSIGN;
|
||||
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
op += '=';
|
||||
} else {
|
||||
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
|
||||
token.value = op;
|
||||
},
|
||||
token.value = op;
|
||||
},
|
||||
|
||||
// FIXME: Unicode escape sequences
|
||||
// FIXME: Unicode identifiers
|
||||
lexIdent: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
// FIXME: Unicode escape sequences
|
||||
lexIdent: function (ch) {
|
||||
var token = this.token;
|
||||
var id = ch;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') || ch === '$' || ch === '_');
|
||||
while ((ch = this.getValidIdentifierChar(false)) !== null) {
|
||||
id += ch;
|
||||
}
|
||||
|
||||
this.cursor--; // Put the non-word character back.
|
||||
token.type = definitions.keywords[id] || IDENTIFIER;
|
||||
if (token.type in this.blackList) {
|
||||
// banned keyword, this is an identifier
|
||||
token.type = IDENTIFIER;
|
||||
}
|
||||
token.value = id;
|
||||
},
|
||||
|
||||
var id = input.substring(token.start, this.cursor);
|
||||
token.type = definitions.keywords[id] || IDENTIFIER;
|
||||
token.value = id;
|
||||
},
|
||||
/*
|
||||
* Tokenizer.get :: void -> token type
|
||||
*
|
||||
* Consume input *only* if there is no lookahead.
|
||||
* Dispatch to the appropriate lexing function depending on the input.
|
||||
*/
|
||||
get: function (scanOperand) {
|
||||
var token;
|
||||
while (this.lookahead) {
|
||||
--this.lookahead;
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (token.type !== NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
|
||||
this.skip();
|
||||
|
||||
/*
|
||||
* Tokenizer.get :: void -> token type
|
||||
*
|
||||
* Consume input *only* if there is no lookahead.
|
||||
* Dispatch to the appropriate lexing function depending on the input.
|
||||
*/
|
||||
get: function (scanOperand) {
|
||||
var token;
|
||||
while (this.lookahead) {
|
||||
--this.lookahead;
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (token.type !== NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
|
||||
this.skip();
|
||||
var input = this.source;
|
||||
if (this.cursor >= input.length)
|
||||
return token.type = END;
|
||||
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
|
||||
var input = this.source;
|
||||
if (this.cursor === input.length)
|
||||
return token.type = END;
|
||||
var ich = this.getValidIdentifierChar(true);
|
||||
var ch = (ich === null) ? input[this.cursor++] : null;
|
||||
if (ich !== null) {
|
||||
this.lexIdent(ich);
|
||||
} else if (scanOperand && ch === '/') {
|
||||
this.lexRegExp(ch);
|
||||
} else if (ch in opTokens) {
|
||||
this.lexOp(ch);
|
||||
} else if (ch === '.') {
|
||||
this.lexDot(ch);
|
||||
} else if (ch >= '1' && ch <= '9') {
|
||||
this.lexNumber(ch);
|
||||
} else if (ch === '0') {
|
||||
this.lexZeroNumber(ch);
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
this.lexString(ch);
|
||||
} else if (this.scanNewlines && (ch === '\n' || ch === '\r')) {
|
||||
// if this was a \r, look for \r\n
|
||||
if (ch === '\r' && input[this.cursor] === '\n') this.cursor++;
|
||||
token.type = NEWLINE;
|
||||
token.value = '\n';
|
||||
this.lineno++;
|
||||
} else {
|
||||
throw this.newSyntaxError("Illegal token");
|
||||
}
|
||||
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
token.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
|
||||
var ch = input[this.cursor++];
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_') {
|
||||
this.lexIdent(ch);
|
||||
} else if (scanOperand && ch === '/') {
|
||||
this.lexRegExp(ch);
|
||||
} else if (ch in opTokens) {
|
||||
this.lexOp(ch);
|
||||
} else if (ch === '.') {
|
||||
this.lexDot(ch);
|
||||
} else if (ch >= '1' && ch <= '9') {
|
||||
this.lexNumber(ch);
|
||||
} else if (ch === '0') {
|
||||
this.lexZeroNumber(ch);
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
this.lexString(ch);
|
||||
} else if (this.scanNewlines && ch === '\n') {
|
||||
token.type = NEWLINE;
|
||||
token.value = '\n';
|
||||
this.lineno++;
|
||||
} else {
|
||||
throw this.newSyntaxError("Illegal token");
|
||||
}
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
* Match depends on unget returning undefined.
|
||||
*/
|
||||
unget: function () {
|
||||
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
|
||||
token.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
newSyntaxError: function (m) {
|
||||
m = (this.filename ? this.filename + ":" : "") + this.lineno + ": " + m;
|
||||
var e = new SyntaxError(m, this.filename, this.lineno);
|
||||
e.source = this.source;
|
||||
e.cursor = this.lookahead
|
||||
? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
|
||||
: this.cursor;
|
||||
return e;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
* Match depends on unget returning undefined.
|
||||
*/
|
||||
unget: function () {
|
||||
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
/* Gets a single valid identifier char from the input stream, or null
|
||||
* if there is none.
|
||||
* Since JavaScript provides no convenient way to determine if a
|
||||
* character is in a particular Unicode category, we use
|
||||
* metacircularity to accomplish this (oh yeaaaah!) */
|
||||
getValidIdentifierChar: function(first) {
|
||||
var input = this.source;
|
||||
if (this.cursor >= input.length) return null;
|
||||
var ch = input[this.cursor];
|
||||
|
||||
newSyntaxError: function (m) {
|
||||
var e = new SyntaxError(m, this.filename, this.lineno);
|
||||
e.source = this.source;
|
||||
e.lineno = this.lineno;
|
||||
e.cursor = this.lookahead
|
||||
? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
|
||||
: this.cursor;
|
||||
return e;
|
||||
},
|
||||
};
|
||||
// first check for \u escapes
|
||||
if (ch === '\\' && input[this.cursor+1] === 'u') {
|
||||
// get the character value
|
||||
try {
|
||||
ch = String.fromCharCode(parseInt(
|
||||
input.substring(this.cursor + 2, this.cursor + 6),
|
||||
16));
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
this.cursor += 5;
|
||||
}
|
||||
|
||||
exports.Tokenizer = Tokenizer;
|
||||
// check directly for ASCII
|
||||
if (ch <= "\u007F") {
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||
|
||||
(!first && (ch >= '0' && ch <= '9'))) {
|
||||
this.cursor++;
|
||||
return ch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// create an object to test this in
|
||||
var x = {};
|
||||
x["x"+ch] = true;
|
||||
x[ch] = true;
|
||||
|
||||
// then use eval to determine if it's a valid character
|
||||
var valid = false;
|
||||
try {
|
||||
valid = (Function("x", "return (x." + (first?"":"x") + ch + ");")(x) === true);
|
||||
} catch (ex) {}
|
||||
if (valid) this.cursor++;
|
||||
return (valid ? ch : null);
|
||||
},
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
return { Tokenizer: Tokenizer };
|
||||
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -290,6 +290,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
session.documentToScreenPosition(this.start);
|
||||
var screenPosEnd =
|
||||
session.documentToScreenPosition(this.end);
|
||||
|
||||
return new Range(
|
||||
screenPosStart.row, screenPosStart.column,
|
||||
screenPosEnd.row, screenPosEnd.column
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ if (typeof process !== "undefined") {
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var Range = require("ace/range").Range;
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
var assert = require("ace/test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
|
@ -165,6 +166,27 @@ module.exports = {
|
|||
|
||||
var range = new Range(2, 0, 2, 0);
|
||||
assert.range(range.collapseRows(), 2, 0, 2, 0);
|
||||
},
|
||||
|
||||
"test: to screen range" : function() {
|
||||
var session = new EditSession([
|
||||
"juhu",
|
||||
"12\t\t34",
|
||||
"ぁぁa",
|
||||
"\t\t34",
|
||||
]);
|
||||
|
||||
var range = new Range(0, 0, 0, 3);
|
||||
assert.range(range.toScreenRange(session), 0, 0, 0, 3);
|
||||
|
||||
var range = new Range(1, 1, 1, 3);
|
||||
assert.range(range.toScreenRange(session), 1, 1, 1, 4);
|
||||
|
||||
var range = new Range(2, 1, 2, 2);
|
||||
assert.range(range.toScreenRange(session), 2, 2, 2, 4);
|
||||
|
||||
var range = new Range(3, 0, 3, 4);
|
||||
assert.range(range.toScreenRange(session), 3, 0, 3, 10);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,11 @@ var ScrollBar = function(parent) {
|
|||
|
||||
parent.appendChild(this.element);
|
||||
|
||||
// in OSX lion the scrollbars appear to have no width. In this case resize
|
||||
// the to show the scrollbar but still pretend that the scrollbar has a width
|
||||
// of 0px
|
||||
this.width = dom.scrollbarWidth();
|
||||
this.element.style.width = this.width + "px";
|
||||
this.element.style.width = (this.width || 15) + "px";
|
||||
|
||||
event.addListener(this.element, "scroll", this.onScroll.bind(this));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@ var lang = require("pilot/lang");
|
|||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
/**
|
||||
* Keeps cursor position and the text selection of an edit session.
|
||||
*
|
||||
* The row/columns used in the selection are in document coordinates
|
||||
* representing ths coordinates as thez appear in the document
|
||||
* before applying soft wrap and folding.
|
||||
*/
|
||||
var Selection = function(session) {
|
||||
this.session = session;
|
||||
this.doc = session.getDocument();
|
||||
|
|
@ -56,7 +63,7 @@ var Selection = function(session) {
|
|||
_self._dispatchEvent("changeCursor");
|
||||
if (!_self.$isEmpty)
|
||||
_self._dispatchEvent("changeSelection");
|
||||
if (e.old.row == e.value.row)
|
||||
if (!_self.$preventUpdateDesiredColumnOnChange && e.old.column != e.value.column)
|
||||
_self.$updateDesiredColumn();
|
||||
});
|
||||
|
||||
|
|
@ -297,7 +304,8 @@ var Selection = function(session) {
|
|||
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) {
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
@ -318,25 +326,25 @@ var Selection = function(session) {
|
|||
var screenRow = this.session.documentToScreenRow(row, column);
|
||||
|
||||
// Determ the doc-position of the first character at the screen line.
|
||||
var firstColumnPosition =
|
||||
this.session.screenToDocumentPosition(screenRow, 0);
|
||||
var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);
|
||||
|
||||
// Determ the string "before" the cursor.
|
||||
// Determ the line
|
||||
var beforeCursor = this.session.getDisplayLine(
|
||||
row, column,
|
||||
firstColumnPosition.row, firstColumnPosition.column);
|
||||
row, null,
|
||||
firstColumnPosition.row, firstColumnPosition.column
|
||||
);
|
||||
|
||||
//
|
||||
var leadingSpace = beforeCursor.match(/^\s*/);
|
||||
if (leadingSpace[0].length == 0
|
||||
|| leadingSpace[0].length >= column - firstColumnPosition.column)
|
||||
{
|
||||
if (leadingSpace[0].length == column) {
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row, firstColumnPosition.column);
|
||||
} else {
|
||||
firstColumnPosition.row, firstColumnPosition.column
|
||||
);
|
||||
}
|
||||
else {
|
||||
this.moveCursorTo(
|
||||
firstColumnPosition.row,
|
||||
firstColumnPosition.column + leadingSpace[0].length);
|
||||
firstColumnPosition.column + leadingSpace[0].length
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -434,7 +442,6 @@ var Selection = function(session) {
|
|||
);
|
||||
var screenCol = (chars == 0 && this.$desiredColumn) || screenPos.column;
|
||||
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
|
||||
|
||||
this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
|
||||
};
|
||||
|
||||
|
|
@ -449,7 +456,11 @@ var Selection = function(session) {
|
|||
row = fold.start.row;
|
||||
column = fold.start.column;
|
||||
}
|
||||
|
||||
this.$preventUpdateDesiredColumnOnChange = true;
|
||||
this.selectionLead.setPosition(row, column);
|
||||
this.$preventUpdateDesiredColumnOnChange = false;
|
||||
|
||||
if (!preventUpdateDesiredColumn)
|
||||
this.$updateDesiredColumn(this.selectionLead.column);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -144,8 +144,12 @@ module.exports = {
|
|||
},
|
||||
|
||||
"test: moveCursor word left" : function() {
|
||||
var session = new EditSession( ["ab",
|
||||
" Juhu Kinners (abc, 12)", " cde"].join("\n"));
|
||||
var session = new EditSession([
|
||||
"ab",
|
||||
" Juhu Kinners (abc, 12)",
|
||||
" cde"
|
||||
].join("\n"));
|
||||
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorDown();
|
||||
|
|
@ -183,6 +187,18 @@ module.exports = {
|
|||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 2);
|
||||
},
|
||||
|
||||
"test: moveCursor word left" : function() {
|
||||
var session = new EditSession(" Fuß Füße");
|
||||
|
||||
var selection = session.getSelection();
|
||||
selection.moveCursorTo(0, 9)
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 5);
|
||||
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 4);
|
||||
},
|
||||
|
||||
"test: select word left if cursor in word" : function() {
|
||||
var session = new EditSession("Juhu Kinners");
|
||||
|
|
@ -327,6 +343,106 @@ module.exports = {
|
|||
// Move behind ||
|
||||
selection.moveCursorWordLeft();
|
||||
assert.position(selection.getCursor(), 0, 0);
|
||||
},
|
||||
|
||||
"test: move cursor to line start should move cursor to end of the indentation first": function() {
|
||||
var session = new EditSession("12\n Juhu\n12");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(1, 6);
|
||||
selection.moveCursorLineStart();
|
||||
|
||||
assert.position(selection.getCursor(), 1, 4);
|
||||
},
|
||||
|
||||
"test: move cursor to line start when the cursor is at the end of the indentation should move cursor to column 0": function() {
|
||||
var session = new EditSession("12\n Juhu\n12");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(1, 4);
|
||||
selection.moveCursorLineStart();
|
||||
|
||||
assert.position(selection.getCursor(), 1, 0);
|
||||
},
|
||||
|
||||
"test: move cursor to line start when the cursor is at column 0 should move cursor to the end of the indentation": function() {
|
||||
var session = new EditSession("12\n Juhu\n12");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(1, 0);
|
||||
selection.moveCursorLineStart();
|
||||
|
||||
assert.position(selection.getCursor(), 1, 4);
|
||||
},
|
||||
|
||||
// Eclipse style
|
||||
"test: move cursor to line start when the cursor is before the initial indentation should move cursor to the end of the indentation": function() {
|
||||
var session = new EditSession("12\n Juhu\n12");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(1, 2);
|
||||
selection.moveCursorLineStart();
|
||||
|
||||
assert.position(selection.getCursor(), 1, 4);
|
||||
},
|
||||
|
||||
"test go line up when in the middle of the first line should go to document start": function() {
|
||||
var session = new EditSession("juhu kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 4);
|
||||
selection.moveCursorUp();
|
||||
|
||||
assert.position(selection.getCursor(), 0, 0);
|
||||
},
|
||||
|
||||
"test: (wrap) go line up when in the middle of the first line should go to document start": function() {
|
||||
var session = new EditSession("juhu kinners");
|
||||
session.setWrapLimitRange(5, 5);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 4);
|
||||
selection.moveCursorUp();
|
||||
|
||||
assert.position(selection.getCursor(), 0, 0);
|
||||
},
|
||||
|
||||
|
||||
"test go line down when in the middle of the last line should go to document end": function() {
|
||||
var session = new EditSession("juhu kinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 4);
|
||||
selection.moveCursorDown();
|
||||
|
||||
assert.position(selection.getCursor(), 0, 12);
|
||||
},
|
||||
|
||||
"test (wrap) go line down when in the middle of the last line should go to document end": function() {
|
||||
var session = new EditSession("juhu kinners");
|
||||
session.setWrapLimitRange(8, 8);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(0, 10);
|
||||
selection.moveCursorDown();
|
||||
|
||||
assert.position(selection.getCursor(), 0, 12);
|
||||
},
|
||||
|
||||
"test go line up twice and then once down when in the second should go back to the previous column": function() {
|
||||
var session = new EditSession("juhu\nkinners");
|
||||
var selection = session.getSelection();
|
||||
|
||||
selection.moveCursorTo(1, 4);
|
||||
selection.moveCursorUp();
|
||||
selection.moveCursorUp();
|
||||
selection.moveCursorDown();
|
||||
|
||||
assert.position(selection.getCursor(), 1, 4);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("pilot/oop");
|
||||
var dom = require("pilot/dom");
|
||||
var lang = require("pilot/lang");
|
||||
var EventEmitter = require("pilot/event_emitter").EventEmitter;
|
||||
|
||||
|
|
@ -71,12 +72,12 @@ var Split = function(container, theme, splits) {
|
|||
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 el = document.createElement("div");
|
||||
el.className = this.$editorCSS;
|
||||
el.style.cssText = "position: absolute; top:0px; bottom:0px";
|
||||
this.$container.appendChild(el);
|
||||
var session = new EditSession("");
|
||||
var editor = new Editor(new Renderer(dom, this.$theme));
|
||||
var editor = new Editor(new Renderer(el, this.$theme));
|
||||
|
||||
editor.on("focus", function() {
|
||||
this._emit("focus", editor);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
require("pilot/fixoldbrowsers");
|
||||
var AsyncTest = require("asyncjs/test");
|
||||
var AsyncTest = require("asyncjs").test;
|
||||
var async = require("asyncjs");
|
||||
var dom = require("pilot/dom");
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ var tests = [
|
|||
require("ace/mode/html_tokenizer_test"),
|
||||
require("ace/mode/javascript_test"),
|
||||
require("ace/mode/javascript_tokenizer_test"),
|
||||
require("ace/mode/ruby_tokenizer_test"),
|
||||
require("ace/mode/text_test"),
|
||||
require("ace/mode/xml_test"),
|
||||
require("ace/mode/xml_tokenizer_test")
|
||||
|
|
|
|||
85
lib/ace/test/benchmark.js
Normal file
85
lib/ace/test/benchmark.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 ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("../../../support/paths");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var assert = require("ace/test/assertions");
|
||||
var EditSession = require("ace/edit_session").EditSession;
|
||||
|
||||
module.exports = {
|
||||
setUp : function() {
|
||||
this.start = Date.now();
|
||||
},
|
||||
|
||||
tearDown : function() {
|
||||
console.log("took: ", Date.now() - this.start + "ms");
|
||||
},
|
||||
|
||||
"test: document to screen position": function() {
|
||||
var s = new EditSession(Array(6000).join('someText\n'));
|
||||
|
||||
for (var i=0; i<6000; i++)
|
||||
s.documentToScreenPosition(i, 0);
|
||||
|
||||
for (var i=0; i<6000; i++)
|
||||
s.documentToScreenPosition(i, 0);
|
||||
|
||||
console.log(s.$rowCache.length);
|
||||
},
|
||||
|
||||
"test: screen to document position": function() {
|
||||
var s = new EditSession(Array(6000).join('someText\n'));
|
||||
|
||||
for (var i=0; i<6000; i++)
|
||||
s.screenToDocumentPosition(i, 0);
|
||||
|
||||
for (var i=0; i<6000; i++)
|
||||
s.documentToScreenPosition(i, 0);
|
||||
|
||||
console.log(s.$rowCache.length);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec();
|
||||
}
|
||||
198
lib/ace/theme/crimson_editor.js
Normal file
198
lib/ace/theme/crimson_editor.js
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/* ***** 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-crimson-editor .ace_editor {\
|
||||
border: 2px solid rgb(159, 159, 159);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_editor.ace_focus {\
|
||||
border: 2px solid #327fbd;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_gutter {\
|
||||
width: 50px;\
|
||||
background: #e8e8e8;\
|
||||
color: #333;\
|
||||
overflow : hidden;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_gutter-layer {\
|
||||
width: 100%;\
|
||||
text-align: right;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_gutter-layer .ace_gutter-cell {\
|
||||
padding-right: 6px;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_print_margin {\
|
||||
width: 1px;\
|
||||
background: #e8e8e8;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_text-layer {\
|
||||
cursor: text;\
|
||||
color: rgb(64, 64, 64);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_cursor {\
|
||||
border-left: 2px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_cursor.ace_overwrite {\
|
||||
border-left: 0px;\
|
||||
border-bottom: 1px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_invisible {\
|
||||
color: rgb(191, 191, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_identifier {\
|
||||
color: black;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_keyword {\
|
||||
color: blue;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_constant.ace_buildin {\
|
||||
color: rgb(88, 72, 246);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_constant.ace_language {\
|
||||
color: rgb(255, 156, 0);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_constant.ace_library {\
|
||||
color: rgb(6, 150, 14);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_invalid {\
|
||||
text-decoration: line-through;\
|
||||
color: rgb(224, 0, 0);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_fold {\
|
||||
background-color: #E4E4E4;\
|
||||
border-radius: 3px;\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_support.ace_function {\
|
||||
color: rgb(192, 0, 0);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_support.ace_constant {\
|
||||
color: rgb(6, 150, 14);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_support.ace_type,\
|
||||
.ace-crimson-editor .ace_line .ace_support.ace_class {\
|
||||
color: rgb(109, 121, 222);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_keyword.ace_operator {\
|
||||
color: rgb(49, 132, 149);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_string {\
|
||||
color: rgb(128, 0, 128);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_comment {\
|
||||
color: rgb(76, 136, 107);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_comment.ace_doc {\
|
||||
color: rgb(0, 102, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_comment.ace_doc.ace_tag {\
|
||||
color: rgb(128, 159, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_constant.ace_numeric {\
|
||||
color: rgb(0, 0, 64);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_variable {\
|
||||
color: rgb(0, 64, 128);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_line .ace_xml_pe {\
|
||||
color: rgb(104, 104, 91);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_selection {\
|
||||
background: rgb(181, 213, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_step {\
|
||||
background: rgb(252, 255, 0);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_stack {\
|
||||
background: rgb(164, 229, 101);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_bracket {\
|
||||
margin: -1px 0 0 -1px;\
|
||||
border: 1px solid rgb(192, 192, 192);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_active_line {\
|
||||
background: rgb(232, 242, 254);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_marker-layer .ace_selected_word {\
|
||||
background: rgb(250, 250, 255);\
|
||||
border: 1px solid rgb(200, 200, 250);\
|
||||
}\
|
||||
\
|
||||
.ace-crimson-editor .ace_string.ace_regex {\
|
||||
color: rgb(192, 0, 192);\
|
||||
}";
|
||||
|
||||
// Import CSS once.
|
||||
dom.importCssString(cssText);
|
||||
|
||||
exports.cssClass = "ace-crimson-editor";
|
||||
});
|
||||
|
|
@ -174,7 +174,7 @@ define(function(require, exports, module) {
|
|||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_active_line {\
|
||||
background: rgb(232, 242, 254);\
|
||||
background: rgba(0, 0, 0, 0.07);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_selected_word {\
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ var Tokenizer = function(rules) {
|
|||
}
|
||||
|
||||
this.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", "g");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -93,23 +92,26 @@ var Tokenizer = function(rules) {
|
|||
|
||||
while (match = re.exec(line)) {
|
||||
var type = "text";
|
||||
var rule = null;
|
||||
var value = [match[0]];
|
||||
|
||||
for ( var i = 0; i < match.length-2; i++) {
|
||||
for (var i = 0; i < match.length-2; i++) {
|
||||
if (match[i + 1] !== undefined) {
|
||||
var rule = state[mapping[i].rule];
|
||||
rule = state[mapping[i].rule];
|
||||
|
||||
if (mapping[i].len > 1) {
|
||||
value = match.slice(i+2, i+1+mapping[i].len);
|
||||
}
|
||||
|
||||
// compute token type
|
||||
if (typeof rule.token == "function")
|
||||
type = rule.token.apply(this, value);
|
||||
else
|
||||
type = rule.token;
|
||||
|
||||
if (rule.next && rule.next !== currentState) {
|
||||
currentState = rule.next;
|
||||
var next = rule.next;
|
||||
if (next && next !== currentState) {
|
||||
currentState = next;
|
||||
state = this.rules[currentState];
|
||||
mapping = this.matchMappings[currentState];
|
||||
lastIndex = re.lastIndex;
|
||||
|
|
@ -120,26 +122,25 @@ var Tokenizer = function(rules) {
|
|||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof type == "string") {
|
||||
if (typeof value != "string") {
|
||||
|
||||
if (value[0]) {
|
||||
if (typeof type == "string") {
|
||||
value = [value.join("")];
|
||||
type = [type];
|
||||
}
|
||||
type = [type];
|
||||
}
|
||||
|
||||
for ( var i = 0; i < value.length; i++) {
|
||||
if (token.type !== type[i]) {
|
||||
if (token.type) {
|
||||
tokens.push(token);
|
||||
}
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
if ((!rule || rule.merge || type[i] === "text") && token.type === type[i]) {
|
||||
token.value += value[i];
|
||||
} else {
|
||||
if (token.type) {
|
||||
tokens.push(token);
|
||||
}
|
||||
|
||||
token = {
|
||||
type: type[i],
|
||||
value: value[i]
|
||||
token = {
|
||||
type: type[i],
|
||||
value: value[i]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
token.value += value[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
106
lib/ace/unicode.js
Normal file
106
lib/ace/unicode.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
/*
|
||||
XRegExp Unicode plugin pack: Categories 1.0
|
||||
(c) 2010 Steven Levithan
|
||||
MIT License
|
||||
<http://xregexp.com>
|
||||
Uses the Unicode 5.2 character database
|
||||
|
||||
This package for the XRegExp Unicode plugin enables the following Unicode categories (aka properties):
|
||||
|
||||
L - Letter (the top-level Letter category is included in the Unicode plugin base script)
|
||||
Ll - Lowercase letter
|
||||
Lu - Uppercase letter
|
||||
Lt - Titlecase letter
|
||||
Lm - Modifier letter
|
||||
Lo - Letter without case
|
||||
M - Mark
|
||||
Mn - Non-spacing mark
|
||||
Mc - Spacing combining mark
|
||||
Me - Enclosing mark
|
||||
N - Number
|
||||
Nd - Decimal digit
|
||||
Nl - Letter number
|
||||
No - Other number
|
||||
P - Punctuation
|
||||
Pd - Dash punctuation
|
||||
Ps - Open punctuation
|
||||
Pe - Close punctuation
|
||||
Pi - Initial punctuation
|
||||
Pf - Final punctuation
|
||||
Pc - Connector punctuation
|
||||
Po - Other punctuation
|
||||
S - Symbol
|
||||
Sm - Math symbol
|
||||
Sc - Currency symbol
|
||||
Sk - Modifier symbol
|
||||
So - Other symbol
|
||||
Z - Separator
|
||||
Zs - Space separator
|
||||
Zl - Line separator
|
||||
Zp - Paragraph separator
|
||||
C - Other
|
||||
Cc - Control
|
||||
Cf - Format
|
||||
Co - Private use
|
||||
Cs - Surrogate
|
||||
Cn - Unassigned
|
||||
|
||||
Example usage:
|
||||
|
||||
\p{N}
|
||||
\p{Cn}
|
||||
*/
|
||||
|
||||
|
||||
// will be populated by addUnicodePackage
|
||||
exports.packages = {};
|
||||
|
||||
addUnicodePackage({
|
||||
L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",
|
||||
Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",
|
||||
Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",
|
||||
Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",
|
||||
Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",
|
||||
Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",
|
||||
M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",
|
||||
Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",
|
||||
Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",
|
||||
Me: "0488048906DE20DD-20E020E2-20E4A670-A672",
|
||||
N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",
|
||||
Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",
|
||||
Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",
|
||||
No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",
|
||||
P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",
|
||||
Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",
|
||||
Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",
|
||||
Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",
|
||||
Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",
|
||||
Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21",
|
||||
Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F",
|
||||
Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",
|
||||
S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",
|
||||
Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",
|
||||
Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",
|
||||
Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",
|
||||
So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",
|
||||
Z: "002000A01680180E2000-200A20282029202F205F3000",
|
||||
Zs: "002000A01680180E2000-200A202F205F3000",
|
||||
Zl: "2028",
|
||||
Zp: "2029",
|
||||
C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",
|
||||
Cc: "0000-001F007F-009F",
|
||||
Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",
|
||||
Co: "E000-F8FF",
|
||||
Cs: "D800-DFFF",
|
||||
Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"
|
||||
});
|
||||
|
||||
function addUnicodePackage (pack) {
|
||||
var codePoint = /\w{4}/g;
|
||||
for (var name in pack)
|
||||
exports.packages[name] = pack[name].replace(codePoint, "\\u$&");
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -121,6 +121,20 @@ var VirtualRenderer = function(container, theme) {
|
|||
scrollerWidth: 0
|
||||
};
|
||||
|
||||
this.layerConfig = {
|
||||
width : 1,
|
||||
padding : 0,
|
||||
firstRow : 0,
|
||||
firstRowScreen: 0,
|
||||
lastRow : 0,
|
||||
lineHeight : 1,
|
||||
characterWidth : 1,
|
||||
minHeight : 1,
|
||||
maxHeight : 1,
|
||||
offset : 0,
|
||||
height : 1
|
||||
};
|
||||
|
||||
this.$loop = new RenderLoop(this.$renderChanges.bind(this));
|
||||
this.$loop.schedule(this.CHANGE_FULL);
|
||||
|
||||
|
|
@ -332,39 +346,36 @@ var VirtualRenderer = function(container, theme) {
|
|||
return;
|
||||
|
||||
var bounds = this.content.getBoundingClientRect();
|
||||
var offset = (this.layerConfig && this.layerConfig.offset) || 0;
|
||||
var offset = this.layerConfig.offset;
|
||||
|
||||
textarea.style.left = (bounds.left + pos.left + this.$padding) + "px";
|
||||
textarea.style.top = (bounds.top + pos.top - this.scrollTop + offset) + "px";
|
||||
};
|
||||
|
||||
this.getFirstVisibleRow = function() {
|
||||
return (this.layerConfig || {}).firstRow || 0;
|
||||
return this.layerConfig.firstRow;
|
||||
};
|
||||
|
||||
this.getFirstFullyVisibleRow = function(){
|
||||
if (!this.layerConfig)
|
||||
return 0;
|
||||
|
||||
this.getFirstFullyVisibleRow = function() {
|
||||
return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
|
||||
};
|
||||
|
||||
this.getLastFullyVisibleRow = function() {
|
||||
if (!this.layerConfig)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
return this.layerConfig.lastRow;
|
||||
};
|
||||
|
||||
this.$padding = null;
|
||||
this.setPadding = function(padding) {
|
||||
this.$padding = padding;
|
||||
this.content.style.padding = "0 " + padding + "px";
|
||||
this.$textLayer.setPadding(padding);
|
||||
this.$cursorLayer.setPadding(padding);
|
||||
this.$markerFront.setPadding(padding);
|
||||
this.$markerBack.setPadding(padding);
|
||||
this.$loop.schedule(this.CHANGE_FULL);
|
||||
this.$updatePrintMargin();
|
||||
};
|
||||
|
|
@ -395,8 +406,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
return;
|
||||
|
||||
// text, scrolling and resize changes can cause the view port size to change
|
||||
if (!this.layerConfig ||
|
||||
changes & this.CHANGE_FULL ||
|
||||
if (changes & this.CHANGE_FULL ||
|
||||
changes & this.CHANGE_SIZE ||
|
||||
changes & this.CHANGE_TEXT ||
|
||||
changes & this.CHANGE_LINES ||
|
||||
|
|
@ -469,7 +479,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
var minHeight = this.$size.scrollerHeight + this.lineHeight;
|
||||
|
||||
var longestLine = this.$getLongestLine();
|
||||
var widthChanged = !this.layerConfig ? true : (this.layerConfig.width != longestLine);
|
||||
var widthChanged = this.layerConfig.width != longestLine;
|
||||
|
||||
var horizScroll = this.$horizScrollAlwaysVisible || this.$size.scrollerWidth - longestLine < 0;
|
||||
var horizScrollChanged = this.$horizScroll !== horizScroll;
|
||||
|
|
@ -570,7 +580,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
if (this.$textLayer.showInvisibles)
|
||||
charCount += 1;
|
||||
|
||||
return Math.max(this.$size.scrollerWidth - this.$padding * 2, Math.round(charCount * this.characterWidth));
|
||||
return Math.max(this.$size.scrollerWidth, Math.round(charCount * this.characterWidth));
|
||||
};
|
||||
|
||||
this.updateFrontMarkers = function() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
define(function(require, exports, module) {
|
||||
/*
|
||||
/*!
|
||||
* JSHint, by JSHint Community.
|
||||
*
|
||||
* Licensed under the same slightly modified MIT license that JSLint is.
|
||||
|
|
@ -152,7 +152,8 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
|
||||
/*jshint
|
||||
evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true
|
||||
evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,
|
||||
undef: true, maxlen: 100
|
||||
*/
|
||||
|
||||
/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
|
||||
|
|
@ -186,13 +187,14 @@ define(function(require, exports, module) {
|
|||
close, closed, closure, comment, condition, confirm, console, constructor,
|
||||
content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,
|
||||
decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
|
||||
edition, else, emit, encodeURI, encodeURIComponent, entityify, eqeqeq, eqnull,
|
||||
errors, es5, escape, eval, event, evidence, evil, ex, exception, exec, exps,
|
||||
expr, exports, FileReader, first, floor, focus, forin, fragment, frames, from,
|
||||
fromCharCode, fud, funct, function, functions, g, gc, getComputedStyle, getRow,
|
||||
GLOBAL, global, globals, globalstrict, hasOwnProperty, help, history, i, id,
|
||||
identifier, immed, implieds, include, indent, indexOf, init, ins, instanceOf,
|
||||
isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint,
|
||||
dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent,
|
||||
entityify, eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil,
|
||||
ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,
|
||||
forin, fragment, frames, from, fromCharCode, fud, funct, function, functions,
|
||||
g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict,
|
||||
hasOwnProperty, help, history, i, id, identifier, immed, implieds, include,
|
||||
indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,
|
||||
isDigit, isFinite, isNaN, iterator, join, jshint,
|
||||
JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak,
|
||||
latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
|
||||
log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,
|
||||
|
|
@ -200,10 +202,10 @@ define(function(require, exports, module) {
|
|||
nonew, nud, onbeforeunload, onblur, onerror, onevar, onfocus, onload, onresize,
|
||||
onunload, open, openDatabase, openURL, opener, opera, outer, param, parent,
|
||||
parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,
|
||||
prototype, prototypejs, push, quit, range, raw, reach, reason, regexp,
|
||||
proto, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp,
|
||||
readFile, readUrl, regexdash, removeEventListener, replace, report, require,
|
||||
reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,
|
||||
runCommand, scroll, screen, scrollBy, scrollTo, scrollbar, search, seal, send,
|
||||
runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, send,
|
||||
serialize, setInterval, setTimeout, shift, slice, sort,spawn, split, stack,
|
||||
status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync,
|
||||
test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type,
|
||||
|
|
@ -247,9 +249,10 @@ var JSHINT = (function () {
|
|||
boss : true, // if advanced usage of assignments should be allowed
|
||||
browser : true, // if the standard browser globals should be predefined
|
||||
couch : true, // if CouchDB globals should be predefined
|
||||
curly : true, // if curly braces around blocks should be required (even in if/for/while)
|
||||
curly : true, // if curly braces around all blocks should be required
|
||||
debug : true, // if debugger statements should be allowed
|
||||
devel : true, // if logging globals should be predefined (console, alert, etc.)
|
||||
dojo : true, // if Dojo Toolkit globals should be predefined
|
||||
eqeqeq : true, // if === should be required
|
||||
eqnull : true, // if == null comparisons should be tolerated
|
||||
es5 : true, // if ES5 syntax should be allowed
|
||||
|
|
@ -258,6 +261,7 @@ var JSHINT = (function () {
|
|||
forin : true, // if for in statements must filter
|
||||
globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
|
||||
immed : true, // if immediate invocations must be wrapped in parens
|
||||
iterator : true, // if the `__iterator__` property should be disallowed
|
||||
jquery : true, // if jQuery globals should be predefined
|
||||
latedef : true, // if the use before definition should not be tolerated
|
||||
laxbreak : true, // if line breaks should not be checked
|
||||
|
|
@ -272,18 +276,22 @@ var JSHINT = (function () {
|
|||
onevar : true, // if only one var statement per function should be allowed
|
||||
passfail : true, // if the scan should stop on first error
|
||||
plusplus : true, // if increment/decrement should not be allowed
|
||||
proto : true, // if the `__proto__` property should be disallowed
|
||||
prototypejs : true, // if Prototype and Scriptaculous globals should be predefined
|
||||
regexdash : true, // if unescaped last dash (-) inside brackets should be tolerated
|
||||
regexp : true, // if the . should not be allowed in regexp literals
|
||||
rhino : true, // if the Rhino environment globals should be predefined
|
||||
undef : true, // if variables should be declared before used
|
||||
scripturl : true, // if script-targeted URLs should be tolerated
|
||||
shadow : true, // if variable shadowing should be tolerated
|
||||
strict : true, // require the "use strict"; pragma
|
||||
sub : true, // if all forms of subscript notation are tolerated
|
||||
supernew : true, // if `new function () { ... };` and `new Object;` should be tolerated
|
||||
supernew : true, // if `new function () { ... };` and `new Object;`
|
||||
// should be tolerated
|
||||
trailing : true, // if trailing whitespace rules apply
|
||||
white : true, // if strict whitespace rules apply
|
||||
wsh : true // if the Windows Scripting Host environment globals should be predefined
|
||||
wsh : true // if the Windows Scripting Host environment globals should
|
||||
// be predefined
|
||||
},
|
||||
|
||||
// browser contains a set of global names which are commonly provided by a
|
||||
|
|
@ -375,12 +383,20 @@ var JSHINT = (function () {
|
|||
},
|
||||
|
||||
devel = {
|
||||
alert : false,
|
||||
confirm : false,
|
||||
console : false,
|
||||
Debug : false,
|
||||
opera : false,
|
||||
prompt : false
|
||||
alert : false,
|
||||
confirm : false,
|
||||
console : false,
|
||||
Debug : false,
|
||||
opera : false,
|
||||
prompt : false
|
||||
},
|
||||
|
||||
dojo = {
|
||||
dojo : false,
|
||||
dijit : false,
|
||||
dojox : false,
|
||||
define : false,
|
||||
"require" : false
|
||||
},
|
||||
|
||||
escapes = {
|
||||
|
|
@ -617,27 +633,38 @@ var JSHINT = (function () {
|
|||
VBArray : true,
|
||||
WSH : true,
|
||||
WScript : true
|
||||
},
|
||||
};
|
||||
|
||||
// Regular expressions. Some of these are stupidly long.
|
||||
// Regular expressions. Some of these are stupidly long.
|
||||
var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
|
||||
(function () {
|
||||
/*jshint maxlen:300 */
|
||||
|
||||
// unsafe comment or string
|
||||
ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i,
|
||||
// unsafe characters that are silently deleted by one or more browsers
|
||||
cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
|
||||
// token
|
||||
tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
|
||||
// characters in strings that need escapement
|
||||
nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
|
||||
nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
// star slash
|
||||
lx = /\*\/|\/\*/,
|
||||
// identifier
|
||||
ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,
|
||||
// javascript url
|
||||
jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,
|
||||
// catches /* falls through */ comments
|
||||
ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
|
||||
// unsafe comment or string
|
||||
ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
|
||||
|
||||
// unsafe characters that are silently deleted by one or more browsers
|
||||
cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
|
||||
|
||||
// token
|
||||
tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
|
||||
|
||||
// characters in strings that need escapement
|
||||
nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
|
||||
nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
||||
|
||||
// star slash
|
||||
lx = /\*\/|\/\*/;
|
||||
|
||||
// identifier
|
||||
ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
|
||||
|
||||
// javascript url
|
||||
jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
|
||||
|
||||
// catches /* falls through */ comments
|
||||
ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
|
||||
}());
|
||||
|
||||
function F() {} // Used by Object.create
|
||||
|
||||
|
|
@ -760,6 +787,9 @@ var JSHINT = (function () {
|
|||
if (option.devel)
|
||||
combine(predefined, devel);
|
||||
|
||||
if (option.dojo)
|
||||
combine(predefined, dojo);
|
||||
|
||||
if (option.browser)
|
||||
combine(predefined, browser);
|
||||
|
||||
|
|
@ -875,7 +905,7 @@ var JSHINT = (function () {
|
|||
|
||||
// Check for trailing whitespaces
|
||||
tw = s.search(/\s+$/);
|
||||
if (option.trailing && ~tw)
|
||||
if (option.trailing && ~tw && !~s.search(/^\s+$/))
|
||||
warningAt("Trailing whitespace.", line, tw);
|
||||
|
||||
return true;
|
||||
|
|
@ -895,17 +925,19 @@ var JSHINT = (function () {
|
|||
}
|
||||
t = Object.create(t);
|
||||
if (type === '(string)' || type === '(range)') {
|
||||
if (jx.test(value)) {
|
||||
if (!option.scripturl && jx.test(value)) {
|
||||
warningAt("Script URL.", line, from);
|
||||
}
|
||||
}
|
||||
if (type === '(identifier)') {
|
||||
t.identifier = true;
|
||||
if (value === '__iterator__' || value === '__proto__') {
|
||||
errorAt("Reserved name '{a}'.",
|
||||
if (value === '__proto__' && !option.proto) {
|
||||
warningAt("The '{a}' property is deprecated.",
|
||||
line, from, value);
|
||||
} else if (option.nomen &&
|
||||
(value.charAt(0) === '_' ||
|
||||
} else if (value === '__iterator__' && !option.iterator) {
|
||||
warningAt("'{a}' is only available in JavaScript 1.7.",
|
||||
line, from, value);
|
||||
} else if (option.nomen && (value.charAt(0) === '_' ||
|
||||
value.charAt(value.length - 1) === '_')) {
|
||||
warningAt("Unexpected {a} in '{b}'.", line, from,
|
||||
"dangling '_'", value);
|
||||
|
|
@ -2141,12 +2173,14 @@ loop: for (;;) {
|
|||
|
||||
if (!t.block) {
|
||||
if (!option.expr && (!r || !r.exps)) {
|
||||
warning("Expected an assignment or function call and instead saw an expression.", token);
|
||||
warning("Expected an assignment or function call and instead saw an expression.",
|
||||
token);
|
||||
} else if (option.nonew && r.id === '(' && r.left.id === 'new') {
|
||||
warning("Do not use 'new' for side effects.");
|
||||
}
|
||||
if (nexttoken.id !== ';') {
|
||||
if (!option.asi && !(option.lastsemic && nexttoken.id == '}' && nexttoken.line == token.line)) {
|
||||
if (!option.asi && !(option.lastsemic && nexttoken.id == '}' &&
|
||||
nexttoken.line == token.line)) {
|
||||
warningAt("Missing semicolon.", token.line, token.from + token.value.length);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2509,7 +2543,10 @@ loop: for (;;) {
|
|||
});
|
||||
relation('===');
|
||||
relation('!=', function (left, right) {
|
||||
if (option.eqeqeq) {
|
||||
var eqnull = option.eqnull &&
|
||||
(left.value == 'null' || right.value == 'null');
|
||||
|
||||
if (!eqnull && option.eqeqeq) {
|
||||
warning("Expected '{a}' and instead saw '{b}'.",
|
||||
this, '!==', '!=');
|
||||
} else if (isPoorRelation(left)) {
|
||||
|
|
@ -2536,7 +2573,7 @@ loop: for (;;) {
|
|||
if (left && right && left.id === '(string)' && right.id === '(string)') {
|
||||
left.value += right.value;
|
||||
left.character = right.character;
|
||||
if (jx.test(left.value)) {
|
||||
if (!option.scripturl && jx.test(left.value)) {
|
||||
warning("JavaScript URL.", left);
|
||||
}
|
||||
return left;
|
||||
|
|
@ -2637,7 +2674,8 @@ loop: for (;;) {
|
|||
if (c.id !== 'function') {
|
||||
i = c.value.substr(0, 1);
|
||||
if (option.newcap && (i < 'A' || i > 'Z')) {
|
||||
warning("A constructor name should start with an uppercase letter.", token);
|
||||
warning("A constructor name should start with "+
|
||||
"an uppercase letter.", token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3043,8 +3081,9 @@ loop: for (;;) {
|
|||
|
||||
blockstmt('function', function () {
|
||||
if (inblock) {
|
||||
warning(
|
||||
"Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token);
|
||||
warning("Function declarations should not be placed in blocks. " +
|
||||
"Use a function expression or move the statement to the top of " +
|
||||
"the outer function.", token);
|
||||
|
||||
}
|
||||
var i = identifier();
|
||||
|
|
@ -3318,7 +3357,8 @@ loop: for (;;) {
|
|||
s = block(true, true);
|
||||
if (option.forin && (s.length > 1 || typeof s[0] !== 'object' ||
|
||||
s[0].value !== 'if')) {
|
||||
warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this);
|
||||
warning("The body of a for in should be wrapped in an if statement to filter " +
|
||||
"unwanted properties from the prototype.", this);
|
||||
}
|
||||
funct['(breakage)'] -= 1;
|
||||
funct['(loopage)'] -= 1;
|
||||
|
|
@ -3487,8 +3527,10 @@ loop: for (;;) {
|
|||
if (o[nexttoken.value] === true) {
|
||||
warning("Duplicate key '{a}'.",
|
||||
nexttoken, nexttoken.value);
|
||||
} else if (nexttoken.value === '__proto__') {
|
||||
warning("Stupid key '{a}'.",
|
||||
} else if ((nexttoken.value === '__proto__' &&
|
||||
!option.proto) || (nexttoken.value === '__iterator__' &&
|
||||
!option.iterator)) {
|
||||
warning("The '{a}' key may produce unexpected results.",
|
||||
nexttoken, nexttoken.value);
|
||||
} else {
|
||||
o[nexttoken.value] = true;
|
||||
|
|
@ -3574,7 +3616,7 @@ loop: for (;;) {
|
|||
} else if (typeof a === 'object') {
|
||||
k = Object.keys(a);
|
||||
for (i = 0; i < k.length; i += 1) {
|
||||
predefined[k[i]] = !!a[k];
|
||||
predefined[k[i]] = !!a[k[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3871,5 +3913,5 @@ loop: for (;;) {
|
|||
// Make JSHINT a Node module, if possible.
|
||||
if (typeof exports == 'object' && exports)
|
||||
exports.JSHINT = JSHINT;
|
||||
|
||||
|
||||
});
|
||||
|
|
@ -49,13 +49,15 @@ var WorkerClient = function(topLevelNamespaces, packagedJs, module, classname) {
|
|||
var worker = this.$worker = new Worker(base + packagedJs);
|
||||
}
|
||||
else {
|
||||
var workerUrl = require.nameToUrl("ace/worker/worker", null, "_");
|
||||
var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
|
||||
var worker = this.$worker = new Worker(workerUrl);
|
||||
|
||||
var tlns = {};
|
||||
for (var i=0; i<topLevelNamespaces.length; i++) {
|
||||
var ns = topLevelNamespaces[i];
|
||||
tlns[ns] = require.nameToUrl(ns, null, "_").replace(/.js$/, "");
|
||||
var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
|
||||
|
||||
tlns[ns] = path;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,20 +102,31 @@ var WorkerClient = function(topLevelNamespaces, packagedJs, module, classname) {
|
|||
|
||||
oop.implement(this, EventEmitter);
|
||||
|
||||
this.$normalizePath = function(path) {
|
||||
if (!path.match(/^\w+:/))
|
||||
path = location.protocol + "//" + location.host + location.pathname.replace(/\/.*?$/, "/") + "/" + path;
|
||||
return path;
|
||||
};
|
||||
|
||||
this.$guessBasePath = function() {
|
||||
if (require.aceBaseUrl)
|
||||
return require.aceBaseUrl;
|
||||
|
||||
var scripts = document.getElementsByTagName("script");
|
||||
for (var i=0; i<scripts.length; i++) {
|
||||
var src = scripts[i].src || scripts[i].getAttribute("src");
|
||||
var script = scripts[i];
|
||||
|
||||
var base = script.getAttribute("data-ace-base");
|
||||
if (base)
|
||||
return base.replace(/\/*$/, "/");
|
||||
|
||||
var src = script.src || script.getAttribute("src");
|
||||
if (!src) {
|
||||
continue;
|
||||
}
|
||||
var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace-uncompressed\.js)(?:\?|$)/);
|
||||
if (m) {
|
||||
if (m)
|
||||
return m[1] || m[2];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue