Merge master
This commit is contained in:
commit
1c5320f84e
406 changed files with 82454 additions and 34265 deletions
|
|
@ -56,7 +56,13 @@ var EditSession = require("./edit_session").EditSession;
|
|||
var UndoManager = require("./undomanager").UndoManager;
|
||||
var Renderer = require("./virtual_renderer").VirtualRenderer;
|
||||
|
||||
// The following require()s are for inclusion in the built ace file
|
||||
require("./worker/worker_client");
|
||||
require("./keyboard/hash_handler");
|
||||
require("./keyboard/state_handler");
|
||||
require("./lib/net");
|
||||
require("./placeholder");
|
||||
require("./config").init();
|
||||
|
||||
/**
|
||||
* Ace.edit(el) -> Editor
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ var CommandManager = function(platform, commands) {
|
|||
|
||||
var key = typeof binding == "string" ? binding: binding[this.platform];
|
||||
this.bindKey(key, command);
|
||||
}
|
||||
};
|
||||
|
||||
function parseKeys(keys, val, ret) {
|
||||
var key;
|
||||
|
|
@ -126,10 +126,10 @@ var CommandManager = function(platform, commands) {
|
|||
return {
|
||||
key: key,
|
||||
hashId: hashId
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function splitSafe(s, separator) {
|
||||
function splitSafe(s) {
|
||||
return (s.toLowerCase()
|
||||
.trim()
|
||||
.split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
|
||||
|
|
@ -143,7 +143,7 @@ var CommandManager = function(platform, commands) {
|
|||
|
||||
var ckbr = this.commmandKeyBinding;
|
||||
return ckbr[hashId] && ckbr[hashId][textOrKey.toLowerCase()];
|
||||
}
|
||||
};
|
||||
|
||||
this.exec = function(command, editor, args) {
|
||||
if (typeof command === 'string')
|
||||
|
|
@ -195,7 +195,7 @@ var CommandManager = function(platform, commands) {
|
|||
this.exec(x, editor);
|
||||
else
|
||||
this.exec(x[0], editor, x[1]);
|
||||
}, this)
|
||||
}, this);
|
||||
} finally {
|
||||
this.$inReplay = false;
|
||||
}
|
||||
|
|
@ -207,9 +207,9 @@ var CommandManager = function(platform, commands) {
|
|||
x[0] = x[0].name;
|
||||
if (!x[1])
|
||||
x = x[0];
|
||||
return x
|
||||
})
|
||||
}
|
||||
return x;
|
||||
});
|
||||
};
|
||||
|
||||
}).call(CommandManager.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -334,13 +334,13 @@ exports.commands = [{
|
|||
}, {
|
||||
name: "backspace",
|
||||
bindKey: bindKey(
|
||||
"Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
|
||||
"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
|
||||
"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
|
||||
),
|
||||
exec: function(editor) { editor.remove("left"); }
|
||||
}, {
|
||||
name: "removetolinestart",
|
||||
bindKey: bindKey("Alt-Backspace", "Option-Backspace"),
|
||||
bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
|
||||
exec: function(editor) { editor.removeToLineStart(); }
|
||||
}, {
|
||||
name: "removetolineend",
|
||||
|
|
|
|||
128
lib/ace/config.js
Normal file
128
lib/ace/config.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* vim:ts=4:sts=4:sw=4:
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Ajax.org Code Editor (ACE).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ajax.org B.V.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
*
|
||||
* 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) {
|
||||
"no use strict";
|
||||
|
||||
var lang = require("./lib/lang");
|
||||
|
||||
var global = (function() {
|
||||
return this;
|
||||
})();
|
||||
|
||||
var options = {
|
||||
packaged: false,
|
||||
workerPath: "",
|
||||
modePath: "",
|
||||
themePath: "",
|
||||
suffix: ".js"
|
||||
};
|
||||
|
||||
exports.get = function(key) {
|
||||
if (!options.hasOwnProperty(key))
|
||||
throw new Error("Unknown confik key: " + key);
|
||||
|
||||
return options[key];
|
||||
};
|
||||
|
||||
exports.set = function(key, value) {
|
||||
if (!options.hasOwnProperty(key))
|
||||
throw new Error("Unknown confik key: " + key);
|
||||
|
||||
options[key] = value;
|
||||
};
|
||||
|
||||
exports.all = function() {
|
||||
return lang.copyObject(options);
|
||||
};
|
||||
|
||||
exports.init = function() {
|
||||
options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
|
||||
|
||||
if (!global.document)
|
||||
return "";
|
||||
|
||||
var scriptOptions = {};
|
||||
var scriptUrl = "";
|
||||
var suffix;
|
||||
|
||||
var scripts = document.getElementsByTagName("script");
|
||||
for (var i=0; i<scripts.length; i++) {
|
||||
var script = scripts[i];
|
||||
|
||||
var src = script.src || script.getAttribute("src");
|
||||
if (!src) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var attributes = script.attributes;
|
||||
for (var j=0, l=attributes.length; j < l; j++) {
|
||||
var attr = attributes[j];
|
||||
if (attr.name.indexOf("data-ace-") === 0) {
|
||||
scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
|
||||
}
|
||||
}
|
||||
|
||||
var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace((-uncompressed)?(-noconflict)?\.js))(?:\?|$)/);
|
||||
if (m) {
|
||||
scriptUrl = m[1] || m[2];
|
||||
suffix = m[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptUrl) {
|
||||
scriptOptions.base = scriptOptions.base || scriptUrl;
|
||||
scriptOptions.packaged = true;
|
||||
}
|
||||
|
||||
scriptOptions.suffix = scriptOptions.suffix || suffix;
|
||||
scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
|
||||
scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
|
||||
scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
|
||||
delete scriptOptions.base;
|
||||
|
||||
for (var key in scriptOptions)
|
||||
if (typeof scriptOptions[key] !== "undefined")
|
||||
exports.set(key, scriptOptions[key]);
|
||||
};
|
||||
|
||||
function deHyphenate(str) {
|
||||
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -83,7 +83,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Replaces all the lines in the current `Document` with the value of `text`.
|
||||
**/
|
||||
this.setValue = function(text) {
|
||||
this.setValue = function(text) {
|
||||
var len = this.getLength();
|
||||
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
|
||||
this.insert({row: 0, column:0}, text);
|
||||
|
|
@ -94,7 +94,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Returns all the lines in the document as a single string, split by the new line character.
|
||||
**/
|
||||
this.getValue = function() {
|
||||
this.getValue = function() {
|
||||
return this.getAllLines().join(this.getNewLineCharacter());
|
||||
};
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Creates a new `Anchor` to define a floating point in the document.
|
||||
**/
|
||||
this.createAnchor = function(row, column) {
|
||||
this.createAnchor = function(row, column) {
|
||||
return new Anchor(this, row, column);
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ var Document = function(text) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$detectNewLine = function(text) {
|
||||
this.$detectNewLine = function(text) {
|
||||
var match = text.match(/^.*?(\r\n|\r|\n)/m);
|
||||
if (match) {
|
||||
this.$autoNewLine = match[1];
|
||||
|
|
@ -159,7 +159,7 @@ var Document = function(text) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.getNewLineCharacter = function() {
|
||||
this.getNewLineCharacter = function() {
|
||||
switch (this.$newLineMode) {
|
||||
case "windows":
|
||||
return "\r\n";
|
||||
|
|
@ -180,7 +180,7 @@ var Document = function(text) {
|
|||
*
|
||||
* [Sets the new line mode.]{: #Document.setNewLineMode.desc}
|
||||
**/
|
||||
this.setNewLineMode = function(newLineMode) {
|
||||
this.setNewLineMode = function(newLineMode) {
|
||||
if (this.$newLineMode === newLineMode)
|
||||
return;
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ var Document = function(text) {
|
|||
* [Returns the type of newlines being used; either `windows`, `unix`, or `auto`]{: #Document.getNewLineMode}
|
||||
*
|
||||
**/
|
||||
this.getNewLineMode = function() {
|
||||
this.getNewLineMode = function() {
|
||||
return this.$newLineMode;
|
||||
};
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ var Document = function(text) {
|
|||
* Returns `true` if `text` is a newline character (either `\r\n`, `\r`, or `\n`).
|
||||
*
|
||||
**/
|
||||
this.isNewLine = function(text) {
|
||||
this.isNewLine = function(text) {
|
||||
return (text == "\r\n" || text == "\r" || text == "\n");
|
||||
};
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ var Document = function(text) {
|
|||
* Returns a verbatim copy of the given line as it is in the document
|
||||
*
|
||||
**/
|
||||
this.getLine = function(row) {
|
||||
this.getLine = function(row) {
|
||||
return this.$lines[row] || "";
|
||||
};
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ var Document = function(text) {
|
|||
* Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
|
||||
*
|
||||
**/
|
||||
this.getLines = function(firstRow, lastRow) {
|
||||
this.getLines = function(firstRow, lastRow) {
|
||||
return this.$lines.slice(firstRow, lastRow + 1);
|
||||
};
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Returns all lines in the document as string array. <Warning>The caller should not modify this array!</Warning>
|
||||
**/
|
||||
this.getAllLines = function() {
|
||||
this.getAllLines = function() {
|
||||
return this.getLines(0, this.getLength());
|
||||
};
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Returns the number of rows in the document.
|
||||
**/
|
||||
this.getLength = function() {
|
||||
this.getLength = function() {
|
||||
return this.$lines.length;
|
||||
};
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ var Document = function(text) {
|
|||
*
|
||||
* [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
|
||||
**/
|
||||
this.getTextRange = function(range) {
|
||||
this.getTextRange = function(range) {
|
||||
if (range.start.row == range.end.row) {
|
||||
return this.$lines[range.start.row].substring(range.start.column,
|
||||
range.end.column);
|
||||
|
|
@ -274,7 +274,7 @@ var Document = function(text) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$clipPosition = function(position) {
|
||||
this.$clipPosition = function(position) {
|
||||
var length = this.getLength();
|
||||
if (position.row >= length) {
|
||||
position.row = Math.max(0, length - 1);
|
||||
|
|
@ -295,12 +295,13 @@ var Document = function(text) {
|
|||
* Returns the position of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
|
||||
*
|
||||
**/
|
||||
this.insert = function(position, text) {
|
||||
if (text.length == 0)
|
||||
this.insert = function(position, text) {
|
||||
if (!text || text.length === 0)
|
||||
return position;
|
||||
|
||||
position = this.$clipPosition(position);
|
||||
|
||||
// only detect new lines if the document has no line break yet
|
||||
if (this.getLength() <= 1)
|
||||
this.$detectNewLine(text);
|
||||
|
||||
|
|
@ -335,7 +336,7 @@ var Document = function(text) {
|
|||
* {row: row, column: 0}
|
||||
*
|
||||
**/
|
||||
this.insertLines = function(row, lines) {
|
||||
this.insertLines = function(row, lines) {
|
||||
if (lines.length == 0)
|
||||
return {row: row, column: 0};
|
||||
|
||||
|
|
@ -366,7 +367,7 @@ var Document = function(text) {
|
|||
* {row: endRow, column: 0}
|
||||
*
|
||||
**/
|
||||
this.insertNewLine = function(position) {
|
||||
this.insertNewLine = function(position) {
|
||||
position = this.$clipPosition(position);
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
|
|
@ -404,7 +405,7 @@ var Document = function(text) {
|
|||
* If `text` is empty, this function returns the value of `position`.
|
||||
*
|
||||
**/
|
||||
this.insertInLine = function(position, text) {
|
||||
this.insertInLine = function(position, text) {
|
||||
if (text.length == 0)
|
||||
return position;
|
||||
|
||||
|
|
@ -438,7 +439,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
|
||||
**/
|
||||
this.remove = function(range) {
|
||||
this.remove = function(range) {
|
||||
// clip to document
|
||||
range.start = this.$clipPosition(range.start);
|
||||
range.end = this.$clipPosition(range.end);
|
||||
|
|
@ -482,7 +483,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Returns an object containing `startRow` and `startColumn`, indicating the new row and column values. If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||
**/
|
||||
this.removeInLine = function(row, startColumn, endColumn) {
|
||||
this.removeInLine = function(row, startColumn, endColumn) {
|
||||
if (startColumn == endColumn)
|
||||
return;
|
||||
|
||||
|
|
@ -507,14 +508,14 @@ var Document = function(text) {
|
|||
* - lastRow (Number): The last row to be removed
|
||||
*
|
||||
* Removes a range of full lines. This method also triggers the `'change'` event.
|
||||
*
|
||||
*
|
||||
*
|
||||
* #### Returns
|
||||
*
|
||||
* Returns all the removed lines.
|
||||
*
|
||||
**/
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||
|
||||
|
|
@ -535,7 +536,7 @@ var Document = function(text) {
|
|||
* Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
|
||||
*
|
||||
**/
|
||||
this.removeNewLine = function(row) {
|
||||
this.removeNewLine = function(row) {
|
||||
var firstLine = this.getLine(row);
|
||||
var secondLine = this.getLine(row+1);
|
||||
|
||||
|
|
@ -570,7 +571,7 @@ var Document = function(text) {
|
|||
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
|
||||
*
|
||||
**/
|
||||
this.replace = function(range, text) {
|
||||
this.replace = function(range, text) {
|
||||
if (text.length == 0 && range.isEmpty())
|
||||
return range.start;
|
||||
|
||||
|
|
@ -595,7 +596,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
**/
|
||||
this.applyDeltas = function(deltas) {
|
||||
this.applyDeltas = function(deltas) {
|
||||
for (var i=0; i<deltas.length; i++) {
|
||||
var delta = deltas[i];
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
|
@ -616,7 +617,7 @@ var Document = function(text) {
|
|||
*
|
||||
* Reverts any changes previously applied. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
**/
|
||||
this.revertDeltas = function(deltas) {
|
||||
this.revertDeltas = function(deltas) {
|
||||
for (var i=deltas.length-1; i>=0; i--) {
|
||||
var delta = deltas[i];
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,10 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var config = require("./config");
|
||||
var oop = require("./lib/oop");
|
||||
var lang = require("./lib/lang");
|
||||
var net = require("./lib/net");
|
||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||
var Selection = require("./selection").Selection;
|
||||
var TextMode = require("./mode/text").Mode;
|
||||
|
|
@ -109,7 +111,7 @@ var EditSession = function(text, mode) {
|
|||
* Sets the `EditSession` to point to a new `Document`. If a `BackgroundTokenizer` exists, it also points to `doc`.
|
||||
*
|
||||
**/
|
||||
this.setDocument = function(doc) {
|
||||
this.setDocument = function(doc) {
|
||||
if (this.doc)
|
||||
throw new Error("Document is already set");
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns the `Document` associated with this session.
|
||||
*
|
||||
**/
|
||||
this.getDocument = function() {
|
||||
this.getDocument = function() {
|
||||
return this.doc;
|
||||
};
|
||||
|
||||
|
|
@ -140,7 +142,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$resetRowCache = function(row) {
|
||||
this.$resetRowCache = function(row) {
|
||||
if (row == 0) {
|
||||
this.$rowCache = [];
|
||||
return;
|
||||
|
|
@ -160,7 +162,7 @@ var EditSession = function(text, mode) {
|
|||
* Emitted when a code fold changes its state.
|
||||
*
|
||||
**/
|
||||
this.onChangeFold = function(e) {
|
||||
this.onChangeFold = function(e) {
|
||||
var fold = e.data;
|
||||
this.$resetRowCache(fold.start.row);
|
||||
};
|
||||
|
|
@ -170,7 +172,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Emitted when the document changes.
|
||||
**/
|
||||
this.onChange = function(e) {
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
this.$modified = true;
|
||||
|
||||
|
|
@ -200,7 +202,7 @@ var EditSession = function(text, mode) {
|
|||
* Sets the session text.
|
||||
*
|
||||
**/
|
||||
this.setValue = function(text) {
|
||||
this.setValue = function(text) {
|
||||
this.doc.setValue(text);
|
||||
this.selection.moveCursorTo(0, 0);
|
||||
this.selection.clearSelection();
|
||||
|
|
@ -225,7 +227,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
**/
|
||||
this.getValue =
|
||||
this.toString = function() {
|
||||
this.toString = function() {
|
||||
return this.doc.getValue();
|
||||
};
|
||||
|
||||
|
|
@ -234,7 +236,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the string of the current selection.
|
||||
**/
|
||||
this.getSelection = function() {
|
||||
this.getSelection = function() {
|
||||
return this.selection;
|
||||
};
|
||||
|
||||
|
|
@ -245,7 +247,7 @@ var EditSession = function(text, mode) {
|
|||
* {:BackgroundTokenizer.getState}
|
||||
*
|
||||
**/
|
||||
this.getState = function(row) {
|
||||
this.getState = function(row) {
|
||||
return this.bgTokenizer.getState(row);
|
||||
};
|
||||
|
||||
|
|
@ -257,7 +259,7 @@ var EditSession = function(text, mode) {
|
|||
* Starts tokenizing at the row indicated. Returns a list of objects of the tokenized rows.
|
||||
*
|
||||
**/
|
||||
this.getTokens = function(firstRow, lastRow) {
|
||||
this.getTokens = function(firstRow, lastRow) {
|
||||
return this.bgTokenizer.getTokens(firstRow, lastRow);
|
||||
};
|
||||
|
||||
|
|
@ -268,7 +270,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns an array of tokens at the indicated row and column.
|
||||
**/
|
||||
this.getTokenAt = function(row, column) {
|
||||
this.getTokenAt = function(row, column) {
|
||||
var tokens = this.bgTokenizer.getTokens(row, row)[0].tokens;
|
||||
var token, c = 0;
|
||||
if (column == null) {
|
||||
|
|
@ -295,7 +297,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets the undo manager.
|
||||
**/
|
||||
this.setUndoManager = function(undoManager) {
|
||||
this.setUndoManager = function(undoManager) {
|
||||
this.$undoManager = undoManager;
|
||||
this.$resetRowCache(0);
|
||||
this.$deltas = [];
|
||||
|
|
@ -312,7 +314,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$syncInformUndoManager = function() {
|
||||
this.$syncInformUndoManager = function() {
|
||||
self.$informUndoManager.cancel();
|
||||
|
||||
if (self.$deltasFold.length) {
|
||||
|
|
@ -356,7 +358,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the current undo manager.
|
||||
**/
|
||||
this.getUndoManager = function() {
|
||||
this.getUndoManager = function() {
|
||||
return this.$undoManager || this.$defaultUndoManager;
|
||||
},
|
||||
|
||||
|
|
@ -365,7 +367,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the current value for tabs. If the user is using soft tabs, this will be a series of spaces (defined by [[getTabSize `getTabSize()`]]); otherwise it's simply `'\t'`.
|
||||
**/
|
||||
this.getTabString = function() {
|
||||
this.getTabString = function() {
|
||||
if (this.getUseSoftTabs()) {
|
||||
return lang.stringRepeat(" ", this.getTabSize());
|
||||
} else {
|
||||
|
|
@ -381,7 +383,7 @@ var EditSession = function(text, mode) {
|
|||
* Pass `true` to enable the use of soft tabs. Soft tabs means you're using spaces instead of the tab character (`'\t'`).
|
||||
*
|
||||
**/
|
||||
this.setUseSoftTabs = function(useSoftTabs) {
|
||||
this.setUseSoftTabs = function(useSoftTabs) {
|
||||
if (this.$useSoftTabs === useSoftTabs) return;
|
||||
|
||||
this.$useSoftTabs = useSoftTabs;
|
||||
|
|
@ -393,7 +395,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns `true` if soft tabs are being used, `false` otherwise.
|
||||
*
|
||||
**/
|
||||
this.getUseSoftTabs = function() {
|
||||
this.getUseSoftTabs = function() {
|
||||
return this.$useSoftTabs;
|
||||
};
|
||||
|
||||
|
|
@ -404,7 +406,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Set the number of spaces that define a soft tab; for example, passing in `4` transforms the soft tabs to be equivalent to four spaces. This function also emits the `changeTabSize` event.
|
||||
**/
|
||||
this.setTabSize = function(tabSize) {
|
||||
this.setTabSize = function(tabSize) {
|
||||
if (isNaN(tabSize) || this.$tabSize === tabSize) return;
|
||||
|
||||
this.$modified = true;
|
||||
|
|
@ -417,7 +419,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the current tab size.
|
||||
**/
|
||||
this.getTabSize = function() {
|
||||
this.getTabSize = function() {
|
||||
return this.$tabSize;
|
||||
};
|
||||
|
||||
|
|
@ -427,7 +429,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns `true` if the character at the position is a soft tab.
|
||||
**/
|
||||
this.isTabStop = function(position) {
|
||||
this.isTabStop = function(position) {
|
||||
return this.$useSoftTabs && (position.column % this.$tabSize == 0);
|
||||
};
|
||||
|
||||
|
|
@ -439,7 +441,7 @@ var EditSession = function(text, mode) {
|
|||
* Pass in `true` to enable overwrites in your session, or `false` to disable. If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
|
||||
*
|
||||
**/
|
||||
this.setOverwrite = function(overwrite) {
|
||||
this.setOverwrite = function(overwrite) {
|
||||
if (this.$overwrite == overwrite) return;
|
||||
|
||||
this.$overwrite = overwrite;
|
||||
|
|
@ -451,7 +453,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns `true` if overwrites are enabled; `false` otherwise.
|
||||
**/
|
||||
this.getOverwrite = function() {
|
||||
this.getOverwrite = function() {
|
||||
return this.$overwrite;
|
||||
};
|
||||
|
||||
|
|
@ -460,7 +462,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets the value of overwrite to the opposite of whatever it currently is.
|
||||
**/
|
||||
this.toggleOverwrite = function() {
|
||||
this.toggleOverwrite = function() {
|
||||
this.setOverwrite(!this.$overwrite);
|
||||
};
|
||||
|
||||
|
|
@ -469,7 +471,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns an array of numbers, indicating which rows have breakpoints.
|
||||
**/
|
||||
this.getBreakpoints = function() {
|
||||
this.getBreakpoints = function() {
|
||||
return this.$breakpoints;
|
||||
};
|
||||
|
||||
|
|
@ -480,7 +482,7 @@ var EditSession = function(text, mode) {
|
|||
* Sets a breakpoint on every row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
|
||||
*
|
||||
**/
|
||||
this.setBreakpoints = function(rows) {
|
||||
this.setBreakpoints = function(rows) {
|
||||
this.$breakpoints = [];
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
this.$breakpoints[rows[i]] = true;
|
||||
|
|
@ -493,7 +495,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Removes all breakpoints on the rows. This function also emites the `'changeBreakpoint'` event.
|
||||
**/
|
||||
this.clearBreakpoints = function() {
|
||||
this.clearBreakpoints = function() {
|
||||
this.$breakpoints = [];
|
||||
this._emit("changeBreakpoint", {});
|
||||
};
|
||||
|
|
@ -504,7 +506,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets a breakpoint on the row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
|
||||
**/
|
||||
this.setBreakpoint = function(row) {
|
||||
this.setBreakpoint = function(row) {
|
||||
this.$breakpoints[row] = true;
|
||||
this._emit("changeBreakpoint", {});
|
||||
};
|
||||
|
|
@ -515,7 +517,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Removes a breakpoint on the row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
|
||||
**/
|
||||
this.clearBreakpoint = function(row) {
|
||||
this.clearBreakpoint = function(row) {
|
||||
delete this.$breakpoints[row];
|
||||
this._emit("changeBreakpoint", {});
|
||||
};
|
||||
|
|
@ -530,7 +532,7 @@ var EditSession = function(text, mode) {
|
|||
* Adds a new marker to the given `Range`. If `inFront` is `true`, a front marker is defined, and the `'changeFrontMarker'` event fires; otherwise, the `'changeBackMarker'` event fires.
|
||||
*
|
||||
**/
|
||||
this.addMarker = function(range, clazz, type, inFront) {
|
||||
this.addMarker = function(range, clazz, type, inFront) {
|
||||
var id = this.$markerId++;
|
||||
|
||||
var marker = {
|
||||
|
|
@ -559,7 +561,7 @@ var EditSession = function(text, mode) {
|
|||
* Removes the marker with the specified ID. If this marker was in front, the `'changeFrontMarker'` event is emitted. If the marker was in the back, the `'changeBackMarker'` event is emitted.
|
||||
*
|
||||
**/
|
||||
this.removeMarker = function(markerId) {
|
||||
this.removeMarker = function(markerId) {
|
||||
var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
|
||||
if (!marker)
|
||||
return;
|
||||
|
|
@ -578,7 +580,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns an array containing the IDs of all the markers, either front or back.
|
||||
*
|
||||
**/
|
||||
this.getMarkers = function(inFront) {
|
||||
this.getMarkers = function(inFront) {
|
||||
return inFront ? this.$frontMarkers : this.$backMarkers;
|
||||
};
|
||||
|
||||
|
|
@ -597,7 +599,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets annotations for the `EditSession`. This functions emits the `'changeAnnotation'` event.
|
||||
**/
|
||||
this.setAnnotations = function(annotations) {
|
||||
this.setAnnotations = function(annotations) {
|
||||
this.$annotations = {};
|
||||
for (var i=0; i<annotations.length; i++) {
|
||||
var annotation = annotations[i];
|
||||
|
|
@ -615,7 +617,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the annotations for the `EditSession`.
|
||||
**/
|
||||
this.getAnnotations = function() {
|
||||
this.getAnnotations = function() {
|
||||
return this.$annotations || {};
|
||||
};
|
||||
|
||||
|
|
@ -624,7 +626,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Clears all the annotations for this session. This function also triggers the `'changeAnnotation'` event.
|
||||
**/
|
||||
this.clearAnnotations = function() {
|
||||
this.clearAnnotations = function() {
|
||||
this.$annotations = {};
|
||||
this._emit("changeAnnotation", {});
|
||||
};
|
||||
|
|
@ -636,7 +638,7 @@ var EditSession = function(text, mode) {
|
|||
* If `text` contains either the newline (`\n`) or carriage-return ('\r') characters, [[autoNewLine `autoNewLine`]] stores that value.
|
||||
*
|
||||
**/
|
||||
this.$detectNewLine = function(text) {
|
||||
this.$detectNewLine = function(text) {
|
||||
var match = text.match(/^.*?(\r?\n)/m);
|
||||
if (match) {
|
||||
this.$autoNewLine = match[1];
|
||||
|
|
@ -653,7 +655,7 @@ var EditSession = function(text, mode) {
|
|||
* Given a starting row and column, this method returns the `Range` of the first word boundary it finds.
|
||||
*
|
||||
**/
|
||||
this.getWordRange = function(row, column) {
|
||||
this.getWordRange = function(row, column) {
|
||||
var line = this.getLine(row);
|
||||
|
||||
var inToken = false;
|
||||
|
|
@ -691,7 +693,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Gets the range of a word, including its right whitespace.
|
||||
**/
|
||||
this.getAWordRange = function(row, column) {
|
||||
this.getAWordRange = function(row, column) {
|
||||
var wordRange = this.getWordRange(row, column);
|
||||
var line = this.getLine(wordRange.end.row);
|
||||
|
||||
|
|
@ -707,7 +709,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* {:Document.setNewLineMode.desc}
|
||||
**/
|
||||
this.setNewLineMode = function(newLineMode) {
|
||||
this.setNewLineMode = function(newLineMode) {
|
||||
this.doc.setNewLineMode(newLineMode);
|
||||
};
|
||||
|
||||
|
|
@ -716,7 +718,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the current new line mode.
|
||||
**/
|
||||
this.getNewLineMode = function() {
|
||||
this.getNewLineMode = function() {
|
||||
return this.doc.getNewLineMode();
|
||||
};
|
||||
|
||||
|
|
@ -729,7 +731,7 @@ var EditSession = function(text, mode) {
|
|||
* Identifies if you want to use a worker for the `EditSession`.
|
||||
*
|
||||
**/
|
||||
this.setUseWorker = function(useWorker) {
|
||||
this.setUseWorker = function(useWorker) {
|
||||
if (this.$useWorker == useWorker)
|
||||
return;
|
||||
|
||||
|
|
@ -745,7 +747,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns `true` if workers are being used.
|
||||
**/
|
||||
this.getUseWorker = function() {
|
||||
this.getUseWorker = function() {
|
||||
return this.$useWorker;
|
||||
};
|
||||
|
||||
|
|
@ -754,24 +756,79 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Reloads all the tokens on the current session. This function calls [[BackgroundTokenizer.start `BackgroundTokenizer.start ()`]] to all the rows; it also emits the `'tokenizerUpdate'` event.
|
||||
**/
|
||||
this.onReloadTokenizer = function(e) {
|
||||
this.onReloadTokenizer = function(e) {
|
||||
var rows = e.data;
|
||||
this.bgTokenizer.start(rows.first);
|
||||
this._emit("tokenizerUpdate", e);
|
||||
};
|
||||
|
||||
this.$modes = {};
|
||||
this._loadMode = function(mode, callback) {
|
||||
if (this.$modes[mode])
|
||||
return callback(this.$modes[mode]);
|
||||
|
||||
var _self = this;
|
||||
var module;
|
||||
try {
|
||||
module = require(mode);
|
||||
} catch (e) {};
|
||||
if (module)
|
||||
return done(module);
|
||||
|
||||
fetch(function() {
|
||||
require([mode], done);
|
||||
});
|
||||
|
||||
function done(module) {
|
||||
if (_self.$modes[mode])
|
||||
return callback(_self.$modes[mode]);
|
||||
|
||||
_self.$modes[mode] = new module.Mode();
|
||||
_self._emit("loadmode", {
|
||||
name: mode,
|
||||
mode: _self.$modes[mode]
|
||||
});
|
||||
callback(_self.$modes[mode]);
|
||||
}
|
||||
|
||||
function fetch(callback) {
|
||||
if (!config.get("packaged"))
|
||||
return callback();
|
||||
|
||||
var base = mode.split("/").pop();
|
||||
var filename = config.get("modePath") + "/mode-" + base + config.get("suffix");
|
||||
net.loadScript(filename, callback);
|
||||
}
|
||||
};
|
||||
|
||||
this.$mode = null;
|
||||
/**
|
||||
this.$origMode = null;
|
||||
/**
|
||||
* EditSession.setMode(mode) -> Void
|
||||
* - mode (TextMode): Set a new text mode
|
||||
*
|
||||
* Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted.
|
||||
*
|
||||
**/
|
||||
this.setMode = function(mode) {
|
||||
this.setMode = function(mode) {
|
||||
this.$origMode = mode;
|
||||
|
||||
// load on demand
|
||||
if (typeof mode === "string") {
|
||||
var _self = this;
|
||||
this._loadMode(mode, function(module) {
|
||||
if (_self.$origMode !== mode)
|
||||
return;
|
||||
|
||||
_self.setMode(module);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$mode === mode) return;
|
||||
this.$mode = mode;
|
||||
|
||||
|
||||
this.$stopWorker();
|
||||
|
||||
if (this.$useWorker)
|
||||
|
|
@ -810,7 +867,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$stopWorker = function() {
|
||||
this.$stopWorker = function() {
|
||||
if (this.$worker)
|
||||
this.$worker.terminate();
|
||||
|
||||
|
|
@ -822,7 +879,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$startWorker = function() {
|
||||
this.$startWorker = function() {
|
||||
if (typeof Worker !== "undefined" && !require.noWorker) {
|
||||
try {
|
||||
this.$worker = this.$mode.createWorker(this);
|
||||
|
|
@ -841,7 +898,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the current text mode.
|
||||
**/
|
||||
this.getMode = function() {
|
||||
this.getMode = function() {
|
||||
return this.$mode;
|
||||
};
|
||||
|
||||
|
|
@ -852,7 +909,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* This function sets the scroll top value. It also emits the `'changeScrollTop'` event.
|
||||
**/
|
||||
this.setScrollTop = function(scrollTop) {
|
||||
this.setScrollTop = function(scrollTop) {
|
||||
scrollTop = Math.round(Math.max(0, scrollTop));
|
||||
if (this.$scrollTop === scrollTop)
|
||||
return;
|
||||
|
|
@ -866,7 +923,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* [Returns the value of the distance between the top of the editor and the topmost part of the visible content.]{: #EditSession.getScrollTop}
|
||||
**/
|
||||
this.getScrollTop = function() {
|
||||
this.getScrollTop = function() {
|
||||
return this.$scrollTop;
|
||||
};
|
||||
|
||||
|
|
@ -876,7 +933,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* [Sets the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.setScrollLeft}
|
||||
**/
|
||||
this.setScrollLeft = function(scrollLeft) {
|
||||
this.setScrollLeft = function(scrollLeft) {
|
||||
scrollLeft = Math.round(Math.max(0, scrollLeft));
|
||||
if (this.$scrollLeft === scrollLeft)
|
||||
return;
|
||||
|
|
@ -890,7 +947,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* [Returns the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.getScrollLeft}
|
||||
**/
|
||||
this.getScrollLeft = function() {
|
||||
this.getScrollLeft = function() {
|
||||
return this.$scrollLeft;
|
||||
};
|
||||
|
||||
|
|
@ -899,7 +956,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the width of the document.
|
||||
**/
|
||||
this.getWidth = function() {
|
||||
this.getWidth = function() {
|
||||
this.$computeWidth();
|
||||
return this.width;
|
||||
};
|
||||
|
|
@ -909,12 +966,12 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the width of the screen.
|
||||
**/
|
||||
this.getScreenWidth = function() {
|
||||
this.getScreenWidth = function() {
|
||||
this.$computeWidth();
|
||||
return this.screenWidth;
|
||||
};
|
||||
|
||||
this.$computeWidth = function(force) {
|
||||
this.$computeWidth = function(force) {
|
||||
if (this.$modified || force) {
|
||||
this.$modified = false;
|
||||
|
||||
|
|
@ -960,7 +1017,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns a verbatim copy of the given line as it is in the document
|
||||
*
|
||||
**/
|
||||
this.getLine = function(row) {
|
||||
this.getLine = function(row) {
|
||||
return this.doc.getLine(row);
|
||||
};
|
||||
|
||||
|
|
@ -972,7 +1029,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
|
||||
*
|
||||
**/
|
||||
this.getLines = function(firstRow, lastRow) {
|
||||
this.getLines = function(firstRow, lastRow) {
|
||||
return this.doc.getLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
|
|
@ -981,7 +1038,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the number of rows in the document.
|
||||
**/
|
||||
this.getLength = function() {
|
||||
this.getLength = function() {
|
||||
return this.doc.getLength();
|
||||
};
|
||||
|
||||
|
|
@ -991,7 +1048,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* {:Document.getTextRange.desc}
|
||||
**/
|
||||
this.getTextRange = function(range) {
|
||||
this.getTextRange = function(range) {
|
||||
return this.doc.getTextRange(range);
|
||||
};
|
||||
|
||||
|
|
@ -1007,7 +1064,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns the position of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
|
||||
*
|
||||
**/
|
||||
this.insert = function(position, text) {
|
||||
this.insert = function(position, text) {
|
||||
return this.doc.insert(position, text);
|
||||
};
|
||||
|
||||
|
|
@ -1021,7 +1078,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
|
||||
**/
|
||||
this.remove = function(range) {
|
||||
this.remove = function(range) {
|
||||
return this.doc.remove(range);
|
||||
};
|
||||
|
||||
|
|
@ -1032,7 +1089,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Reverts previous changes to your document.
|
||||
**/
|
||||
this.undoChanges = function(deltas, dontSelect) {
|
||||
this.undoChanges = function(deltas, dontSelect) {
|
||||
if (!deltas.length)
|
||||
return;
|
||||
|
||||
|
|
@ -1065,7 +1122,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Re-implements a previously undone change to your document.
|
||||
**/
|
||||
this.redoChanges = function(deltas, dontSelect) {
|
||||
this.redoChanges = function(deltas, dontSelect) {
|
||||
if (!deltas.length)
|
||||
return;
|
||||
|
||||
|
|
@ -1093,7 +1150,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* ENables or disables highlighting of the range where an undo occured.
|
||||
**/
|
||||
this.setUndoSelect = function(enable) {
|
||||
this.setUndoSelect = function(enable) {
|
||||
this.$undoSelect = enable;
|
||||
};
|
||||
|
||||
|
|
@ -1102,7 +1159,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
|
||||
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
|
||||
function isInsert(delta) {
|
||||
var insert =
|
||||
delta.action == "insertText" || delta.action == "insertLines";
|
||||
|
|
@ -1174,7 +1231,7 @@ var EditSession = function(text, mode) {
|
|||
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
|
||||
*
|
||||
**/
|
||||
this.replace = function(range, text) {
|
||||
this.replace = function(range, text) {
|
||||
return this.doc.replace(range, text);
|
||||
};
|
||||
|
||||
|
|
@ -1182,7 +1239,7 @@ var EditSession = function(text, mode) {
|
|||
* EditSession.moveText(fromRange, toPosition) -> Range
|
||||
* - fromRange (Range): The range of text you want moved within the document
|
||||
* - toPosition (Object): The location (row and column) where you want to move the text to
|
||||
*
|
||||
*
|
||||
* Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
|
||||
*
|
||||
* { row: newRowLocation, column: newColumnLocation }
|
||||
|
|
@ -1193,7 +1250,7 @@ var EditSession = function(text, mode) {
|
|||
* The new range where the text was moved to.
|
||||
*
|
||||
**/
|
||||
this.moveText = function(fromRange, toPosition) {
|
||||
this.moveText = function(fromRange, toPosition) {
|
||||
var text = this.getTextRange(fromRange);
|
||||
this.remove(fromRange);
|
||||
|
||||
|
|
@ -1234,7 +1291,7 @@ var EditSession = function(text, mode) {
|
|||
* If `indentString` contains the `'\t'` character, it's replaced by whatever is defined by [[getTabString `getTabString()`]].
|
||||
*
|
||||
**/
|
||||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
indentString = indentString.replace(/\t/g, this.getTabString());
|
||||
for (var row=startRow; row<=endRow; row++)
|
||||
this.insert({row: row, column:0}, indentString);
|
||||
|
|
@ -1283,7 +1340,7 @@ var EditSession = function(text, mode) {
|
|||
* If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
**/
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
if (firstRow <= 0) return 0;
|
||||
|
||||
var removed = this.doc.removeLines(firstRow, lastRow);
|
||||
|
|
@ -1303,7 +1360,7 @@ var EditSession = function(text, mode) {
|
|||
* If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
**/
|
||||
this.moveLinesDown = function(firstRow, lastRow) {
|
||||
this.moveLinesDown = function(firstRow, lastRow) {
|
||||
if (lastRow >= this.doc.getLength()-1) return 0;
|
||||
|
||||
var removed = this.doc.removeLines(firstRow, lastRow);
|
||||
|
|
@ -1323,7 +1380,7 @@ var EditSession = function(text, mode) {
|
|||
* Returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
|
||||
*
|
||||
**/
|
||||
this.duplicateLines = function(firstRow, lastRow) {
|
||||
this.duplicateLines = function(firstRow, lastRow) {
|
||||
var firstRow = this.$clipRowToDocument(firstRow);
|
||||
var lastRow = this.$clipRowToDocument(lastRow);
|
||||
|
||||
|
|
@ -1335,18 +1392,18 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
|
||||
|
||||
this.$clipRowToDocument = function(row) {
|
||||
this.$clipRowToDocument = function(row) {
|
||||
return Math.max(0, Math.min(row, this.doc.getLength()-1));
|
||||
};
|
||||
|
||||
this.$clipColumnToRow = function(row, column) {
|
||||
this.$clipColumnToRow = function(row, column) {
|
||||
if (column < 0)
|
||||
return 0;
|
||||
return Math.min(this.doc.getLine(row).length, column);
|
||||
};
|
||||
|
||||
|
||||
this.$clipPositionToDocument = function(row, column) {
|
||||
this.$clipPositionToDocument = function(row, column) {
|
||||
column = Math.max(0, column);
|
||||
|
||||
if (row < 0) {
|
||||
|
|
@ -1368,7 +1425,7 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
};
|
||||
|
||||
this.$clipRangeToDocument = function(range) {
|
||||
this.$clipRangeToDocument = function(range) {
|
||||
if (range.start.row < 0) {
|
||||
range.start.row = 0;
|
||||
range.start.column = 0
|
||||
|
|
@ -1406,7 +1463,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets whether or not line wrapping is enabled. If `useWrapMode` is different than the current value, the `'changeWrapMode'` event is emitted.
|
||||
**/
|
||||
this.setUseWrapMode = function(useWrapMode) {
|
||||
this.setUseWrapMode = function(useWrapMode) {
|
||||
if (useWrapMode != this.$useWrapMode) {
|
||||
this.$useWrapMode = useWrapMode;
|
||||
this.$modified = true;
|
||||
|
|
@ -1431,7 +1488,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns `true` if wrap mode is being used; `false` otherwise.
|
||||
**/
|
||||
this.getUseWrapMode = function() {
|
||||
this.getUseWrapMode = function() {
|
||||
return this.$useWrapMode;
|
||||
};
|
||||
|
||||
|
|
@ -1446,7 +1503,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Sets the boundaries of wrap. Either value can be `null` to have an unconstrained wrap, or, they can be the same number to pin the limit. If the wrap limits for `min` or `max` are different, this method also emits the `'changeWrapMode'` event.
|
||||
**/
|
||||
this.setWrapLimitRange = function(min, max) {
|
||||
this.setWrapLimitRange = function(min, max) {
|
||||
if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
|
||||
this.$wrapLimitRange.min = min;
|
||||
this.$wrapLimitRange.max = max;
|
||||
|
|
@ -1462,7 +1519,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* This should generally only be called by the renderer when a resize is detected.
|
||||
**/
|
||||
this.adjustWrapLimit = function(desiredLimit) {
|
||||
this.adjustWrapLimit = function(desiredLimit) {
|
||||
var wrapLimit = this.$constrainWrapLimit(desiredLimit);
|
||||
if (wrapLimit != this.$wrapLimit && wrapLimit > 0) {
|
||||
this.$wrapLimit = wrapLimit;
|
||||
|
|
@ -1482,7 +1539,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$constrainWrapLimit = function(wrapLimit) {
|
||||
this.$constrainWrapLimit = function(wrapLimit) {
|
||||
var min = this.$wrapLimitRange.min;
|
||||
if (min)
|
||||
wrapLimit = Math.max(min, wrapLimit);
|
||||
|
|
@ -1500,7 +1557,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the value of wrap limit.
|
||||
**/
|
||||
this.getWrapLimit = function() {
|
||||
this.getWrapLimit = function() {
|
||||
return this.$wrapLimit;
|
||||
};
|
||||
|
||||
|
|
@ -1512,7 +1569,7 @@ var EditSession = function(text, mode) {
|
|||
* { min: wrapLimitRange_min, max: wrapLimitRange_max }
|
||||
*
|
||||
**/
|
||||
this.getWrapLimitRange = function() {
|
||||
this.getWrapLimitRange = function() {
|
||||
// Avoid unexpected mutation by returning a copy
|
||||
return {
|
||||
min : this.$wrapLimitRange.min,
|
||||
|
|
@ -1525,7 +1582,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$updateInternalDataOnChange = function(e) {
|
||||
this.$updateInternalDataOnChange = function(e) {
|
||||
var useWrapMode = this.$useWrapMode;
|
||||
var len;
|
||||
var action = e.data.action;
|
||||
|
|
@ -1645,7 +1702,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$updateWrapData = function(firstRow, lastRow) {
|
||||
this.$updateWrapData = function(firstRow, lastRow) {
|
||||
var lines = this.doc.getAllLines();
|
||||
var tabSize = this.getTabSize();
|
||||
var wrapData = this.$wrapData;
|
||||
|
|
@ -1709,7 +1766,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.$computeWrapSplits = function(tokens, wrapLimit) {
|
||||
this.$computeWrapSplits = function(tokens, wrapLimit) {
|
||||
if (tokens.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -1832,7 +1889,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Given a string, returns an array of the display characters, including tabs and spaces.
|
||||
**/
|
||||
this.$getDisplayTokens = function(str, offset) {
|
||||
this.$getDisplayTokens = function(str, offset) {
|
||||
var arr = [];
|
||||
var tabSize;
|
||||
offset = offset || 0;
|
||||
|
|
@ -1874,9 +1931,9 @@ var EditSession = function(text, mode) {
|
|||
* #### Returns
|
||||
*
|
||||
* Returns an `int[]` array with two elements. The first position indicates the number of columns for `str` on screen. The second value contains the position of the document column that this function read until.
|
||||
*
|
||||
*
|
||||
**/
|
||||
this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
|
||||
this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
|
||||
if (maxScreenColumn == 0) {
|
||||
return [0, 0];
|
||||
}
|
||||
|
|
@ -1914,7 +1971,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the length of the indicated row.
|
||||
**/
|
||||
this.getRowLength = function(row) {
|
||||
this.getRowLength = function(row) {
|
||||
if (!this.$useWrapMode || !this.$wrapData[row]) {
|
||||
return 1;
|
||||
} else {
|
||||
|
|
@ -1929,8 +1986,8 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the height of the indicated row. This is mostly relevant for situations where wrapping occurs, and a single line spans across multiple rows.
|
||||
*
|
||||
**/
|
||||
this.getRowHeight = function(config, row) {
|
||||
**/
|
||||
this.getRowHeight = function(config, row) {
|
||||
return this.getRowLength(row) * config.lineHeight;
|
||||
}
|
||||
|
||||
|
|
@ -1940,7 +1997,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the column position (on screen) for the last character in the provided row.
|
||||
**/
|
||||
this.getScreenLastRowColumn = function(screenRow) {
|
||||
this.getScreenLastRowColumn = function(screenRow) {
|
||||
//return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
|
||||
return this.documentToScreenColumn(screenRow, this.doc.getLine(screenRow).length);
|
||||
};
|
||||
|
|
@ -1951,7 +2008,7 @@ var EditSession = function(text, mode) {
|
|||
* - docColumn (Number):
|
||||
*
|
||||
**/
|
||||
this.getDocumentLastRowColumn = function(docRow, docColumn) {
|
||||
this.getDocumentLastRowColumn = function(docRow, docColumn) {
|
||||
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
||||
return this.getScreenLastRowColumn(screenRow);
|
||||
};
|
||||
|
|
@ -1960,7 +2017,7 @@ var EditSession = function(text, mode) {
|
|||
* EditSession.getDocumentLastRowColumnPosition(docRow, docColumn) -> Number
|
||||
*
|
||||
**/
|
||||
this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
|
||||
this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
|
||||
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
||||
return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
|
||||
};
|
||||
|
|
@ -1969,7 +2026,7 @@ var EditSession = function(text, mode) {
|
|||
* EditSession.getRowSplitData(row) -> undefined | String
|
||||
*
|
||||
**/
|
||||
this.getRowSplitData = function(row) {
|
||||
this.getRowSplitData = function(row) {
|
||||
if (!this.$useWrapMode) {
|
||||
return undefined;
|
||||
} else {
|
||||
|
|
@ -1983,7 +2040,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* The distance to the next tab stop at the specified screen column.
|
||||
**/
|
||||
this.getScreenTabSize = function(screenColumn) {
|
||||
this.getScreenTabSize = function(screenColumn) {
|
||||
return this.$tabSize - screenColumn % this.$tabSize;
|
||||
};
|
||||
|
||||
|
|
@ -1992,7 +2049,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.screenToDocumentRow = function(screenRow, screenColumn) {
|
||||
this.screenToDocumentRow = function(screenRow, screenColumn) {
|
||||
return this.screenToDocumentPosition(screenRow, screenColumn).row;
|
||||
};
|
||||
|
||||
|
|
@ -2001,7 +2058,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.screenToDocumentColumn = function(screenRow, screenColumn) {
|
||||
this.screenToDocumentColumn = function(screenRow, screenColumn) {
|
||||
return this.screenToDocumentPosition(screenRow, screenColumn).column;
|
||||
};
|
||||
|
||||
|
|
@ -2017,7 +2074,7 @@ var EditSession = function(text, mode) {
|
|||
* The object returned has two properties: `row` and `column`.
|
||||
*
|
||||
**/
|
||||
this.screenToDocumentPosition = function(screenRow, screenColumn) {
|
||||
this.screenToDocumentPosition = function(screenRow, screenColumn) {
|
||||
if (screenRow < 0) {
|
||||
return {
|
||||
row: 0,
|
||||
|
|
@ -2131,7 +2188,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.documentToScreenPosition = function(docRow, docColumn) {
|
||||
this.documentToScreenPosition = function(docRow, docColumn) {
|
||||
// Normalize the passed in arguments.
|
||||
if (typeof docColumn === "undefined")
|
||||
var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
|
||||
|
|
@ -2239,7 +2296,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.documentToScreenColumn = function(row, docColumn) {
|
||||
this.documentToScreenColumn = function(row, docColumn) {
|
||||
return this.documentToScreenPosition(row, docColumn).column;
|
||||
};
|
||||
|
||||
|
|
@ -2248,7 +2305,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.documentToScreenRow = function(docRow, docColumn) {
|
||||
this.documentToScreenRow = function(docRow, docColumn) {
|
||||
return this.documentToScreenPosition(docRow, docColumn).row;
|
||||
};
|
||||
|
||||
|
|
@ -2257,7 +2314,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
* Returns the length of the screen.
|
||||
**/
|
||||
this.getScreenLength = function() {
|
||||
this.getScreenLength = function() {
|
||||
var screenRows = 0;
|
||||
var fold = null;
|
||||
if (!this.$useWrapMode) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -395,6 +395,7 @@ function setupSettingPanel(settingDiv, settingOpener, api, options) {
|
|||
svg: "SVG",
|
||||
textile: "Textile",
|
||||
groovy: "Groovy",
|
||||
liquid: "Liquid",
|
||||
Scala: "Scala"
|
||||
},
|
||||
theme: {
|
||||
|
|
|
|||
|
|
@ -52,12 +52,12 @@ var CstyleBehaviour = function () {
|
|||
return {
|
||||
text: '{' + selected + '}',
|
||||
selection: false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
text: '{}',
|
||||
selection: [1, 1]
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (text == '}') {
|
||||
var cursor = editor.getCursorPosition();
|
||||
|
|
@ -69,7 +69,7 @@ var CstyleBehaviour = function () {
|
|||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} else if (text == "\n") {
|
||||
|
|
@ -87,7 +87,7 @@ var CstyleBehaviour = function () {
|
|||
return {
|
||||
text: '\n' + indent + '\n' + next_indent,
|
||||
selection: [1, indent.length, 1, indent.length]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -112,12 +112,12 @@ var CstyleBehaviour = function () {
|
|||
return {
|
||||
text: '(' + selected + ')',
|
||||
selection: false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
text: '()',
|
||||
selection: [1, 1]
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (text == ')') {
|
||||
var cursor = editor.getCursorPosition();
|
||||
|
|
@ -129,7 +129,7 @@ var CstyleBehaviour = function () {
|
|||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -148,14 +148,15 @@ var CstyleBehaviour = function () {
|
|||
});
|
||||
|
||||
this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == '"') {
|
||||
if (text == '"' || text == "'") {
|
||||
var quote = text;
|
||||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "") {
|
||||
return {
|
||||
text: '"' + selected + '"',
|
||||
text: quote + selected + quote,
|
||||
selection: false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
|
|
@ -176,7 +177,7 @@ var CstyleBehaviour = function () {
|
|||
if (token.type == "string") {
|
||||
quotepos = -1;
|
||||
} else if (quotepos < 0) {
|
||||
quotepos = token.value.indexOf('"');
|
||||
quotepos = token.value.indexOf(quote);
|
||||
}
|
||||
if ((token.value.length + col) > selection.start.column) {
|
||||
break;
|
||||
|
|
@ -185,19 +186,19 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
|
||||
// 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)))) {
|
||||
if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
|
||||
return {
|
||||
text: '""',
|
||||
text: quote + quote,
|
||||
selection: [1,1]
|
||||
}
|
||||
};
|
||||
} else if (token && token.type === "string") {
|
||||
// Ignore input and move right one if we're typing over the closing quote.
|
||||
var rightChar = line.substring(cursor.column, cursor.column + 1);
|
||||
if (rightChar == '"') {
|
||||
if (rightChar == quote) {
|
||||
return {
|
||||
text: '',
|
||||
selection: [1, 1]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +207,7 @@ var CstyleBehaviour = function () {
|
|||
|
||||
this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
|
||||
var selected = session.doc.getTextRange(range);
|
||||
if (!range.isMultiLine() && selected == '"') {
|
||||
if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
|
||||
var line = session.doc.getLine(range.start.row);
|
||||
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
|
||||
if (rightChar == '"') {
|
||||
|
|
@ -216,7 +217,8 @@ var CstyleBehaviour = function () {
|
|||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
oop.inherits(CstyleBehaviour, Behaviour);
|
||||
|
||||
exports.CstyleBehaviour = CstyleBehaviour;
|
||||
|
|
|
|||
68
lib/ace/mode/behaviour/xquery.js
Normal file
68
lib/ace/mode/behaviour/xquery.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* eXide - web-based XQuery IDE
|
||||
*
|
||||
* Copyright (C) 2011 Wolfgang Meier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../../lib/oop");
|
||||
var Behaviour = require('../behaviour').Behaviour;
|
||||
var CstyleBehaviour = require('./cstyle').CstyleBehaviour;
|
||||
|
||||
var XQueryBehaviour = function (parent) {
|
||||
|
||||
this.inherit(CstyleBehaviour, ["braces", "parens", "string_dquotes"]); // Get string behaviour
|
||||
this.parent = parent;
|
||||
|
||||
this.add("brackets", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == "\n") {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var rightChars = line.substring(cursor.column, cursor.column + 2);
|
||||
if (rightChars == '</') {
|
||||
var indent = this.$getIndent(session.doc.getLine(cursor.row)) + session.getTabString();
|
||||
var next_indent = this.$getIndent(session.doc.getLine(cursor.row));
|
||||
|
||||
return {
|
||||
text: '\n' + indent + '\n' + next_indent,
|
||||
selection: [1, indent.length, 1, indent.length]
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Check for open tag if user enters / and auto-close it.
|
||||
this.add("slash", "insertion", function (state, action, editor, session, text) {
|
||||
if (text == "/") {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
if (cursor.column > 0 && line.charAt(cursor.column - 1) == "<") {
|
||||
line = line.substring(0, cursor.column) + "/" + line.substring(cursor.column);
|
||||
var lines = session.doc.getAllLines();
|
||||
lines[cursor.row] = line;
|
||||
// call mode helper to close the tag if possible
|
||||
parent.exec("closeTag", lines.join(session.doc.getNewLineCharacter()), cursor.row);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
oop.inherits(XQueryBehaviour, Behaviour);
|
||||
|
||||
exports.XQueryBehaviour = XQueryBehaviour;
|
||||
});
|
||||
|
|
@ -138,9 +138,9 @@ var ClojureHighlightRules = function() {
|
|||
token : "comment",
|
||||
regex : ";.*$"
|
||||
}, {
|
||||
token : "comment", // multi line comment
|
||||
regex : "^\=begin$",
|
||||
next : "comment"
|
||||
token : "comment", // multi line comment
|
||||
regex : "^=begin$",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "keyword", //parens
|
||||
regex : "[\\(|\\)]"
|
||||
|
|
@ -193,17 +193,17 @@ var ClojureHighlightRules = function() {
|
|||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // symbol
|
||||
regex : "[:](?:[a-zA-Z]|\d)+"
|
||||
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$",
|
||||
regex : "^=end$",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment", // comment spanning whole line
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
|
|
@ -24,41 +24,44 @@
|
|||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Generated by CoffeeScript 1.2.1-pre
|
||||
|
||||
var extend, flatten;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
};
|
||||
|
||||
exports.ends = function(string, literal, back) {
|
||||
var len;
|
||||
len = literal.length;
|
||||
return literal === string.substr(string.length - len - (back || 0), len);
|
||||
};
|
||||
|
||||
exports.compact = function(array) {
|
||||
var item, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
item = array[_i];
|
||||
if (item) {
|
||||
_results.push(item);
|
||||
}
|
||||
if (item) _results.push(item);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
exports.count = function(string, substr) {
|
||||
var num, pos;
|
||||
num = pos = 0;
|
||||
if (!substr.length) {
|
||||
return 1 / 0;
|
||||
}
|
||||
if (!substr.length) return 1 / 0;
|
||||
while (pos = 1 + string.indexOf(substr, pos)) {
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
|
||||
exports.merge = function(options, overrides) {
|
||||
return extend(extend({}, options), overrides);
|
||||
};
|
||||
|
||||
extend = exports.extend = function(object, properties) {
|
||||
var key, val;
|
||||
for (key in properties) {
|
||||
|
|
@ -67,6 +70,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
exports.flatten = flatten = function(array) {
|
||||
var element, flattened, _i, _len;
|
||||
flattened = [];
|
||||
|
|
@ -80,13 +84,17 @@ define(function(require, exports, module) {
|
|||
}
|
||||
return flattened;
|
||||
};
|
||||
|
||||
exports.del = function(obj, key) {
|
||||
var val;
|
||||
val = obj[key];
|
||||
delete obj[key];
|
||||
return val;
|
||||
};
|
||||
|
||||
exports.last = function(array, back) {
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
|
|
@ -24,26 +24,25 @@
|
|||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
Rewriter = require('./rewriter').Rewriter;
|
||||
_ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
|
||||
// Generated by CoffeeScript 1.2.1-pre
|
||||
|
||||
var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
|
||||
|
||||
_ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last;
|
||||
|
||||
exports.Lexer = Lexer = (function() {
|
||||
|
||||
Lexer.name = 'Lexer';
|
||||
|
||||
function Lexer() {}
|
||||
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var i;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
}
|
||||
var i, tag;
|
||||
if (opts == null) opts = {};
|
||||
if (WHITESPACE.test(code)) code = "\n" + code;
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
this.code = code;
|
||||
this.line = opts.line || 0;
|
||||
|
|
@ -51,22 +50,21 @@ define(function(require, exports, module) {
|
|||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.ends = [];
|
||||
this.tokens = [];
|
||||
i = 0;
|
||||
while (this.chunk = code.slice(i)) {
|
||||
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (opts.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
if (tag = this.ends.pop()) this.error("missing " + tag);
|
||||
if (opts.rewrite === false) return this.tokens;
|
||||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
this.token('OWN', id);
|
||||
|
|
@ -74,7 +72,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
|
||||
tag = 'IDENTIFIER';
|
||||
if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
|
||||
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
|
|
@ -103,13 +101,11 @@ define(function(require, exports, module) {
|
|||
id = new String(id);
|
||||
id.reserved = true;
|
||||
} else if (__indexOf.call(RESERVED, id) >= 0) {
|
||||
this.identifierError(id);
|
||||
this.error("reserved word \"" + id + "\"");
|
||||
}
|
||||
}
|
||||
if (!forcedIdentifier) {
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
}
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
|
||||
tag = (function() {
|
||||
switch (id) {
|
||||
case '!':
|
||||
|
|
@ -127,7 +123,6 @@ define(function(require, exports, module) {
|
|||
return 'BOOL';
|
||||
case 'break':
|
||||
case 'continue':
|
||||
case 'debugger':
|
||||
return 'STATEMENT';
|
||||
default:
|
||||
return tag;
|
||||
|
|
@ -135,33 +130,43 @@ define(function(require, exports, module) {
|
|||
})();
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) {
|
||||
this.token(':', ':');
|
||||
}
|
||||
if (colon) this.token(':', ':');
|
||||
return input.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
var binaryLiteral, lexedLength, match, number, octalLiteral;
|
||||
if (!(match = NUMBER.exec(this.chunk))) return 0;
|
||||
number = match[0];
|
||||
if (/E/.test(number)) {
|
||||
this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'");
|
||||
} else if (/[BOX]/.test(number)) {
|
||||
this.error("radix prefix '" + number + "' must be lowercase");
|
||||
} else if (/^0[89]/.test(number)) {
|
||||
this.error("decimal literal '" + number + "' must not be prefixed with '0'");
|
||||
} else if (/^0[0-7]/.test(number)) {
|
||||
this.error("octal literal '" + number + "' must be prefixed with '0o'");
|
||||
}
|
||||
lexedLength = number.length;
|
||||
if (octalLiteral = /0o([0-7]+)/.exec(number)) {
|
||||
number = (parseInt(octalLiteral[1], 8)).toString();
|
||||
}
|
||||
if (binaryLiteral = /0b([01]+)/.exec(number)) {
|
||||
number = (parseInt(binaryLiteral[1], 2)).toString();
|
||||
}
|
||||
this.token('NUMBER', number);
|
||||
return number.length;
|
||||
return lexedLength;
|
||||
};
|
||||
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var match, string;
|
||||
var match, octalEsc, string;
|
||||
switch (this.chunk.charAt(0)) {
|
||||
case "'":
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
|
||||
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
||||
break;
|
||||
case '"':
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) return 0;
|
||||
if (0 < string.indexOf('#{', 1)) {
|
||||
this.interpolateString(string.slice(1, -1));
|
||||
} else {
|
||||
|
|
@ -171,14 +176,16 @@ define(function(require, exports, module) {
|
|||
default:
|
||||
return 0;
|
||||
}
|
||||
if (octalEsc = /^(?:\\.|[^\\])*\\[0-7]/.test(string)) {
|
||||
this.error("octal escape sequences " + string + " are not allowed");
|
||||
}
|
||||
this.line += count(string, '\n');
|
||||
return string.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heredocToken = function() {
|
||||
var doc, heredoc, match, quote;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = HEREDOC.exec(this.chunk))) return 0;
|
||||
heredoc = match[0];
|
||||
quote = heredoc.charAt(0);
|
||||
doc = this.sanitizeHeredoc(match[2], {
|
||||
|
|
@ -195,22 +202,21 @@ define(function(require, exports, module) {
|
|||
this.line += count(heredoc, '\n');
|
||||
return heredoc.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var comment, here, match;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = this.chunk.match(COMMENT))) return 0;
|
||||
comment = match[0], here = match[1];
|
||||
if (here) {
|
||||
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
|
||||
herecomment: true,
|
||||
indent: Array(this.indent + 1).join(' ')
|
||||
}));
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
this.line += count(comment, '\n');
|
||||
return comment.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.jsToken = function() {
|
||||
var match, script;
|
||||
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
|
||||
|
|
@ -219,31 +225,37 @@ define(function(require, exports, module) {
|
|||
this.token('JS', (script = match[0]).slice(1, -1));
|
||||
return script.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var match, prev, regex, _ref2;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return 0;
|
||||
}
|
||||
var flags, length, match, prev, regex, _ref2, _ref3;
|
||||
if (this.chunk.charAt(0) !== '/') return 0;
|
||||
if (match = HEREGEX.exec(this.chunk)) {
|
||||
this.line += count(match[0], '\n');
|
||||
return this.heregexToken(match);
|
||||
length = this.heregexToken(match);
|
||||
this.line += count(match[0], '\n');
|
||||
return length;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return 0;
|
||||
if (!(match = REGEX.exec(this.chunk))) return 0;
|
||||
_ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2];
|
||||
if (regex.slice(0, 2) === '/*') {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
regex = match[0];
|
||||
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
|
||||
return regex.length;
|
||||
if (regex === '//') regex = '/(?:)/';
|
||||
this.token('REGEX', "" + regex + flags);
|
||||
return match.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
if (re.match(/^\*/)) {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
|
||||
return heregex.length;
|
||||
}
|
||||
|
|
@ -258,9 +270,7 @@ define(function(require, exports, module) {
|
|||
if (tag === 'TOKENS') {
|
||||
tokens.push.apply(tokens, value);
|
||||
} else {
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
|
||||
continue;
|
||||
}
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
|
||||
value = value.replace(/\\/g, '\\\\');
|
||||
tokens.push(['STRING', this.makeString(value, '"', true)]);
|
||||
}
|
||||
|
|
@ -271,19 +281,17 @@ define(function(require, exports, module) {
|
|||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_ref5 = this.tokens).push.apply(_ref5, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
this.token(')', ')');
|
||||
return heregex.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, match, noNewlines, prev, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
|
||||
indent = match[0];
|
||||
this.line += count(indent, '\n');
|
||||
this.seenFor = false;
|
||||
prev = last(this.tokens, 1);
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
noNewlines = this.unfinished();
|
||||
|
|
@ -304,6 +312,7 @@ define(function(require, exports, module) {
|
|||
diff = size - this.indent + this.outdebt;
|
||||
this.token('INDENT', diff);
|
||||
this.indents.push(diff);
|
||||
this.ends.push('OUTDENT');
|
||||
this.outdebt = this.indebt = 0;
|
||||
} else {
|
||||
this.indebt = 0;
|
||||
|
|
@ -312,7 +321,8 @@ define(function(require, exports, module) {
|
|||
this.indent = size;
|
||||
return indent.length;
|
||||
};
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
|
||||
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
|
||||
var dent, len;
|
||||
while (moveOut > 0) {
|
||||
len = this.indents.length - 1;
|
||||
|
|
@ -328,51 +338,52 @@ define(function(require, exports, module) {
|
|||
dent = this.indents.pop() - this.outdebt;
|
||||
moveOut -= dent;
|
||||
this.outdebt = 0;
|
||||
this.pair('OUTDENT');
|
||||
this.token('OUTDENT', dent);
|
||||
}
|
||||
}
|
||||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
if (dent) this.outdebt -= moveOut;
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.whitespaceToken = function() {
|
||||
var match, nline, prev;
|
||||
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
|
||||
return 0;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev) {
|
||||
prev[match ? 'spaced' : 'newLine'] = true;
|
||||
}
|
||||
if (prev) prev[match ? 'spaced' : 'newLine'] = true;
|
||||
if (match) {
|
||||
return match[0].length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Lexer.prototype.newlineToken = function() {
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') {
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') this.tokens.pop();
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
value = match[0];
|
||||
if (CODE.test(value)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
if (CODE.test(value)) this.tagParameters();
|
||||
} else {
|
||||
value = this.chunk.charAt(0);
|
||||
}
|
||||
|
|
@ -380,7 +391,7 @@ define(function(require, exports, module) {
|
|||
prev = last(this.tokens);
|
||||
if (value === '=' && prev) {
|
||||
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
|
||||
this.assignmentError();
|
||||
this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
|
||||
}
|
||||
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
|
|
@ -389,6 +400,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
}
|
||||
if (value === ';') {
|
||||
this.seenFor = false;
|
||||
tag = 'TERMINATOR';
|
||||
} else if (__indexOf.call(MATH, value) >= 0) {
|
||||
tag = 'MATH';
|
||||
|
|
@ -404,34 +416,39 @@ define(function(require, exports, module) {
|
|||
tag = 'LOGIC';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
prev[0] = 'INDEX_SOAK';
|
||||
break;
|
||||
case '::':
|
||||
prev[0] = 'INDEX_PROTO';
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (value) {
|
||||
case '(':
|
||||
case '{':
|
||||
case '[':
|
||||
this.ends.push(INVERSES[value]);
|
||||
break;
|
||||
case ')':
|
||||
case '}':
|
||||
case ']':
|
||||
this.pair(value);
|
||||
}
|
||||
this.token(tag, value);
|
||||
return value.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var attempt, herecomment, indent, match, _ref2;
|
||||
indent = options.indent, herecomment = options.herecomment;
|
||||
if (herecomment) {
|
||||
if (HEREDOC_ILLEGAL.test(doc)) {
|
||||
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) {
|
||||
return doc;
|
||||
this.error("block comment cannot contain \"*/\", starting");
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) return doc;
|
||||
} else {
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
|
|
@ -440,19 +457,14 @@ define(function(require, exports, module) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (indent) {
|
||||
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
}
|
||||
if (!herecomment) {
|
||||
doc = doc.replace(/^\n/, '');
|
||||
}
|
||||
if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
if (!herecomment) doc = doc.replace(/^\n/, '');
|
||||
return doc;
|
||||
};
|
||||
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var i, stack, tok, tokens;
|
||||
if (this.tag() !== ')') {
|
||||
return this;
|
||||
}
|
||||
if (this.tag() !== ')') return this;
|
||||
stack = [];
|
||||
tokens = this.tokens;
|
||||
i = tokens.length;
|
||||
|
|
@ -469,38 +481,41 @@ define(function(require, exports, module) {
|
|||
} else if (tok[0] === '(') {
|
||||
tok[0] = 'PARAM_START';
|
||||
return this;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.closeIndentation = function() {
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||
};
|
||||
|
||||
Lexer.prototype.balancedString = function(str, end) {
|
||||
var i, letter, prev, stack, _ref2;
|
||||
var continueCount, i, letter, match, prev, stack, _i, _ref2;
|
||||
continueCount = 0;
|
||||
stack = [end];
|
||||
for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
|
||||
for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {
|
||||
if (continueCount) {
|
||||
--continueCount;
|
||||
continue;
|
||||
}
|
||||
switch (letter = str.charAt(i)) {
|
||||
case '\\':
|
||||
i++;
|
||||
++continueCount;
|
||||
continue;
|
||||
case end:
|
||||
stack.pop();
|
||||
if (!stack.length) {
|
||||
return str.slice(0, i + 1);
|
||||
}
|
||||
if (!stack.length) return str.slice(0, i + 1 || 9e9);
|
||||
end = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
if (end === '}' && (letter === '"' || letter === "'")) {
|
||||
stack.push(end = letter);
|
||||
} else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
|
||||
continueCount += match[0].length - 1;
|
||||
} else if (end === '}' && letter === '{') {
|
||||
stack.push(end = '}');
|
||||
} else if (end === '"' && prev === '#' && letter === '{') {
|
||||
|
|
@ -508,13 +523,12 @@ define(function(require, exports, module) {
|
|||
}
|
||||
prev = letter;
|
||||
}
|
||||
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
|
||||
return this.error("missing " + (stack.pop()) + ", starting");
|
||||
};
|
||||
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) options = {};
|
||||
heredoc = options.heredoc, regex = options.regex;
|
||||
tokens = [];
|
||||
pi = 0;
|
||||
|
|
@ -527,9 +541,7 @@ define(function(require, exports, module) {
|
|||
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
|
||||
continue;
|
||||
}
|
||||
if (pi < i) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
}
|
||||
if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
inner = expr.slice(1, -1);
|
||||
if (inner.length) {
|
||||
nested = new Lexer().tokenize(inner, {
|
||||
|
|
@ -542,8 +554,8 @@ define(function(require, exports, module) {
|
|||
}
|
||||
if (len = nested.length) {
|
||||
if (len > 1) {
|
||||
nested.unshift(['(', '(']);
|
||||
nested.push([')', ')']);
|
||||
nested.unshift(['(', '(', this.line]);
|
||||
nested.push([')', ')', this.line]);
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
}
|
||||
|
|
@ -551,59 +563,60 @@ define(function(require, exports, module) {
|
|||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if ((i > pi && pi < str.length)) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
}
|
||||
if (regex) {
|
||||
return tokens;
|
||||
}
|
||||
if (!tokens.length) {
|
||||
return this.token('STRING', '""');
|
||||
}
|
||||
if (tokens[0][0] !== 'NEOSTRING') {
|
||||
tokens.unshift(['', '']);
|
||||
}
|
||||
if (interpolated = tokens.length > 1) {
|
||||
this.token('(', '(');
|
||||
}
|
||||
for (i = 0, _len = tokens.length; i < _len; i++) {
|
||||
if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
if (regex) return tokens;
|
||||
if (!tokens.length) return this.token('STRING', '""');
|
||||
if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
|
||||
if (interpolated = tokens.length > 1) this.token('(', '(');
|
||||
for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) {
|
||||
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
|
||||
if (i) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
if (i) this.token('+', '+');
|
||||
if (tag === 'TOKENS') {
|
||||
(_ref4 = this.tokens).push.apply(_ref4, value);
|
||||
} else {
|
||||
this.token('STRING', this.makeString(value, '"', heredoc));
|
||||
}
|
||||
}
|
||||
if (interpolated) {
|
||||
this.token(')', ')');
|
||||
}
|
||||
if (interpolated) this.token(')', ')');
|
||||
return tokens;
|
||||
};
|
||||
|
||||
Lexer.prototype.pair = function(tag) {
|
||||
var size, wanted;
|
||||
if (tag !== (wanted = last(this.ends))) {
|
||||
if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
|
||||
this.indent -= size = last(this.indents);
|
||||
this.outdentToken(size, true);
|
||||
return this.pair(tag);
|
||||
}
|
||||
return this.ends.pop();
|
||||
};
|
||||
|
||||
Lexer.prototype.token = function(tag, value) {
|
||||
return this.tokens.push([tag, value, this.line]);
|
||||
};
|
||||
|
||||
Lexer.prototype.tag = function(index, tag) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
|
||||
};
|
||||
|
||||
Lexer.prototype.value = function(index, val) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
|
||||
};
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var prev, value;
|
||||
return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
|
||||
var _ref2;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
|
||||
};
|
||||
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
return str.replace(MULTILINER, heredoc ? '\\n' : '');
|
||||
};
|
||||
|
||||
Lexer.prototype.makeString = function(body, quote, heredoc) {
|
||||
if (!body) {
|
||||
return quote + quote;
|
||||
}
|
||||
if (!body) return quote + quote;
|
||||
body = body.replace(/\\([\s\S])/g, function(match, contents) {
|
||||
if (contents === '\n' || contents === quote) {
|
||||
return contents;
|
||||
|
|
@ -614,10 +627,19 @@ define(function(require, exports, module) {
|
|||
body = body.replace(RegExp("" + quote, "g"), '\\$&');
|
||||
return quote + this.escapeLines(body, heredoc) + quote;
|
||||
};
|
||||
|
||||
Lexer.prototype.error = function(message) {
|
||||
throw SyntaxError("" + message + " on line " + (this.line + 1));
|
||||
};
|
||||
|
||||
return Lexer;
|
||||
|
||||
})();
|
||||
|
||||
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
|
||||
|
||||
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
|
||||
|
||||
COFFEE_ALIAS_MAP = {
|
||||
and: '&&',
|
||||
or: '||',
|
||||
|
|
@ -629,6 +651,7 @@ define(function(require, exports, module) {
|
|||
on: 'true',
|
||||
off: 'false'
|
||||
};
|
||||
|
||||
COFFEE_ALIASES = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
|
|
@ -637,41 +660,80 @@ define(function(require, exports, module) {
|
|||
}
|
||||
return _results;
|
||||
})();
|
||||
|
||||
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
|
||||
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield'];
|
||||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval'];
|
||||
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED;
|
||||
|
||||
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
|
||||
NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
|
||||
|
||||
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
WHITESPACE = /^[^\n\S]+/;
|
||||
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
|
||||
|
||||
CODE = /^[-=]>/;
|
||||
|
||||
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
|
||||
|
||||
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
|
||||
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
|
||||
REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
|
||||
|
||||
REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/;
|
||||
|
||||
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
|
||||
|
||||
HEREGEX_OMIT = /\s+(?:#.*)?/g;
|
||||
|
||||
MULTILINER = /\n/g;
|
||||
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)/g;
|
||||
|
||||
HEREDOC_ILLEGAL = /\*\//;
|
||||
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
|
||||
|
||||
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
|
||||
|
||||
TRAILING_SPACES = /\s+$/;
|
||||
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
|
||||
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
|
||||
|
||||
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
|
||||
|
||||
LOGIC = ['&&', '||', '&', '|', '^'];
|
||||
|
||||
SHIFT = ['<<', '>>', '>>>'];
|
||||
|
||||
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
|
||||
|
||||
MATH = ['*', '/', '%'];
|
||||
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
|
||||
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
|
||||
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
|
||||
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
|
|
@ -24,16 +24,18 @@
|
|||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
}, __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.2.1-pre
|
||||
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__slice = [].slice;
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
|
||||
Rewriter.name = 'Rewriter';
|
||||
|
||||
function Rewriter() {}
|
||||
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.removeLeadingNewlines();
|
||||
|
|
@ -44,10 +46,9 @@ define(function(require, exports, module) {
|
|||
this.tagPostfixConditionals();
|
||||
this.addImplicitBraces();
|
||||
this.addImplicitParentheses();
|
||||
this.ensureBalance(BALANCED_PAIRS);
|
||||
this.rewriteClosingParens();
|
||||
return this.tokens;
|
||||
};
|
||||
|
||||
Rewriter.prototype.scanTokens = function(block) {
|
||||
var i, token, tokens;
|
||||
tokens = this.tokens;
|
||||
|
|
@ -57,39 +58,36 @@ define(function(require, exports, module) {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref2;
|
||||
var levels, token, tokens, _ref, _ref1;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (!token || levels < 0) return action.call(this, token, i - 1);
|
||||
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
|
||||
} else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
var i, tag, _i, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
tag = _ref[i][0];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
if (tag !== 'TERMINATOR') break;
|
||||
}
|
||||
if (i) return this.tokens.splice(0, i);
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var _ref;
|
||||
|
|
@ -100,6 +98,7 @@ define(function(require, exports, module) {
|
|||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
|
|
@ -110,12 +109,11 @@ define(function(require, exports, module) {
|
|||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
|
|
@ -126,34 +124,33 @@ define(function(require, exports, module) {
|
|||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var action, condition, stack, start, startIndent;
|
||||
var action, condition, sameLine, stack, start, startIndent, startsLine;
|
||||
stack = [];
|
||||
start = null;
|
||||
startsLine = null;
|
||||
sameLine = true;
|
||||
startIndent = 0;
|
||||
condition = function(token, i) {
|
||||
var one, tag, three, two, _ref, _ref2;
|
||||
_ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
|
||||
return false;
|
||||
}
|
||||
var one, tag, three, two, _ref, _ref1;
|
||||
_ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
|
||||
tag = token[0];
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) sameLine = false;
|
||||
return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine)) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var tok;
|
||||
tok = ['}', '}', token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('}', '}', token[2]);
|
||||
return this.tokens.splice(i, 0, tok);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var ago, idx, tag, tok, value, _ref, _ref2;
|
||||
var ago, idx, prevTag, tag, tok, value, _ref, _ref1;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
|
|
@ -162,80 +159,82 @@ define(function(require, exports, module) {
|
|||
start = stack.pop();
|
||||
return 1;
|
||||
}
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
sameLine = true;
|
||||
stack.push(['{']);
|
||||
idx = ago === '@' ? i - 2 : i - 1;
|
||||
while (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
prevTag = this.tag(idx - 1);
|
||||
startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
|
||||
value = new String('{');
|
||||
value.generated = true;
|
||||
tok = ['{', value, token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('{', value, token[2]);
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var action, noCall;
|
||||
noCall = false;
|
||||
var action, condition, noCall, seenControl, seenSingle;
|
||||
noCall = seenSingle = seenControl = false;
|
||||
condition = function(token, i) {
|
||||
var post, tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) return true;
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2]));
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
var callObject, current, next, prev, tag, _ref, _ref1, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF') {
|
||||
if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {
|
||||
noCall = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
_ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);
|
||||
seenSingle = false;
|
||||
seenControl = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = false;
|
||||
}
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (token.fromThen) {
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
|
||||
if (prev && !prev.spaced && tag === '?') token.call = true;
|
||||
if (token.fromThen) return 1;
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
var post, _ref4;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
|
||||
var tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
|
|
@ -251,139 +250,93 @@ define(function(require, exports, module) {
|
|||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
indent.generated = outdent.generated = true;
|
||||
_ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];
|
||||
if (starter === 'THEN') indent.fromThen = true;
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
var _ref3;
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
if (tag === 'THEN') tokens.splice(i, 1);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
var condition;
|
||||
var action, condition, original;
|
||||
original = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var original;
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
if (token[0] !== 'IF') return 1;
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, function(token, i) {
|
||||
if (token[0] !== 'INDENT') {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
});
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.ensureBalance = function(pairs) {
|
||||
var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
|
||||
levels = {};
|
||||
openLine = {};
|
||||
_ref = this.tokens;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
token = _ref[_i];
|
||||
tag = token[0];
|
||||
for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
|
||||
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
|
||||
levels[open] |= 0;
|
||||
if (tag === open) {
|
||||
if (levels[open]++ === 0) {
|
||||
openLine[open] = token[2];
|
||||
}
|
||||
} else if (tag === close && --levels[open] < 0) {
|
||||
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (open in levels) {
|
||||
level = levels[open];
|
||||
if (level > 0) {
|
||||
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
Rewriter.prototype.indentation = function(token, implicit) {
|
||||
var indent, outdent;
|
||||
if (implicit == null) implicit = false;
|
||||
indent = ['INDENT', 2, token[2]];
|
||||
outdent = ['OUTDENT', 2, token[2]];
|
||||
if (implicit) indent.generated = outdent.generated = true;
|
||||
return [indent, outdent];
|
||||
};
|
||||
Rewriter.prototype.rewriteClosingParens = function() {
|
||||
var debt, key, stack;
|
||||
stack = [];
|
||||
debt = {};
|
||||
for (key in INVERSES) {
|
||||
debt[key] = 0;
|
||||
}
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var inv, match, mtag, oppos, tag, val, _ref;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push(token);
|
||||
return 1;
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (debt[inv = INVERSES[tag]] > 0) {
|
||||
debt[inv] -= 1;
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
match = stack.pop();
|
||||
mtag = match[0];
|
||||
oppos = INVERSES[mtag];
|
||||
if (tag === oppos) {
|
||||
return 1;
|
||||
}
|
||||
debt[mtag] += 1;
|
||||
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
|
||||
if (this.tag(i + 2) === mtag) {
|
||||
tokens.splice(i + 3, 0, val);
|
||||
stack.push(match);
|
||||
} else {
|
||||
tokens.splice(i, 0, val);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
|
||||
Rewriter.prototype.generate = function(tag, value, line) {
|
||||
var tok;
|
||||
tok = [tag, value, line];
|
||||
tok.generated = true;
|
||||
return tok;
|
||||
};
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
var _ref;
|
||||
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
|
||||
};
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
|
||||
INVERSES = {};
|
||||
|
||||
exports.INVERSES = INVERSES = {};
|
||||
|
||||
EXPRESSION_START = [];
|
||||
|
||||
EXPRESSION_END = [];
|
||||
|
||||
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
|
||||
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
|
||||
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Jeremy Ashkenas
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
|
|
@ -24,10 +24,18 @@
|
|||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
// Generated by CoffeeScript 1.2.1-pre
|
||||
|
||||
var Scope, extend, last, _ref;
|
||||
|
||||
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
|
||||
|
||||
exports.Scope = Scope = (function() {
|
||||
|
||||
Scope.name = 'Scope';
|
||||
|
||||
Scope.root = null;
|
||||
|
||||
function Scope(parent, expressions, method) {
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
|
|
@ -39,17 +47,13 @@ define(function(require, exports, module) {
|
|||
}
|
||||
];
|
||||
this.positions = {};
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
}
|
||||
if (!this.parent) Scope.root = this;
|
||||
}
|
||||
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
var pos;
|
||||
if (this.shared && !immediate) {
|
||||
return this.parent.add(name, type, immediate);
|
||||
}
|
||||
if (typeof (pos = this.positions[name]) === 'number') {
|
||||
return this.variables[pos].type = type;
|
||||
if (this.shared && !immediate) return this.parent.add(name, type, immediate);
|
||||
if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
|
||||
return this.variables[this.positions[name]].type = type;
|
||||
} else {
|
||||
return this.positions[name] = this.variables.push({
|
||||
name: name,
|
||||
|
|
@ -57,89 +61,94 @@ define(function(require, exports, module) {
|
|||
}) - 1;
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) {
|
||||
return true;
|
||||
}
|
||||
if (this.check(name, options)) return true;
|
||||
this.add(name, 'var');
|
||||
return false;
|
||||
};
|
||||
|
||||
Scope.prototype.parameter = function(name) {
|
||||
if (this.shared && this.parent.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
if (this.shared && this.parent.check(name, true)) return;
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
|
||||
Scope.prototype.check = function(name, immediate) {
|
||||
var found, _ref2;
|
||||
var found, _ref1;
|
||||
found = !!this.type(name);
|
||||
if (found || immediate) {
|
||||
return found;
|
||||
}
|
||||
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
|
||||
if (found || immediate) return found;
|
||||
return !!((_ref1 = this.parent) != null ? _ref1.check(name) : void 0);
|
||||
};
|
||||
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index : '');
|
||||
return '_' + name + (index > 1 ? index - 1 : '');
|
||||
} else {
|
||||
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.type = function(name) {
|
||||
var v, _i, _len, _ref2;
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.name === name) {
|
||||
return v.type;
|
||||
}
|
||||
var v, _i, _len, _ref1;
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.name === name) return v.type;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
|
||||
Scope.prototype.freeVariable = function(name, reserve) {
|
||||
var index, temp;
|
||||
if (reserve == null) reserve = true;
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(type, index)))) {
|
||||
while (this.check((temp = this.temporary(name, index)))) {
|
||||
index++;
|
||||
}
|
||||
this.add(temp, 'var', true);
|
||||
if (reserve) this.add(temp, 'var', true);
|
||||
return temp;
|
||||
};
|
||||
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
}, true);
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
|
||||
Scope.prototype.hasDeclarations = function() {
|
||||
return !!this.declaredVariables().length;
|
||||
};
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref2;
|
||||
var realVars, tempVars, v, _i, _len, _ref1;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
}
|
||||
}
|
||||
return realVars.sort().concat(tempVars.sort());
|
||||
};
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref2, _results;
|
||||
_ref2 = this.variables;
|
||||
var v, _i, _len, _ref1, _results;
|
||||
_ref1 = this.variables;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.type.assigned) {
|
||||
_results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
return Scope;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -105,11 +105,17 @@ var CssHighlightRules = function() {
|
|||
"purple|red|silver|teal|white|yellow").split("|")
|
||||
);
|
||||
|
||||
var fonts = lang.arrayToMap(
|
||||
("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
|
||||
"symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
|
||||
"serif|monospace").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
|
||||
|
||||
|
||||
var base_ruleset = [
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
|
|
@ -123,8 +129,11 @@ var CssHighlightRules = function() {
|
|||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "constant.numeric",
|
||||
regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
|
||||
token : ["constant.numeric", "keyword"],
|
||||
regex : "(" + numRe + ")(em|ex|px|ch|cm|mm|in|pt|pc|deg|rad|dpi|grad|ms|s|hz|khz|%)"
|
||||
}, {
|
||||
token : ["constant.numeric"],
|
||||
regex : "([0-9]+)"
|
||||
}, {
|
||||
token : "constant.numeric", // hex6 color
|
||||
regex : "#[a-f0-9]{6}"
|
||||
|
|
@ -145,12 +154,15 @@ var CssHighlightRules = function() {
|
|||
else if (colors.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.constant.color";
|
||||
}
|
||||
else if (fonts.hasOwnProperty(value.toLowerCase())) {
|
||||
return "support.constant.fonts";
|
||||
}
|
||||
else {
|
||||
return "text";
|
||||
}
|
||||
},
|
||||
regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var ruleset = lang.copyArray(base_ruleset);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ module.exports = {
|
|||
var line = "-12px";
|
||||
var tokens = this.tokenizer.getLineTokens(line, "ruleset").tokens;
|
||||
|
||||
assert.equal(1, tokens.length);
|
||||
assert.equal(2, tokens.length);
|
||||
assert.equal("constant.numeric", tokens[0].type);
|
||||
},
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ module.exports = {
|
|||
assert.equal("keyword.operator", tokens[4].type);
|
||||
assert.equal("string", tokens[5].type);
|
||||
assert.equal("meta.tag", tokens[6].type);
|
||||
assert.equal("keyword.definition", tokens[7].type);
|
||||
assert.equal("storage.type", tokens[7].type);
|
||||
assert.equal("meta.tag", tokens[8].type);
|
||||
assert.equal("meta.tag.script", tokens[9].type);
|
||||
assert.equal("meta.tag", tokens[10].type);
|
||||
|
|
@ -93,12 +93,20 @@ var JavaScriptHighlightRules = function() {
|
|||
);
|
||||
|
||||
// TODO: Unicode escape sequences
|
||||
var identifierRe = "[" + unicode.packages.L + "\\$_]["
|
||||
var identifierRe = "[" + unicode.packages.L + "\\$_]["
|
||||
+ unicode.packages.L
|
||||
+ unicode.packages.Mn + unicode.packages.Mc
|
||||
+ unicode.packages.Nd
|
||||
+ unicode.packages.Pc + "\\$_]*\\b";
|
||||
|
||||
|
||||
var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
|
||||
"u[0-9a-fA-F]{4}|" + // unicode
|
||||
"[0-2][0-7]{0,2}|" + // oct
|
||||
"3[0-6][0-7]?|" + // oct
|
||||
"37[0-7]?|" + // oct
|
||||
"[4-7][0-7]?|" + //oct
|
||||
".)";
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
|
|
@ -106,46 +114,139 @@ var JavaScriptHighlightRules = function() {
|
|||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "\\/\\/.*$"
|
||||
regex : /\/\/.*$/
|
||||
},
|
||||
new DocCommentHighlightRules().getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment
|
||||
merge : true,
|
||||
regex : "\\/\\*",
|
||||
regex : /\/\*/,
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
token : "string",
|
||||
regex : "'",
|
||||
next : "qstring"
|
||||
}, {
|
||||
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 : "string",
|
||||
regex : '"',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||
regex : /0[xX][0-9a-fA-F]+\b/
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : ["keyword.definition", "text", "entity.name.function"],
|
||||
regex : "(function)(\\s+)(" + identifierRe + ")"
|
||||
regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
|
||||
}, { // match stuff like: Sound.prototype.play = function() { }
|
||||
token : [
|
||||
"storage.type",
|
||||
"punctuation.operator",
|
||||
"support.function",
|
||||
"punctuation.operator",
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"keyword.operator",
|
||||
"text",
|
||||
"storage.type",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
|
||||
}, { // match stuff like: Sound.prototype.play = myfunc
|
||||
token : [
|
||||
"storage.type",
|
||||
"punctuation.operator",
|
||||
"support.function",
|
||||
"punctuation.operator",
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"keyword.operator",
|
||||
"text"
|
||||
],
|
||||
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
|
||||
}, { // match stuff like: Sound.play = function() { }
|
||||
token : [
|
||||
"storage.type",
|
||||
"punctuation.operator",
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"keyword.operator",
|
||||
"text",
|
||||
"storage.type",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
|
||||
}, { // match stuff like: play = function() { }
|
||||
token : [
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"keyword.operator",
|
||||
"text",
|
||||
"storage.type",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
|
||||
}, { // match regular function like: function myFunc(arg) { }
|
||||
token : [
|
||||
"storage.type",
|
||||
"text",
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
|
||||
}, { // match stuff like: foobar: function() { }
|
||||
token : [
|
||||
"entity.name.function",
|
||||
"text",
|
||||
"punctuation.operator",
|
||||
"text",
|
||||
"storage.type",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
|
||||
}, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
|
||||
token : [
|
||||
"text",
|
||||
"text",
|
||||
"storage.type",
|
||||
"text",
|
||||
"paren.lparen",
|
||||
"variable.parameter",
|
||||
"paren.rparen"
|
||||
],
|
||||
regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false)\\b"
|
||||
regex : /(?:true|false)\b/
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "(?:" + kwBeforeRe + ")\\b",
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token : "support.function",
|
||||
regex : /\b(?:s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
|
||||
}, {
|
||||
token : "support.function.dom",
|
||||
regex : /\b(?:s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
|
||||
}, {
|
||||
token : ["punctuation.operator", "support.constant"],
|
||||
regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image))\b)/
|
||||
}, {
|
||||
token : ["storage.type", "punctuation.operator", "support.function.firebug"],
|
||||
regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (globals.hasOwnProperty(value))
|
||||
|
|
@ -153,7 +254,7 @@ var JavaScriptHighlightRules = function() {
|
|||
else if (deprecated.hasOwnProperty(value))
|
||||
return "invalid.deprecated";
|
||||
else if (definitions.hasOwnProperty(value))
|
||||
return "keyword.definition";
|
||||
return "storage.type";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (buildinConstants.hasOwnProperty(value))
|
||||
|
|
@ -168,29 +269,29 @@ var JavaScriptHighlightRules = function() {
|
|||
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 : "punctuation.operator",
|
||||
regex : "\\?|\\:|\\,|\\;|\\.",
|
||||
regex : /\?|\:|\,|\;|\./,
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "[[({]",
|
||||
regex : /[\[({]/,
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : "[\\])}]"
|
||||
regex : /[\])}]/
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\/=?",
|
||||
regex : /\/=?/,
|
||||
next : "regex_allowed"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: "^#!.*$"
|
||||
regex: /^#!.*$/
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
regex : /\s+/
|
||||
}
|
||||
],
|
||||
// regular expressions are only allowed after certain tokens. This
|
||||
|
|
@ -215,7 +316,7 @@ var JavaScriptHighlightRules = function() {
|
|||
}, {
|
||||
// immediately return to the start mode without matching
|
||||
// anything
|
||||
token: "empty",
|
||||
token: "empty",
|
||||
regex: "",
|
||||
next: "start"
|
||||
}
|
||||
|
|
@ -227,10 +328,10 @@ var JavaScriptHighlightRules = function() {
|
|||
next: "regex"
|
||||
}, {
|
||||
// flag
|
||||
token: "string.regexp",
|
||||
token: "string.regexp",
|
||||
regex: "/\\w*",
|
||||
next: "start",
|
||||
merge: true
|
||||
merge: true
|
||||
}, {
|
||||
token: "string.regexp",
|
||||
regex: "[^\\\\/\\[]+",
|
||||
|
|
@ -242,9 +343,9 @@ var JavaScriptHighlightRules = function() {
|
|||
next: "regex_character_class",
|
||||
merge: true
|
||||
}, {
|
||||
token: "empty",
|
||||
token: "empty",
|
||||
regex: "",
|
||||
next: "start"
|
||||
next: "start"
|
||||
}
|
||||
],
|
||||
"regex_character_class": [
|
||||
|
|
@ -263,9 +364,9 @@ var JavaScriptHighlightRules = function() {
|
|||
next: "regex_character_class",
|
||||
merge: true
|
||||
}, {
|
||||
token: "empty",
|
||||
token: "empty",
|
||||
regex: "",
|
||||
next: "start"
|
||||
next: "start"
|
||||
}
|
||||
],
|
||||
"comment_regex_allowed" : [
|
||||
|
|
@ -294,28 +395,32 @@ var JavaScriptHighlightRules = function() {
|
|||
],
|
||||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
next : "start"
|
||||
token : "constant.language.escape",
|
||||
regex : escapedRe
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
regex : '[^"\\\\]+'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '"',
|
||||
next : "start"
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
next : "start"
|
||||
token : "constant.language.escape",
|
||||
regex : escapedRe
|
||||
}, {
|
||||
token : "string",
|
||||
merge : true,
|
||||
regex : '.+'
|
||||
regex : "[^'\\\\]+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'",
|
||||
next : "start"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ new DocCommentHighlightRules().getEndRule("start") ]);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,9 +63,20 @@ module.exports = {
|
|||
assert.equal("text", tokens[1].type);
|
||||
assert.equal("keyword.operator", tokens[2].type);
|
||||
assert.equal("text", tokens[3].type);
|
||||
assert.equal("keyword.definition", tokens[4].type);
|
||||
assert.equal("storage.type", tokens[4].type);
|
||||
},
|
||||
|
||||
"test: tokenize 'standard' functions" : function() {
|
||||
var line = "string.charCodeAt(23); document.getElementById('test'); console.log('Here it is');";
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
assert.equal(27, tokens.length);
|
||||
assert.equal("support.function", tokens[2].type); // charCodeAt
|
||||
assert.equal("support.function.dom", tokens[10].type); // getElementById
|
||||
assert.equal("support.function.firebug", tokens[20].type); // log
|
||||
},
|
||||
|
||||
"test: tokenize doc comment" : function() {
|
||||
var line = "abc /** de */ fg";
|
||||
|
||||
|
|
@ -164,6 +175,20 @@ module.exports = {
|
|||
assert.equal("paren.lparen", tokens[0].type);
|
||||
assert.equal("text", tokens[1].type);
|
||||
assert.equal("comment", tokens[2].type);
|
||||
},
|
||||
|
||||
"test skipping escaped chars": function() {
|
||||
var line = "console.log('Meh\\nNeh');"
|
||||
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
assert.equal(11, tokens.length);
|
||||
assert.equal("constant.language.escape", tokens[6].type);
|
||||
|
||||
line = "console.log('\\u1232Feh');";
|
||||
tokens = this.tokenizer.getLineTokens(line, "start").tokens;
|
||||
|
||||
assert.equal(10, tokens.length);
|
||||
assert.equal("constant.language.escape", tokens[5].type);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -41,6 +41,7 @@ define(function(require, exports, module) {
|
|||
var oop = require("../lib/oop");
|
||||
var Mirror = require("../worker/mirror").Mirror;
|
||||
var lint = require("../worker/jshint").JSHINT;
|
||||
var parser = require("../narcissus/parser");
|
||||
|
||||
var JavaScriptWorker = exports.JavaScriptWorker = function(sender) {
|
||||
Mirror.call(this, sender);
|
||||
|
|
@ -56,7 +57,6 @@ oop.inherits(JavaScriptWorker, Mirror);
|
|||
value = value.replace(/^#!.*\n/, "\n");
|
||||
|
||||
// var start = new Date();
|
||||
var parser = require("../narcissus/jsparse");
|
||||
try {
|
||||
parser.parse(value);
|
||||
} catch(e) {
|
||||
|
|
|
|||
|
|
@ -59,19 +59,31 @@ module.exports = {
|
|||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
"test check for syntax error": function() {
|
||||
var worker = new JavaScriptWorker(this.sender);
|
||||
worker.setValue("Juhu Kinners");
|
||||
worker.deferredUpdate.call();
|
||||
|
||||
|
||||
var error = this.sender.events[0][1];
|
||||
assert.equal(error.text, "missing ; before statement");
|
||||
assert.equal(error.type, "error");
|
||||
assert.equal(error.row, 0);
|
||||
assert.equal(error.column, null);
|
||||
},
|
||||
|
||||
|
||||
"test invalid multi line string": function() {
|
||||
var worker = new JavaScriptWorker(this.sender);
|
||||
worker.setValue('"a\n\\nn"');
|
||||
worker.deferredUpdate.call();
|
||||
|
||||
var error = this.sender.events[0][1];
|
||||
assert.equal(error.text, "Unterminated string literal");
|
||||
assert.equal(error.type, "error");
|
||||
assert.equal(error.row, 0);
|
||||
assert.equal(error.column, null);
|
||||
},
|
||||
|
||||
"test check for narcissus bug": function() {
|
||||
var worker = new JavaScriptWorker(this.sender);
|
||||
worker.setValue("if('");
|
||||
|
|
|
|||
116
lib/ace/mode/liquid.js
Normal file
116
lib/ace/mode/liquid.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Ajax.org Code Editor (ACE).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ajax.org B.V.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var Tokenizer = require("../tokenizer").Tokenizer;
|
||||
var LiquidHighlightRules = require("./liquid_highlight_rules").LiquidHighlightRules;
|
||||
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("../range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new LiquidHighlightRules().getRules());
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
var re = /^(\s*)#/;
|
||||
|
||||
for (var i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdent) {
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
for (var i=startRow; i<= endRow; i++)
|
||||
{
|
||||
var line = doc.getLine(i);
|
||||
var m = line.match(re);
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
deleteRange.end.column = m[0].length;
|
||||
doc.replace(deleteRange, m[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
doc.indentRows(startRow, endRow, "#");
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
220
lib/ace/mode/liquid_highlight_rules.js
Normal file
220
lib/ace/mode/liquid_highlight_rules.js
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/* ***** 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules;
|
||||
var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
|
||||
var lang = require("../lib/lang");
|
||||
var xmlUtil = require("./xml_util");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var LiquidHighlightRules = function() {
|
||||
|
||||
// see: https://developer.mozilla.org/en/Liquid/Reference/Global_Objects
|
||||
var functions = lang.arrayToMap(
|
||||
// Standard Filters
|
||||
("date|capitalize|downcase|upcase|first|last|join|sort|map|size|escape|" +
|
||||
"escape_once|strip_html|strip_newlines|newline_to_br|replace|replace_first|" +
|
||||
"truncate|truncatewords|prepend|append|minus|plus|times|divided_by|split"
|
||||
).split("|")
|
||||
);
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
// Standard Tags
|
||||
("capture|endcapture|case|endcase|when|comment|endcomment|" +
|
||||
"cycle|for|endfor|in|reversed|if|endif|else|elsif|include|endinclude|unless|endunless|" +
|
||||
// Commonly used tags
|
||||
"style|text|image|widget|plugin|marker|endmarker|tablerow|endtablerow").split("|")
|
||||
);
|
||||
|
||||
var builtinVariables = lang.arrayToMap(
|
||||
['forloop']
|
||||
// ("forloop\\.(length|index|index0|rindex|rindex0|first|last)|limit|offset|range" +
|
||||
// "tablerowloop\\.(length|index|index0|rindex|rindex0|first|last|col|col0|"+
|
||||
// "col_first|col_last)").split("|")
|
||||
);
|
||||
|
||||
var definitions = lang.arrayToMap(("assign").split("|"));
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
start : [{
|
||||
token : "variable",
|
||||
regex : "{%",
|
||||
next : "liquid_start"
|
||||
}, {
|
||||
token : "variable",
|
||||
regex : "{{",
|
||||
next : "liquid_start"
|
||||
}, {
|
||||
token : "meta.tag",
|
||||
merge : true,
|
||||
regex : "<\\!\\[CDATA\\[",
|
||||
next : "cdata"
|
||||
}, {
|
||||
token : "xml_pe",
|
||||
regex : "<\\?.*?\\?>"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : "<\\!--",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "meta.tag",
|
||||
regex : "<(?=\\s*script\\b)",
|
||||
next : "script"
|
||||
}, {
|
||||
token : "meta.tag",
|
||||
regex : "<(?=\\s*style\\b)",
|
||||
next : "style"
|
||||
}, {
|
||||
token : "meta.tag", // opening tag
|
||||
regex : "<\\/?",
|
||||
next : "tag"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "[^<]+"
|
||||
} ],
|
||||
|
||||
cdata : [ {
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
} ],
|
||||
|
||||
comment : [ {
|
||||
token : "comment",
|
||||
regex : ".*?-->",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
} ] ,
|
||||
|
||||
liquid_start : [{
|
||||
token: "variable",
|
||||
regex: "}}",
|
||||
next: "start"
|
||||
}, {
|
||||
token: "variable",
|
||||
regex: "%}",
|
||||
next: "start"
|
||||
}, {
|
||||
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 (functions.hasOwnProperty(value))
|
||||
return "support.function";
|
||||
else if (keywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (builtinVariables.hasOwnProperty(value))
|
||||
return "variable.language";
|
||||
else if (definitions.hasOwnProperty(value))
|
||||
return "keyword.definition";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\/|\\*|\\-|\\+|=|!=|\\?\\:"
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : /[\[\({]/
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : /[\])}]/
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}]
|
||||
};
|
||||
|
||||
xmlUtil.tag(this.$rules, "tag", "start");
|
||||
xmlUtil.tag(this.$rules, "style", "css-start");
|
||||
xmlUtil.tag(this.$rules, "script", "js-start");
|
||||
|
||||
this.embedRules(JavaScriptHighlightRules, "js-", [{
|
||||
token: "comment",
|
||||
regex: "\\/\\/.*(?=<\\/script>)",
|
||||
next: "tag"
|
||||
}, {
|
||||
token: "meta.tag",
|
||||
regex: "<\\/(?=script)",
|
||||
next: "tag"
|
||||
}]);
|
||||
|
||||
this.embedRules(CssHighlightRules, "css-", [{
|
||||
token: "meta.tag",
|
||||
regex: "<\\/(?=style)",
|
||||
next: "tag"
|
||||
}]);
|
||||
};
|
||||
oop.inherits(LiquidHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.LiquidHighlightRules = LiquidHighlightRules;
|
||||
});
|
||||
91
lib/ace/mode/liquid_highlight_rules_test.js
Normal file
91
lib/ace/mode/liquid_highlight_rules_test.js
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Ajax.org Code Editor (ACE).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ajax.org B.V.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var LiquidMode = require("./liquid").Mode;
|
||||
var assert = require("../test/assertions");
|
||||
|
||||
module.exports = {
|
||||
|
||||
name: "Liquid Tokenizer",
|
||||
|
||||
setUp : function() {
|
||||
this.tokenizer = new LiquidMode().getTokenizer();
|
||||
},
|
||||
|
||||
"test: tokenize tags" : function() {
|
||||
var line = "for one in many";
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens(line, "liquid_start").tokens;
|
||||
|
||||
assert.equal(7, tokens.length);
|
||||
assert.equal("keyword", tokens[0].type);
|
||||
assert.equal("text", tokens[1].type);
|
||||
assert.equal("identifier", tokens[2].type);
|
||||
assert.equal("text", tokens[3].type);
|
||||
assert.equal("keyword", tokens[4].type);
|
||||
assert.equal("text", tokens[5].type);
|
||||
assert.equal("identifier", tokens[6].type);
|
||||
},
|
||||
|
||||
"test: tokenize parens" : function() {
|
||||
var line = "[{( )}]";
|
||||
|
||||
var tokens = this.tokenizer.getLineTokens(line, "liquid_start").tokens;
|
||||
|
||||
assert.equal(7, tokens.length);
|
||||
assert.equal("paren.lparen", tokens[0].type);
|
||||
assert.equal("paren.lparen", tokens[1].type);
|
||||
assert.equal("paren.lparen", tokens[2].type);
|
||||
assert.equal("text", tokens[3].type);
|
||||
assert.equal("paren.rparen", tokens[4].type);
|
||||
assert.equal("paren.rparen", tokens[5].type);
|
||||
assert.equal("paren.rparen", tokens[6].type);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec()
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ var MarkdownHighlightRules = function() {
|
|||
token : "empty_line",
|
||||
regex : '^$'
|
||||
}, { // code span `
|
||||
token : "support.function",
|
||||
token : ["support.function", "support.function", "support.function"],
|
||||
regex : "(`+)([^\\r]*?[^`])(\\1)"
|
||||
}, { // code block
|
||||
token : "support.function",
|
||||
|
|
@ -94,7 +94,7 @@ var MarkdownHighlightRules = function() {
|
|||
next : "blockquote"
|
||||
}, { // reference
|
||||
token : ["text", "constant", "text", "url", "string", "text"],
|
||||
regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?\\s*)$"
|
||||
regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$"
|
||||
}, { // link by reference
|
||||
token : ["text", "string", "text", "constant", "text"],
|
||||
regex : "(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"
|
||||
|
|
@ -120,10 +120,10 @@ var MarkdownHighlightRules = function() {
|
|||
regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",
|
||||
next : "listblock"
|
||||
}, { // strong ** __
|
||||
token : "string",
|
||||
token : ["string", "string", "string"],
|
||||
regex : "([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
|
||||
}, { // emphasis * _
|
||||
token : "string",
|
||||
token : ["string", "string", "string"],
|
||||
regex : "([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
|
||||
}, { //
|
||||
token : ["text", "url", "text"],
|
||||
|
|
|
|||
|
|
@ -952,14 +952,14 @@ var PhpHighlightRules = function() {
|
|||
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : '["].*\\\\$',
|
||||
regex : '["][\\s\\S]*',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // single line
|
||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||
}, {
|
||||
token : "string", // multi line string start
|
||||
regex : "['].*\\\\$",
|
||||
regex : "['][\\s\\S]+",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
|
|
@ -1041,21 +1041,21 @@ var PhpHighlightRules = function() {
|
|||
"qqstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
|
||||
regex : '"',
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
regex : '[^"]+'
|
||||
}
|
||||
],
|
||||
"qstring" : [
|
||||
{
|
||||
token : "string",
|
||||
regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
|
||||
regex : "'",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '.+'
|
||||
regex : "[^']+"
|
||||
}
|
||||
],
|
||||
"htmlcomment" : [
|
||||
|
|
@ -1094,7 +1094,7 @@ var PhpHighlightRules = function() {
|
|||
next : "htmltag"
|
||||
}, {
|
||||
token : "meta.tag",
|
||||
regex : ">",
|
||||
regex : ">"
|
||||
}, {
|
||||
token : 'text',
|
||||
regex : "(?:media|type|href)"
|
||||
|
|
@ -1104,7 +1104,7 @@ var PhpHighlightRules = function() {
|
|||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "\{",
|
||||
next : "cssdeclaration",
|
||||
next : "cssdeclaration"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "#[A-Za-z0-9\-\_\.]+"
|
||||
|
|
@ -1146,7 +1146,7 @@ var PhpHighlightRules = function() {
|
|||
regex : ";",
|
||||
next : "cssdeclaration"
|
||||
}
|
||||
],
|
||||
]
|
||||
};
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
|
|
|
|||
144
lib/ace/mode/sh.js
Normal file
144
lib/ace/mode/sh.js
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/* ***** 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):
|
||||
* Rich Healey <richo AT psych0tik DOT net>
|
||||
*
|
||||
* 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var Tokenizer = require("../tokenizer").Tokenizer;
|
||||
var ShHighlightRules = require("./sh_highlight_rules").ShHighlightRules;
|
||||
var Range = require("../range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.$tokenizer = new Tokenizer(new ShHighlightRules().getRules());
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
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;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[\:]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
var outdents = {
|
||||
"pass": 1,
|
||||
"return": 1,
|
||||
"raise": 1,
|
||||
"break": 1,
|
||||
"continue": 1
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
if (input !== "\r\n" && input !== "\r" && input !== "\n")
|
||||
return false;
|
||||
|
||||
var tokens = this.$tokenizer.getLineTokens(line.trim(), state).tokens;
|
||||
|
||||
if (!tokens)
|
||||
return false;
|
||||
|
||||
// ignore trailing comments
|
||||
do {
|
||||
var last = tokens.pop();
|
||||
} while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
|
||||
|
||||
if (!last)
|
||||
return false;
|
||||
|
||||
return (last.type == "keyword" && outdents[last.value]);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
// outdenting in sh is slightly different because it always applies
|
||||
// to the next line and only of a new line is inserted
|
||||
|
||||
row += 1;
|
||||
var indent = this.$getIndent(doc.getLine(row));
|
||||
var tab = doc.getTabString();
|
||||
if (indent.slice(-tab.length) == tab)
|
||||
doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
137
lib/ace/mode/sh_highlight_rules.js
Normal file
137
lib/ace/mode/sh_highlight_rules.js
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/* ***** 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):
|
||||
* Rich Healey <richo AT psych0tik DOT net>
|
||||
*
|
||||
* 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var lang = require("../lib/lang");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var ShHighlightRules = function() {
|
||||
|
||||
var reservedKeywords = lang.arrayToMap(
|
||||
('!|{|}|case|do|done|elif|else|'+
|
||||
'esac|fi|for|if|in|then|until|while|'+
|
||||
'&|;'
|
||||
).split('|')
|
||||
);
|
||||
|
||||
var languageConstructs = lang.arrayToMap(
|
||||
// TODO
|
||||
('echo|exit|eval|source|[|]|test|'+
|
||||
'true|false|read'
|
||||
).split('|')
|
||||
);
|
||||
|
||||
var integer = "(?:(?:[1-9]\\d*)|(?:0))";
|
||||
// var integer = "(?:" + decimalInteger + ")";
|
||||
|
||||
var fraction = "(?:\\.\\d+)";
|
||||
var intPart = "(?:\\d+)";
|
||||
var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
|
||||
var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + ")";
|
||||
var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
|
||||
var fileDescriptor = "(?:&" + intPart + ")";
|
||||
|
||||
var variableName = "[a-zA-Z][a-zA-Z0-9_]*";
|
||||
var variable = "(?:(?:\\$" + variableName + ")|(?:" + variableName + "=))";
|
||||
|
||||
var builtinVariable = "(?:\\$(?:SHLVL|\\$|\\!|\\?))";
|
||||
|
||||
var func = "(?:" + variableName + "\\s*\\(\\))";
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "string", // " string
|
||||
regex : '"(?:[^\\\\]|\\\\.)*?"'
|
||||
}, {
|
||||
token : "variable.language",
|
||||
regex : builtinVariable
|
||||
}, {
|
||||
token : "variable",
|
||||
regex : variable
|
||||
}, {
|
||||
token : "support.function",
|
||||
regex : func,
|
||||
}, {
|
||||
token : "support.function",
|
||||
regex : fileDescriptor
|
||||
}, {
|
||||
token : "string", // ' string
|
||||
regex : "'(?:[^\\\\]|\\\\.)*?'"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : floatNumber
|
||||
}, {
|
||||
token : "constant.numeric", // integer
|
||||
regex : integer + "\\b"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (reservedKeywords.hasOwnProperty(value))
|
||||
return "keyword";
|
||||
else if (languageConstructs.hasOwnProperty(value))
|
||||
return "constant.language";
|
||||
else if (value == "debugger")
|
||||
return "invalid.deprecated";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!="
|
||||
}, {
|
||||
token : "lparen.paren",
|
||||
regex : "[\\[\\(\\{]"
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : "[\\]\\)\\}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
} ]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(ShHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.ShHighlightRules = ShHighlightRules;
|
||||
});
|
||||
102
lib/ace/mode/xquery.js
Normal file
102
lib/ace/mode/xquery.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* eXide - web-based XQuery IDE
|
||||
*
|
||||
* Copyright (C) 2011 Wolfgang Meier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var Tokenizer = require("../tokenizer").Tokenizer;
|
||||
var XQueryHighlightRules = require("./xquery_highlight_rules").XQueryHighlightRules;
|
||||
var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour;
|
||||
var Range = require("../range").Range;
|
||||
|
||||
var Mode = function(parent) {
|
||||
this.$tokenizer = new Tokenizer(new XQueryHighlightRules().getRules());
|
||||
this.$behaviour = new XQueryBehaviour(parent);
|
||||
};
|
||||
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var match = line.match(/\s*(?:then|else|return|[{\(]|<\w+>)\s*$/);
|
||||
if (match)
|
||||
indent += tab;
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
if (! /^\s+$/.test(line))
|
||||
return false;
|
||||
|
||||
return /^\s*[\}\)]/.test(input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
var line = doc.getLine(row);
|
||||
var match = line.match(/^(\s*[\}\)])/);
|
||||
|
||||
if (!match) return 0;
|
||||
|
||||
var column = match[1].length;
|
||||
var openBracePos = doc.findMatchingBracket({row: row, column: column});
|
||||
|
||||
if (!openBracePos || openBracePos.row == row) return 0;
|
||||
|
||||
var indent = this.$getIndent(doc.getLine(openBracePos.row));
|
||||
doc.replace(new Range(row, 0, row, column-1), indent);
|
||||
};
|
||||
|
||||
this.$getIndent = function(line) {
|
||||
var match = line.match(/^(\s+)/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var i, line;
|
||||
var outdent = true;
|
||||
var re = /^\s*\(:(.*):\)/;
|
||||
|
||||
for (i=startRow; i<= endRow; i++) {
|
||||
if (!re.test(doc.getLine(i))) {
|
||||
outdent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var range = new Range(0, 0, 0, 0);
|
||||
for (i=startRow; i<= endRow; i++) {
|
||||
line = doc.getLine(i);
|
||||
range.start.row = i;
|
||||
range.end.row = i;
|
||||
range.end.column = line.length;
|
||||
|
||||
doc.replace(range, outdent ? line.match(re)[1] : "(:" + line + ":)");
|
||||
}
|
||||
};
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
145
lib/ace/mode/xquery_highlight_rules.js
Normal file
145
lib/ace/mode/xquery_highlight_rules.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* eXide - web-based XQuery IDE
|
||||
*
|
||||
* Copyright (C) 2011 Wolfgang Meier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var lang = require("../lib/lang");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var XQueryHighlightRules = function() {
|
||||
|
||||
var keywords = lang.arrayToMap(
|
||||
("return|for|let|where|order|by|declare|function|variable|xquery|version|option|namespace|import|module|when|encoding|" +
|
||||
"switch|default|try|catch|group|tumbling|sliding|window|start|end|at|only|" +
|
||||
"using|stemming|" +
|
||||
"while|" +
|
||||
"external|" +
|
||||
"if|then|else|as|and|or|typeswitch|case|ascending|descending|empty|in|count|updating|insert|delete|replace|value|node|attribute|text|element|into|of|with|contains").split("|")
|
||||
);
|
||||
|
||||
// regexp must not have capturing parentheses
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
start : [ {
|
||||
token : "text",
|
||||
regex : "<\\!\\[CDATA\\[",
|
||||
next : "cdata"
|
||||
}, {
|
||||
token : "xml_pe",
|
||||
regex : "<\\?.*?\\?>"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "<\\!--",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "\\(:",
|
||||
next : "comment"
|
||||
}, {
|
||||
token : "text", // opening tag
|
||||
regex : "<\\/?",
|
||||
next : "tag"
|
||||
}, {
|
||||
token : "constant", // number
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token : "variable", // variable
|
||||
regex : "\\$[a-zA-Z_][a-zA-Z0-9_\\-:]*\\b"
|
||||
}, {
|
||||
token: "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token: "string",
|
||||
regex : "'.*?'"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token: "support.function",
|
||||
regex: "\\w[\\w+_\\-:]+(?=\\()"
|
||||
}, {
|
||||
token : function(value) {
|
||||
if (keywords[value])
|
||||
return "keyword";
|
||||
else
|
||||
return "identifier";
|
||||
},
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token: "keyword.operator",
|
||||
regex: "\\*|=|<|>|\\-|\\+|and|or|eq|ne|lt|gt"
|
||||
}, {
|
||||
token: "lparen",
|
||||
regex: "[[({]"
|
||||
}, {
|
||||
token: "rparen",
|
||||
regex: "[\\])}]"
|
||||
} ],
|
||||
|
||||
tag : [ {
|
||||
token : "text",
|
||||
regex : ">",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "meta.tag",
|
||||
regex : "[-_a-zA-Z0-9:]+"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '".*?"'
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'.*?'"
|
||||
} ],
|
||||
|
||||
cdata : [ {
|
||||
token : "text",
|
||||
regex : "\\]\\]>",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "(?:[^\\]]|\\](?!\\]>))+"
|
||||
} ],
|
||||
|
||||
comment : [ {
|
||||
token : "comment",
|
||||
regex : ".*?-->",
|
||||
next : "start"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex : ".*:\\)",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : ".+"
|
||||
} ]
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(XQueryHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.XQueryHighlightRules = XQueryHighlightRules;
|
||||
});
|
||||
696
lib/ace/narcissus/definitions.js
Normal file
696
lib/ace/narcissus/definitions.js
Normal file
|
|
@ -0,0 +1,696 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Well-known constants and lookup tables. Many consts are generated from the
|
||||
* tokens table via eval to minimize redundancy, so consumers must be compiled
|
||||
* separately to take advantage of the simple switch-case constant propagation
|
||||
* done by SpiderMonkey.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
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",
|
||||
|
||||
// Contextual keywords.
|
||||
"IMPLEMENTS", "INTERFACE", "LET", "MODULE", "PACKAGE", "PRIVATE",
|
||||
"PROTECTED", "PUBLIC", "STATIC", "USE", "YIELD",
|
||||
|
||||
// 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",
|
||||
"new", "null",
|
||||
"return",
|
||||
"switch",
|
||||
"this", "throw", "true", "try", "typeof",
|
||||
"var", "void",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
var strictKeywords = {
|
||||
__proto__: null,
|
||||
"implements": true,
|
||||
"interface": true,
|
||||
"let": true,
|
||||
"module": true,
|
||||
"package": true,
|
||||
"private": true,
|
||||
"protected": true,
|
||||
"public": true,
|
||||
"static": true,
|
||||
"use": true,
|
||||
"yield": true
|
||||
};
|
||||
|
||||
var statementStartTokens = [
|
||||
"break",
|
||||
"const", "continue",
|
||||
"debugger", "do",
|
||||
"for",
|
||||
"if",
|
||||
"let",
|
||||
"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};
|
||||
var mozillaKeywords = {__proto__: null};
|
||||
|
||||
// Define const END, etc., based on the token names. Also map name to index.
|
||||
var tokenIds = {};
|
||||
|
||||
var hostSupportsEvalConst = (function() {
|
||||
try {
|
||||
return eval("(function(s) { eval(s); return x })('const x = true;')");
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
// Building up a string to be eval'd in different contexts.
|
||||
var consts = 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();
|
||||
if (name === "LET" || name === "YIELD")
|
||||
mozillaKeywords[name] = i;
|
||||
if (strictKeywords[name])
|
||||
strictKeywords[name] = i;
|
||||
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 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\]/);
|
||||
}
|
||||
|
||||
var Fpapply = Function.prototype.apply;
|
||||
|
||||
function apply(f, o, a) {
|
||||
return Fpapply.call(f, [o].concat(a));
|
||||
}
|
||||
|
||||
var applyNew;
|
||||
|
||||
// ES5's bind is a simpler way to implement applyNew
|
||||
if (Function.prototype.bind) {
|
||||
applyNew = function applyNew(f, a) {
|
||||
return new (f.bind.apply(f, [,].concat(Array.prototype.slice.call(a))))();
|
||||
};
|
||||
} else {
|
||||
applyNew = function applyNew(f, a) {
|
||||
switch (a.length) {
|
||||
case 0:
|
||||
return new f();
|
||||
case 1:
|
||||
return new f(a[0]);
|
||||
case 2:
|
||||
return new f(a[0], a[1]);
|
||||
case 3:
|
||||
return new f(a[0], a[1], a[2]);
|
||||
default:
|
||||
var argStr = "a[0]";
|
||||
for (var i = 1, n = a.length; i < n; i++)
|
||||
argStr += ",a[" + i + "]";
|
||||
return eval("new f(" + argStr + ")");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getPropertyDescriptor(obj, name) {
|
||||
while (obj) {
|
||||
if (({}).hasOwnProperty.call(obj, name))
|
||||
return Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
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 = Dict.create(blacklist).mapObject(function(name) { return mask; });
|
||||
return mixinHandler(redirect, target);
|
||||
}
|
||||
|
||||
function whitelistHandler(target, whitelist) {
|
||||
var catchall = Object.create(null, {});
|
||||
var redirect = Dict.create(whitelist).mapObject(function(name) { return target; });
|
||||
return mixinHandler(redirect, catchall);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 Dict(table, size) {
|
||||
this.table = table || Object.create(null, {});
|
||||
this.size = size || 0;
|
||||
}
|
||||
|
||||
Dict.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 Dict(init, size);
|
||||
};
|
||||
|
||||
Dict.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 Dict(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 Dict(table, this.size);
|
||||
},
|
||||
keys: function() {
|
||||
return Object.keys(this.table);
|
||||
},
|
||||
toString: function() { return "[object Dict]" }
|
||||
};
|
||||
|
||||
var _WeakMap = typeof WeakMap === "function" ? WeakMap : (function() {
|
||||
// shim for ES6 WeakMap with poor asymptotics
|
||||
function WeakMap(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();
|
||||
}
|
||||
|
||||
WeakMap.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 });
|
||||
},
|
||||
"delete": function(x) {
|
||||
var a = this.array;
|
||||
searchMap(this, x,
|
||||
function(pair, i) { a.splice(i, 1) },
|
||||
function() { });
|
||||
},
|
||||
toString: function() { return "[object WeakMap]" }
|
||||
};
|
||||
|
||||
return WeakMap;
|
||||
})();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!Array.prototype.copy) {
|
||||
defineProperty(Array.prototype, "copy",
|
||||
function() {
|
||||
var result = [];
|
||||
for (var i = 0, n = this.length; i < n; i++)
|
||||
result[i] = this[i];
|
||||
return result;
|
||||
}, false, false, true);
|
||||
}
|
||||
|
||||
if (!Array.prototype.top) {
|
||||
defineProperty(Array.prototype, "top",
|
||||
function() {
|
||||
return this.length && this[this.length-1];
|
||||
}, false, false, true);
|
||||
}
|
||||
|
||||
exports.tokens = tokens;
|
||||
exports.whitespace = whitespace;
|
||||
exports.opTypeNames = opTypeNames;
|
||||
exports.keywords = keywords;
|
||||
exports.mozillaKeywords = mozillaKeywords;
|
||||
exports.strictKeywords = strictKeywords;
|
||||
exports.isStatementStartCode = isStatementStartCode;
|
||||
exports.tokenIds = tokenIds;
|
||||
exports.consts = consts;
|
||||
exports.assignOps = assignOps;
|
||||
exports.defineGetter = defineGetter;
|
||||
exports.defineGetterSetter = defineGetterSetter;
|
||||
exports.defineMemoGetter = defineMemoGetter;
|
||||
exports.defineProperty = defineProperty;
|
||||
exports.isNativeCode = isNativeCode;
|
||||
exports.apply = apply;
|
||||
exports.applyNew = applyNew;
|
||||
exports.mixinHandler = mixinHandler;
|
||||
exports.whitelistHandler = whitelistHandler;
|
||||
exports.blacklistHandler = blacklistHandler;
|
||||
exports.makePassthruHandler = makePassthruHandler;
|
||||
exports.Dict = Dict;
|
||||
exports.WeakMap = _WeakMap;
|
||||
exports.Stack = Stack;
|
||||
|
||||
});
|
||||
|
|
@ -1,679 +0,0 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Well-known constants and lookup tables. Many consts are generated from the
|
||||
* tokens table via eval to minimize redundancy, so consumers must be compiled
|
||||
* separately to take advantage of the simple switch-case constant propagation
|
||||
* done by SpiderMonkey.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var narcissus = {
|
||||
options: {
|
||||
version: 185,
|
||||
// Global variables to hide from the interpreter
|
||||
hiddenHostGlobals: { Narcissus: true },
|
||||
// Desugar SpiderMonkey language extensions?
|
||||
desugarExtensions: false
|
||||
},
|
||||
hostSupportsEvalConst: (function() {
|
||||
try {
|
||||
return eval("(function(s) { eval(s); return x })('const x = true;')");
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
hostGlobal: this
|
||||
};
|
||||
Narcissus = narcissus;
|
||||
|
||||
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", "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);
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
});
|
||||
|
|
@ -1,549 +0,0 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Lexical scanner.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var definitions = require("./jsdefs");
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(definitions.consts);
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
this.blackList = blackLists[Narcissus.options.version];
|
||||
this.blockComments = null;
|
||||
}
|
||||
|
||||
Tokenizer.prototype = {
|
||||
get done() {
|
||||
// We need to set scanOperand to true here because the first thing
|
||||
// might be a regexp.
|
||||
return this.peek(true) === END;
|
||||
},
|
||||
|
||||
get token() {
|
||||
return this.tokens[this.tokenIndex];
|
||||
},
|
||||
|
||||
match: function (tt, scanOperand) {
|
||||
return this.get(scanOperand) === tt || this.unget();
|
||||
},
|
||||
|
||||
mustMatch: function (tt) {
|
||||
if (!this.match(tt)) {
|
||||
throw this.newSyntaxError("Missing " +
|
||||
definitions.tokens[tt].toLowerCase());
|
||||
}
|
||||
return this.token;
|
||||
},
|
||||
|
||||
peek: function (scanOperand) {
|
||||
var tt, next;
|
||||
if (this.lookahead) {
|
||||
next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
|
||||
tt = (this.scanNewlines && next.lineno !== this.lineno)
|
||||
? NEWLINE
|
||||
: next.type;
|
||||
} else {
|
||||
tt = this.get(scanOperand);
|
||||
this.unget();
|
||||
}
|
||||
return tt;
|
||||
},
|
||||
|
||||
peekOnSameLine: function (scanOperand) {
|
||||
this.scanNewlines = true;
|
||||
var tt = this.peek(scanOperand);
|
||||
this.scanNewlines = false;
|
||||
return tt;
|
||||
},
|
||||
|
||||
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 (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 in definitions.whitespace)) {
|
||||
this.cursor--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Lex the exponential part of a number, if present. Return true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
var input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next === 'e' || next === 'E') {
|
||||
this.cursor++;
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else if (ch === 'x' || ch === 'X') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||
(ch >= 'A' && ch <= 'F'));
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else if (ch >= '0' && ch <= '7') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '7');
|
||||
this.cursor--;
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else {
|
||||
this.cursor--;
|
||||
this.lexExponent(); // 0E1, &c.
|
||||
token.value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
lexNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
var floating = false;
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.' && !floating) {
|
||||
floating = true;
|
||||
ch = input[this.cursor++];
|
||||
}
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
var exponent = this.lexExponent();
|
||||
floating = floating || exponent;
|
||||
|
||||
var str = input.substring(token.start, this.cursor);
|
||||
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||
},
|
||||
|
||||
lexDot: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next >= '0' && next <= '9') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
|
||||
token.type = NUMBER;
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else {
|
||||
token.type = DOT;
|
||||
token.assignOp = null;
|
||||
token.value = '.';
|
||||
}
|
||||
},
|
||||
|
||||
lexString: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = STRING;
|
||||
|
||||
var hasEscapes = false;
|
||||
var delim = ch;
|
||||
if (input.length <= this.cursor)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
while ((ch = input[this.cursor++]) !== delim) {
|
||||
if (this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (ch === '\\') {
|
||||
hasEscapes = true;
|
||||
if (++this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
}
|
||||
}
|
||||
|
||||
token.value = hasEscapes
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
this.cursor++;
|
||||
} else if (ch === '[') {
|
||||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||
// for only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
var next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
}
|
||||
}
|
||||
|
||||
var op = node.op;
|
||||
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
token.type = ASSIGN;
|
||||
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
op += '=';
|
||||
} else {
|
||||
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
|
||||
token.value = op;
|
||||
},
|
||||
|
||||
// FIXME: Unicode escape sequences
|
||||
lexIdent: function (ch) {
|
||||
var token = this.token;
|
||||
var id = ch;
|
||||
|
||||
while ((ch = this.getValidIdentifierChar(false)) !== null) {
|
||||
id += ch;
|
||||
}
|
||||
|
||||
token.type = definitions.keywords[id] || IDENTIFIER;
|
||||
if (token.type in this.blackList) {
|
||||
// banned keyword, this is an identifier
|
||||
token.type = IDENTIFIER;
|
||||
}
|
||||
token.value = id;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.get :: void -> token type
|
||||
*
|
||||
* Consume input *only* if there is no lookahead.
|
||||
* Dispatch to the appropriate lexing function depending on the input.
|
||||
*/
|
||||
get: function (scanOperand) {
|
||||
var token;
|
||||
while (this.lookahead) {
|
||||
--this.lookahead;
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (token.type !== NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
|
||||
this.skip();
|
||||
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
|
||||
var input = this.source;
|
||||
if (this.cursor >= input.length)
|
||||
return token.type = END;
|
||||
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
|
||||
var 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.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
* Match depends on unget returning undefined.
|
||||
*/
|
||||
unget: function () {
|
||||
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
|
||||
newSyntaxError: function (m) {
|
||||
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;
|
||||
},
|
||||
|
||||
/* 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];
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
module.exports = { Tokenizer: Tokenizer };
|
||||
|
||||
});
|
||||
File diff suppressed because it is too large
Load diff
598
lib/ace/narcissus/lexer.js
Normal file
598
lib/ace/narcissus/lexer.js
Normal file
|
|
@ -0,0 +1,598 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Stephan Herhut <stephan.a.herhut@intel.com>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Narcissus - JS implemented in JS.
|
||||
*
|
||||
* Lexical scanner.
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
var definitions = require('./definitions');
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(definitions.consts);
|
||||
|
||||
// Build up a trie of operator tokens.
|
||||
var opTokens = {};
|
||||
for (var op in definitions.opTypeNames) {
|
||||
if (op === '\n' || op === '.')
|
||||
continue;
|
||||
|
||||
var node = opTokens;
|
||||
for (var i = 0; i < op.length; i++) {
|
||||
var ch = op[i];
|
||||
if (!(ch in node))
|
||||
node[ch] = {};
|
||||
node = node[ch];
|
||||
node.op = op;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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!)
|
||||
*/
|
||||
function isValidIdentifierChar(ch, first) {
|
||||
// check directly for ASCII
|
||||
if (ch <= "\u007F") {
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||
|
||||
(!first && (ch >= '0' && ch <= '9'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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) {}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
function isIdentifier(str) {
|
||||
if (typeof str !== "string")
|
||||
return false;
|
||||
|
||||
if (str.length === 0)
|
||||
return false;
|
||||
|
||||
if (!isValidIdentifierChar(str[0], true))
|
||||
return false;
|
||||
|
||||
for (var i = 1; i < str.length; i++) {
|
||||
if (!isValidIdentifierChar(str[i], false))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenizer :: (source, filename, line number, boolean) -> Tokenizer
|
||||
*/
|
||||
function Tokenizer(s, f, l, allowHTMLComments) {
|
||||
this.cursor = 0;
|
||||
this.source = String(s);
|
||||
this.tokens = [];
|
||||
this.tokenIndex = 0;
|
||||
this.lookahead = 0;
|
||||
this.scanNewlines = false;
|
||||
this.filename = f || "";
|
||||
this.lineno = l || 1;
|
||||
this.allowHTMLComments = allowHTMLComments;
|
||||
this.blockComments = null;
|
||||
}
|
||||
|
||||
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, keywordIsName) {
|
||||
return this.get(scanOperand, keywordIsName) === tt || this.unget();
|
||||
},
|
||||
|
||||
mustMatch: function (tt, keywordIsName) {
|
||||
if (!this.match(tt, false, keywordIsName)) {
|
||||
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.allowHTMLComments && ch === '<' && next === '!' &&
|
||||
input[this.cursor + 1] === '-' && input[this.cursor + 2] === '-' &&
|
||||
(this.cursor += 2))) {
|
||||
this.cursor++;
|
||||
for (;;) {
|
||||
ch = input[this.cursor++];
|
||||
next = input[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 in definitions.whitespace)) {
|
||||
this.cursor--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Lex the exponential part of a number, if present. Return true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
var input = this.source;
|
||||
var next = input[this.cursor];
|
||||
if (next === 'e' || next === 'E') {
|
||||
this.cursor++;
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(
|
||||
input.substring(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(
|
||||
input.substring(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 (ch == '\n' || ch == '\r')
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
if (ch === '\\') {
|
||||
hasEscapes = true;
|
||||
if (++this.cursor == input.length)
|
||||
throw this.newSyntaxError("Unterminated string literal");
|
||||
}
|
||||
}
|
||||
|
||||
token.value = hasEscapes
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
this.cursor++;
|
||||
} else if (ch === '[') {
|
||||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
|
||||
this.cursor--;
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||
// for only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
var next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
if (next in node) {
|
||||
node = node[next];
|
||||
this.cursor++;
|
||||
next = input[this.cursor];
|
||||
}
|
||||
}
|
||||
|
||||
var op = node.op;
|
||||
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
token.type = ASSIGN;
|
||||
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
op += '=';
|
||||
} else {
|
||||
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
|
||||
token.value = op;
|
||||
},
|
||||
|
||||
// FIXME: Unicode escape sequences
|
||||
lexIdent: function (ch, keywordIsName) {
|
||||
var token = this.token;
|
||||
var id = ch;
|
||||
|
||||
while ((ch = this.getValidIdentifierChar(false)) !== null) {
|
||||
id += ch;
|
||||
}
|
||||
|
||||
token.type = IDENTIFIER;
|
||||
token.value = id;
|
||||
|
||||
if (keywordIsName)
|
||||
return;
|
||||
|
||||
var kw;
|
||||
|
||||
if (this.parser.mozillaMode) {
|
||||
kw = definitions.mozillaKeywords[id];
|
||||
if (kw) {
|
||||
token.type = kw;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.parser.x.strictMode) {
|
||||
kw = definitions.strictKeywords[id];
|
||||
if (kw) {
|
||||
token.type = kw;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kw = definitions.keywords[id];
|
||||
if (kw)
|
||||
token.type = kw;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.get :: ([boolean[, boolean]]) -> token type
|
||||
*
|
||||
* Consume input *only* if there is no lookahead.
|
||||
* Dispatch to the appropriate lexing function depending on the input.
|
||||
*/
|
||||
get: function (scanOperand, keywordIsName) {
|
||||
var token;
|
||||
while (this.lookahead) {
|
||||
--this.lookahead;
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (token.type !== NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
|
||||
this.skip();
|
||||
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
|
||||
var input = this.source;
|
||||
if (this.cursor >= input.length)
|
||||
return token.type = END;
|
||||
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
|
||||
var ich = this.getValidIdentifierChar(true);
|
||||
var ch = (ich === null) ? input[this.cursor++] : null;
|
||||
if (ich !== null) {
|
||||
this.lexIdent(ich, keywordIsName);
|
||||
} 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.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
* Match depends on unget returning undefined.
|
||||
*/
|
||||
unget: function () {
|
||||
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
|
||||
newSyntaxError: function (m) {
|
||||
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;
|
||||
},
|
||||
|
||||
|
||||
/* Gets a single valid identifier char from the input stream, or null
|
||||
* if there is none.
|
||||
*/
|
||||
getValidIdentifierChar: function(first) {
|
||||
var input = this.source;
|
||||
if (this.cursor >= input.length) return null;
|
||||
var ch = input[this.cursor];
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
var valid = isValidIdentifierChar(ch, first);
|
||||
if (valid) this.cursor++;
|
||||
return (valid ? ch : null);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
exports.isIdentifier = isIdentifier;
|
||||
exports.Tokenizer = Tokenizer;
|
||||
|
||||
});
|
||||
61
lib/ace/narcissus/options.js
Normal file
61
lib/ace/narcissus/options.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* vim: set sw=4 ts=4 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Narcissus JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tom Austin <taustin@ucsc.edu>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Shu-Yu Guo <shu@rfrn.org>
|
||||
* Dave Herman <dherman@mozilla.com>
|
||||
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Global variables to hide from the interpreter
|
||||
exports.hiddenHostGlobals = { Narcissus: true };
|
||||
|
||||
// Desugar SpiderMonkey language extensions?
|
||||
exports.desugarExtensions = false;
|
||||
|
||||
// Allow HTML comments?
|
||||
exports.allowHTMLComments = false;
|
||||
|
||||
// Allow non-standard Mozilla extensions?
|
||||
exports.mozillaMode = true;
|
||||
|
||||
// Allow experimental paren-free mode?
|
||||
exports.parenFreeMode = false;
|
||||
|
||||
});
|
||||
2072
lib/ace/narcissus/parser.js
Normal file
2072
lib/ace/narcissus/parser.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -80,7 +80,8 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
|
|||
|
||||
this.$pos = pos;
|
||||
// Used for reset
|
||||
this.$undoStackDepth = session.getUndoManager().$undostack ? session.getUndoManager().$undostack.length : -1;
|
||||
var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
|
||||
this.$undoStackDepth = undoStack.length;
|
||||
this.setup();
|
||||
|
||||
session.selection.on("changeCursor", this.$onCursorChange);
|
||||
|
|
@ -265,7 +266,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
|
|||
if(this.$undoStackDepth === -1)
|
||||
throw Error("Canceling placeholders only supported with undo manager attached to session.");
|
||||
var undoManager = this.session.getUndoManager();
|
||||
var undosRequired = undoManager.$undostack.length - this.$undoStackDepth;
|
||||
var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;
|
||||
for (var i = 0; i < undosRequired; i++) {
|
||||
undoManager.undo(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,8 +140,6 @@ module.exports = {
|
|||
"test: cancel": function(next) {
|
||||
var session = new EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode());
|
||||
session.setUndoManager(new UndoManager());
|
||||
// hack around the difference between full ACE context and C9 world
|
||||
session.getUndoManager().$undostack = session.getUndoManager().$undoStack;
|
||||
var editor = new Editor(new MockRenderer(), session);
|
||||
var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ define(function (require, exports, module) {
|
|||
require("ace/lib/net").get(req.toUrl(name), onLoad);
|
||||
else
|
||||
//Using special require.nodeRequire, something added by r.js.
|
||||
globalRequire.nodeRequire('fs').readFileSync(req.toUrl(name), 'utf8');
|
||||
onLoad(globalRequire.nodeRequire('fs').readFileSync(req.toUrl(name), 'utf8'));
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ var MockRenderer = exports.MockRenderer = function(visibleRowCount) {
|
|||
};
|
||||
|
||||
this.isMockRenderer = true;
|
||||
|
||||
|
||||
this.$gutter = {};
|
||||
};
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ MockRenderer.prototype.updateCursor = function() {
|
|||
|
||||
MockRenderer.prototype.scrollToX = function(scrollTop) {};
|
||||
MockRenderer.prototype.scrollToY = function(scrollLeft) {};
|
||||
|
||||
|
||||
MockRenderer.prototype.scrollToLine = function(line, center) {
|
||||
var lineHeight = { lineHeight: 16 };
|
||||
var row = 0;
|
||||
|
|
@ -117,6 +117,9 @@ MockRenderer.prototype.scrollToLine = function(line, center) {
|
|||
this.scrollToRow(row);
|
||||
};
|
||||
|
||||
MockRenderer.prototype.scrollSelectionIntoView = function() {
|
||||
};
|
||||
|
||||
MockRenderer.prototype.scrollCursorIntoView = function() {
|
||||
var cursor = this.session.getSelection().getCursor();
|
||||
if (cursor.row < this.layerConfig.firstVisibleRow) {
|
||||
|
|
@ -179,7 +182,7 @@ MockRenderer.prototype.textToScreenCoordinates = function() {
|
|||
};
|
||||
|
||||
MockRenderer.prototype.adjustWrapLimit = function () {
|
||||
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
}\
|
||||
\
|
||||
.ace-chrome .ace_gutter {\
|
||||
width: 50px;\
|
||||
background: #e8e8e8;\
|
||||
color: #333;\
|
||||
overflow : hidden;\
|
||||
|
|
@ -58,10 +57,6 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
text-align: right;\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_gutter-layer .ace_gutter-cell {\
|
||||
padding-right: 6px;\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_print_margin {\
|
||||
width: 1px;\
|
||||
background: #e8e8e8;\
|
||||
|
|
@ -79,15 +74,11 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
border-left: 0px;\
|
||||
border-bottom: 1px solid black;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_invisible {\
|
||||
color: rgb(191, 191, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_keyword {\
|
||||
color: blue;\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_constant.ace_buildin {\
|
||||
color: rgb(88, 72, 246);\
|
||||
}\
|
||||
|
|
@ -121,14 +112,14 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
color: rgb(109, 121, 222);\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_variable.ace_parameter {\
|
||||
font-style:italic;\
|
||||
color:#FD971F;\
|
||||
}\
|
||||
.ace-chrome .ace_line .ace_keyword.ace_operator {\
|
||||
color: rgb(104, 118, 135);\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_string {\
|
||||
color: #1919a6;\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_comment {\
|
||||
color: #236e24;\
|
||||
}\
|
||||
|
|
@ -195,6 +186,8 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
border: 1px solid rgb(200, 200, 250);\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_storage,\
|
||||
.ace-chrome .ace_line .ace_keyword,\
|
||||
.ace-chrome .ace_meta.ace_tag {\
|
||||
color: rgb(147, 15, 128);\
|
||||
}\
|
||||
|
|
@ -203,6 +196,7 @@ exports.cssText = ".ace-chrome .ace_editor {\
|
|||
color: rgb(255, 0, 0)\
|
||||
}\
|
||||
\
|
||||
.ace-chrome .ace_line .ace_string,\
|
||||
.ace-chrome .ace_entity.ace_other.ace_attribute-name{\
|
||||
color: #994409;\
|
||||
}";
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #BFBFBF;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds .ace_keyword {\
|
||||
.ace-clouds .ace_keyword, .ace-clouds .ace_meta {\
|
||||
color:#AF956F;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -130,6 +130,10 @@ exports.cssText = "\
|
|||
color:#C52727;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds .ace_storage {\
|
||||
color:#C52727;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds .ace_string {\
|
||||
color:#5D90CD;\
|
||||
}\
|
||||
|
|
@ -146,7 +150,6 @@ exports.cssText = "\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #BFBFBF;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds-midnight .ace_keyword {\
|
||||
.ace-clouds-midnight .ace_keyword, .ace-clouds-midnight .ace_meta {\
|
||||
color:#927C5D;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -131,6 +131,10 @@ background-color:#E92E2E;\
|
|||
color:#E92E2E;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds-midnight .ace_storage {\
|
||||
color:#E92E2E;\
|
||||
}\
|
||||
\
|
||||
.ace-clouds-midnight .ace_string {\
|
||||
color:#5D90CD;\
|
||||
}\
|
||||
|
|
@ -147,7 +151,6 @@ background-color:#E92E2E;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: rgba(255, 255, 255, 0.15);\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_keyword {\
|
||||
.ace-cobalt .ace_keyword, .ace-cobalt .ace_meta {\
|
||||
color:#FF9D00;\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_constant {\
|
||||
.ace-cobalt .ace_constant, .ace-cobalt .ace_constant.ace_other {\
|
||||
color:#FF628C;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -118,6 +118,10 @@ background-color:#800F00;\
|
|||
color:#80FFBB;\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_support.ace_constant {\
|
||||
color:#EB939A;\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_fold {\
|
||||
background-color: #FF9D00;\
|
||||
border-color: #FFFFFF;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#800F00;\
|
|||
color:#FFB054;\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_storage {\
|
||||
color:#FFEE80;\
|
||||
}\
|
||||
\
|
||||
.ace-cobalt .ace_string.ace_regexp {\
|
||||
color:#80FFC2;\
|
||||
}\
|
||||
|
|
@ -161,6 +169,6 @@ background-color:#001221;\
|
|||
background-color:#130D26;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: rgba(75, 75, 126, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_keyword {\
|
||||
.ace-dawn .ace_keyword, .ace-dawn .ace_meta {\
|
||||
color:#794938;\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_constant {\
|
||||
.ace-dawn .ace_constant, .ace-dawn .ace_constant.ace_other {\
|
||||
color:#811F24;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -126,6 +126,10 @@ color:#B52A1D;\
|
|||
color:#691C97;\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_support.ace_constant {\
|
||||
color:#B4371F;\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_fold {\
|
||||
background-color: #794938;\
|
||||
border-color: #080808;\
|
||||
|
|
@ -135,6 +139,11 @@ color:#B52A1D;\
|
|||
color:#693A17;\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_storage {\
|
||||
font-style:italic;\
|
||||
color:#A71D5D;\
|
||||
}\
|
||||
\
|
||||
.ace-dawn .ace_string {\
|
||||
color:#0B6125;\
|
||||
}\
|
||||
|
|
@ -164,6 +173,6 @@ color:#5A525F;\
|
|||
color:#693A17;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,187 +37,188 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
exports.isDark = false;
|
||||
exports.cssClass = "ace-tm";
|
||||
exports.cssText = ".ace-tm .ace_editor {\
|
||||
exports.cssClass = "ace-dreamweaver";
|
||||
exports.cssText = ".ace-dreamweaver .ace_editor {\
|
||||
border: 2px solid rgb(159, 159, 159);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_editor.ace_focus {\
|
||||
.ace-dreamweaver .ace_editor.ace_focus {\
|
||||
border: 2px solid #327fbd;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_gutter {\
|
||||
.ace-dreamweaver .ace_gutter {\
|
||||
background: #e8e8e8;\
|
||||
color: #333;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_print_margin {\
|
||||
.ace-dreamweaver .ace_print_margin {\
|
||||
width: 1px;\
|
||||
background: #e8e8e8;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_fold {\
|
||||
.ace-dreamweaver .ace_fold {\
|
||||
background-color: #00F;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_text-layer {\
|
||||
.ace-dreamweaver .ace_text-layer {\
|
||||
cursor: text;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_cursor {\
|
||||
.ace-dreamweaver .ace_cursor {\
|
||||
border-left: 2px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_cursor.ace_overwrite {\
|
||||
.ace-dreamweaver .ace_cursor.ace_overwrite {\
|
||||
border-left: 0px;\
|
||||
border-bottom: 1px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_invisible {\
|
||||
.ace-dreamweaver .ace_line .ace_invisible {\
|
||||
color: rgb(191, 191, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_keyword {\
|
||||
.ace-dreamweaver .ace_line .ace_storage,\
|
||||
.ace-dreamweaver .ace_line .ace_keyword {\
|
||||
color: blue;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_constant.ace_buildin {\
|
||||
.ace-dreamweaver .ace_line .ace_constant.ace_buildin {\
|
||||
color: rgb(88, 72, 246);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_constant.ace_language {\
|
||||
.ace-dreamweaver .ace_line .ace_constant.ace_language {\
|
||||
color: rgb(88, 92, 246);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_constant.ace_library {\
|
||||
.ace-dreamweaver .ace_line .ace_constant.ace_library {\
|
||||
color: rgb(6, 150, 14);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_invalid {\
|
||||
.ace-dreamweaver .ace_line .ace_invalid {\
|
||||
background-color: rgb(153, 0, 0);\
|
||||
color: white;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_support.ace_function {\
|
||||
.ace-dreamweaver .ace_line .ace_support.ace_function {\
|
||||
color: rgb(60, 76, 114);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_support.ace_constant {\
|
||||
.ace-dreamweaver .ace_line .ace_support.ace_constant {\
|
||||
color: rgb(6, 150, 14);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_support.ace_type,\
|
||||
.ace-tm .ace_line .ace_support.ace_class {\
|
||||
.ace-dreamweaver .ace_line .ace_support.ace_type,\
|
||||
.ace-dreamweaver .ace_line .ace_support.ace_class {\
|
||||
color: #009;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_support.ace_php_tag {\
|
||||
.ace-dreamweaver .ace_line .ace_support.ace_php_tag {\
|
||||
color: #f00;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_keyword.ace_operator {\
|
||||
.ace-dreamweaver .ace_line .ace_keyword.ace_operator {\
|
||||
color: rgb(104, 118, 135);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_string {\
|
||||
.ace-dreamweaver .ace_line .ace_string {\
|
||||
color: #00F;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_comment {\
|
||||
.ace-dreamweaver .ace_line .ace_comment {\
|
||||
color: rgb(76, 136, 107);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_comment.ace_doc {\
|
||||
.ace-dreamweaver .ace_line .ace_comment.ace_doc {\
|
||||
color: rgb(0, 102, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {\
|
||||
.ace-dreamweaver .ace_line .ace_comment.ace_doc.ace_tag {\
|
||||
color: rgb(128, 159, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_constant.ace_numeric {\
|
||||
.ace-dreamweaver .ace_line .ace_constant.ace_numeric {\
|
||||
color: rgb(0, 0, 205);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_variable {\
|
||||
.ace-dreamweaver .ace_line .ace_variable {\
|
||||
color: #06F\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_xml_pe {\
|
||||
.ace-dreamweaver .ace_line .ace_xml_pe {\
|
||||
color: rgb(104, 104, 91);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_entity.ace_name.ace_function {\
|
||||
.ace-dreamweaver .ace_entity.ace_name.ace_function {\
|
||||
color: #00F;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_markup.ace_markupine {\
|
||||
.ace-dreamweaver .ace_markup.ace_markupine {\
|
||||
text-decoration:underline;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_markup.ace_heading {\
|
||||
.ace-dreamweaver .ace_markup.ace_heading {\
|
||||
color: rgb(12, 7, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_markup.ace_list {\
|
||||
.ace-dreamweaver .ace_markup.ace_list {\
|
||||
color:rgb(185, 6, 144);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_selection {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_selection {\
|
||||
background: rgb(181, 213, 255);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_step {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_step {\
|
||||
background: rgb(252, 255, 0);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_stack {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_stack {\
|
||||
background: rgb(164, 229, 101);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_bracket {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_bracket {\
|
||||
margin: -1px 0 0 -1px;\
|
||||
border: 1px solid rgb(192, 192, 192);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_active_line {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_active_line {\
|
||||
background: rgba(0, 0, 0, 0.07);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_marker-layer .ace_selected_word {\
|
||||
.ace-dreamweaver .ace_marker-layer .ace_selected_word {\
|
||||
background: rgb(250, 250, 255);\
|
||||
border: 1px solid rgb(200, 200, 250);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag {\
|
||||
color:#009;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_anchor {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_anchor {\
|
||||
color:#060;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_form {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_form {\
|
||||
color:#F90;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_image {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_image {\
|
||||
color:#909;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_script {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_script {\
|
||||
color:#900;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_style {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_style {\
|
||||
color:#909;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_meta.ace_tag.ace_table {\
|
||||
.ace-dreamweaver .ace_meta.ace_tag.ace_table {\
|
||||
color:#099;\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_string.ace_regex {\
|
||||
.ace-dreamweaver .ace_string.ace_regex {\
|
||||
color: rgb(255, 0, 0)\
|
||||
}";
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ exports.cssText = ".ace-eclipse .ace_editor {\
|
|||
border-left: 1px solid black;\
|
||||
}\
|
||||
\
|
||||
.ace-eclipse .ace_line .ace_keyword, .ace-eclipse .ace_line .ace_variable {\
|
||||
.ace-eclipse .ace_line .ace_storage,\
|
||||
.ace-eclipse .ace_line .ace_keyword,\
|
||||
.ace-eclipse .ace_line .ace_variable {\
|
||||
color: rgb(127, 0, 85);\
|
||||
}\
|
||||
\
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: #404040;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_keyword {\
|
||||
.ace-idle-fingers .ace_keyword, .ace-idle-fingers .ace_meta {\
|
||||
color:#CC7833;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_constant {\
|
||||
.ace-idle-fingers .ace_constant, .ace-idle-fingers .ace_constant.ace_other {\
|
||||
color:#6C99BB;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -114,6 +114,10 @@ exports.cssText = "\
|
|||
background-color:#FF0000;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_support.ace_constant {\
|
||||
color:#6C99BB;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_fold {\
|
||||
background-color: #CC7833;\
|
||||
border-color: #FFFFFF;\
|
||||
|
|
@ -123,6 +127,10 @@ background-color:#FF0000;\
|
|||
color:#B83426;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_variable.ace_parameter {\
|
||||
font-style:italic;\
|
||||
}\
|
||||
\
|
||||
.ace-idle-fingers .ace_string {\
|
||||
color:#A5C261;\
|
||||
}\
|
||||
|
|
@ -153,6 +161,6 @@ color:#BC9458;\
|
|||
background-color:#FFF980; \
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: rgba(255, 177, 111, 0.32);\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_keyword {\
|
||||
.ace-kr-theme .ace_keyword, .ace-kr-theme .ace_meta {\
|
||||
color:#949C8B;\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_constant {\
|
||||
.ace-kr-theme .ace_constant, .ace-kr-theme .ace_constant.ace_other {\
|
||||
color:rgba(210, 117, 24, 0.76);\
|
||||
}\
|
||||
\
|
||||
|
|
@ -118,6 +118,10 @@ background-color:#A41300;\
|
|||
color:#9FC28A;\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_support.ace_constant {\
|
||||
color:#C27E66;\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_fold {\
|
||||
background-color: #949C8B;\
|
||||
border-color: #FCFFE0;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#A41300;\
|
|||
color:#85873A;\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_storage {\
|
||||
color:#FFEE80;\
|
||||
}\
|
||||
\
|
||||
.ace-kr-theme .ace_string.ace_regexp {\
|
||||
color:rgba(125, 255, 192, 0.65);\
|
||||
}\
|
||||
|
|
@ -156,6 +164,6 @@ color:#706D5B;\
|
|||
background-color:#0F0040;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Schwartz <mr.pants AT gmail DOT com>
|
||||
* 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
|
||||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: #404040;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_keyword {\
|
||||
.ace-merbivore .ace_keyword, .ace-merbivore .ace_meta {\
|
||||
color:#FC6F09;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_constant {\
|
||||
.ace-merbivore .ace_constant, .ace-merbivore .ace_constant.ace_other {\
|
||||
color:#1EDAFB;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -126,6 +126,10 @@ exports.cssText = "\
|
|||
background-color:#990000;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_support.ace_constant {\
|
||||
color:#8DFF0A;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_fold {\
|
||||
background-color: #FC6F09;\
|
||||
border-color: #E6E1DC;\
|
||||
|
|
@ -135,6 +139,10 @@ background-color:#990000;\
|
|||
color:#FC6F09;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_storage {\
|
||||
color:#FC6F09;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore .ace_string {\
|
||||
color:#8DFF0A;\
|
||||
}\
|
||||
|
|
@ -156,6 +164,6 @@ color:#AD2EA4;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Schwartz <mr.pants AT gmail DOT com>
|
||||
* 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
|
||||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: #404040;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_keyword {\
|
||||
.ace-merbivore-soft .ace_keyword, .ace-merbivore-soft .ace_meta {\
|
||||
color:#FC803A;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_constant {\
|
||||
.ace-merbivore-soft .ace_constant, .ace-merbivore-soft .ace_constant.ace_other {\
|
||||
color:#68C1D8;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -131,11 +131,19 @@ background-color:#FE3838;\
|
|||
background-color:#FE3838;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_support.ace_constant {\
|
||||
color:#8EC65F;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_fold {\
|
||||
background-color: #FC803A;\
|
||||
border-color: #E6E1DC;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_storage {\
|
||||
color:#FC803A;\
|
||||
}\
|
||||
\
|
||||
.ace-merbivore-soft .ace_string {\
|
||||
color:#8EC65F;\
|
||||
}\
|
||||
|
|
@ -162,6 +170,6 @@ color:#AC4BB8;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: rgba(102, 108, 104, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_keyword {\
|
||||
.ace-mono-industrial .ace_keyword, .ace-mono-industrial .ace_meta {\
|
||||
color:#A39E64;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -109,7 +109,7 @@ exports.cssText = "\
|
|||
color:#A8B3AB;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_constant {\
|
||||
.ace-mono-industrial .ace_constant, .ace-mono-industrial .ace_constant.ace_other {\
|
||||
color:#E98800;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -122,6 +122,10 @@ exports.cssText = "\
|
|||
background-color:rgba(153, 0, 0, 0.68);\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_support.ace_constant {\
|
||||
color:#C87500;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_fold {\
|
||||
background-color: #A8B3AB;\
|
||||
border-color: #FFFFFF;\
|
||||
|
|
@ -131,6 +135,18 @@ background-color:rgba(153, 0, 0, 0.68);\
|
|||
color:#588E60;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_storage {\
|
||||
color:#C23B00;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_variable {\
|
||||
color:#A8B3AB;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_variable.ace_parameter {\
|
||||
color:#648BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-mono-industrial .ace_comment {\
|
||||
color:#666C68;\
|
||||
background-color:#151C19;\
|
||||
|
|
@ -156,6 +172,6 @@ background-color:#151C19;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #49483E;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_keyword {\
|
||||
.ace-monokai .ace_keyword, .ace-monokai .ace_meta {\
|
||||
color:#F92672;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -113,6 +113,10 @@ exports.cssText = "\
|
|||
color:#AE81FF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_constant.ace_other {\
|
||||
color:#AE81FF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_invalid {\
|
||||
color:#F8F8F0;\
|
||||
background-color:#F92672;\
|
||||
|
|
@ -123,6 +127,10 @@ background-color:#F92672;\
|
|||
background-color:#AE81FF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_support.ace_constant {\
|
||||
color:#66D9EF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_fold {\
|
||||
background-color: #A6E22E;\
|
||||
border-color: #F8F8F2;\
|
||||
|
|
@ -132,6 +140,24 @@ background-color:#AE81FF;\
|
|||
color:#66D9EF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_storage {\
|
||||
color:#F92672;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_storage.ace_type, .ace-monokai .ace_support.ace_type{\
|
||||
font-style:italic;\
|
||||
color:#66D9EF;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_variable {\
|
||||
color:#A6E22E;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_variable.ace_parameter {\
|
||||
font-style:italic;\
|
||||
color:#FD971F;\
|
||||
}\
|
||||
\
|
||||
.ace-monokai .ace_string {\
|
||||
color:#E6DB74;\
|
||||
}\
|
||||
|
|
@ -152,6 +178,6 @@ background-color:#AE81FF;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* André Fiedler <fiedler dot andre a t gmail dot com>
|
||||
* 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
|
||||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: rgba(255, 255, 255, 0.25);\
|
||||
}\
|
||||
\
|
||||
.ace-pastel-on-dark .ace_keyword {\
|
||||
.ace-pastel-on-dark .ace_keyword, .ace-pastel-on-dark .ace_meta {\
|
||||
color:#757aD8;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -109,7 +109,7 @@ exports.cssText = "\
|
|||
color:#797878;\
|
||||
}\
|
||||
\
|
||||
.ace-pastel-on-dark .ace_constant {\
|
||||
.ace-pastel-on-dark .ace_constant, .ace-pastel-on-dark .ace_constant.ace_other {\
|
||||
color:#4FB7C5;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -174,6 +174,6 @@ color:#D2A8A1;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_keyword {\
|
||||
.ace-solarized-dark .ace_keyword, .ace-solarized-dark .ace_meta {\
|
||||
color:#859900;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -113,6 +113,10 @@ exports.cssText = "\
|
|||
color:#D33682;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_constant.ace_other {\
|
||||
color:#CB4B16;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_fold {\
|
||||
background-color: #268BD2;\
|
||||
border-color: #93A1A1;\
|
||||
|
|
@ -122,6 +126,14 @@ exports.cssText = "\
|
|||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_storage {\
|
||||
color:#93A1A1;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_variable {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-dark .ace_string {\
|
||||
color:#2AA198;\
|
||||
}\
|
||||
|
|
@ -151,6 +163,6 @@ color:#657B83;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: rgba(147, 161, 161, 0.50);\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_keyword {\
|
||||
.ace-solarized-light .ace_keyword, .ace-solarized-light .ace_meta {\
|
||||
color:#859900;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -113,6 +113,10 @@ exports.cssText = "\
|
|||
color:#D33682;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_constant.ace_other {\
|
||||
color:#CB4B16;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_fold {\
|
||||
background-color: #268BD2;\
|
||||
border-color: #586E75;\
|
||||
|
|
@ -122,6 +126,14 @@ exports.cssText = "\
|
|||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_storage {\
|
||||
color:#073642;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_variable {\
|
||||
color:#268BD2;\
|
||||
}\
|
||||
\
|
||||
.ace-solarized-light .ace_string {\
|
||||
color:#2AA198;\
|
||||
}\
|
||||
|
|
@ -150,6 +162,6 @@ exports.cssText = "\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ exports.cssText = ".ace-tm .ace_editor {\
|
|||
color: rgb(191, 191, 191);\
|
||||
}\
|
||||
\
|
||||
.ace-tm .ace_line .ace_storage,\
|
||||
.ace-tm .ace_line .ace_keyword {\
|
||||
color: blue;\
|
||||
}\
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #D1D1D1;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_keyword {\
|
||||
.ace-tomorrow .ace_keyword, .ace-tomorrow .ace_meta {\
|
||||
color:#8959A8;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -117,6 +117,10 @@ exports.cssText = "\
|
|||
color:#F5871F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_constant.ace_other {\
|
||||
color:#666969;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_invalid {\
|
||||
color:#FFFFFF;\
|
||||
background-color:#C82829;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#C82829;\
|
|||
background-color:#8959A8;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_support.ace_constant {\
|
||||
color:#F5871F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_fold {\
|
||||
background-color: #4271AE;\
|
||||
border-color: #4D4D4C;\
|
||||
|
|
@ -136,6 +144,22 @@ background-color:#8959A8;\
|
|||
color:#4271AE;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_storage {\
|
||||
color:#8959A8;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_storage.ace_type, .ace-tomorrow .ace_support.ace_type{\
|
||||
color:#8959A8;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_variable {\
|
||||
color:#4271AE;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_variable.ace_parameter {\
|
||||
color:#F5871F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow .ace_string {\
|
||||
color:#718C00;\
|
||||
}\
|
||||
|
|
@ -172,6 +196,6 @@ background-color:#8959A8;\
|
|||
color:#718C00;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #4B4E55;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_keyword {\
|
||||
.ace-tomorrow-night .ace_keyword, .ace-tomorrow-night .ace_meta {\
|
||||
color:#B294BB;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -117,6 +117,10 @@ exports.cssText = "\
|
|||
color:#DE935F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_constant.ace_other {\
|
||||
color:#CED1CF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_invalid {\
|
||||
color:#CED2CF;\
|
||||
background-color:#DF5F5F;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#DF5F5F;\
|
|||
background-color:#B798BF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_support.ace_constant {\
|
||||
color:#DE935F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_fold {\
|
||||
background-color: #81A2BE;\
|
||||
border-color: #C5C8C6;\
|
||||
|
|
@ -136,6 +144,22 @@ background-color:#B798BF;\
|
|||
color:#81A2BE;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_storage {\
|
||||
color:#B294BB;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_storage.ace_type, .ace-tomorrow-night .ace_support.ace_type{\
|
||||
color:#B294BB;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_variable {\
|
||||
color:#81A2BE;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_variable.ace_parameter {\
|
||||
color:#DE935F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night .ace_string {\
|
||||
color:#B5BD68;\
|
||||
}\
|
||||
|
|
@ -172,6 +196,6 @@ background-color:#B798BF;\
|
|||
color:#B5BD68;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #404F7D;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_keyword {\
|
||||
.ace-tomorrow-night-blue .ace_keyword, .ace-tomorrow-night-blue .ace_meta {\
|
||||
color:#EBBBFF;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -117,6 +117,10 @@ exports.cssText = "\
|
|||
color:#FFC58F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_constant.ace_other {\
|
||||
color:#FFFFFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_invalid {\
|
||||
color:#FFFFFF;\
|
||||
background-color:#F99DA5;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#F99DA5;\
|
|||
background-color:#EBBBFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_support.ace_constant {\
|
||||
color:#FFC58F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_fold {\
|
||||
background-color: #BBDAFF;\
|
||||
border-color: #FFFFFF;\
|
||||
|
|
@ -136,6 +144,22 @@ background-color:#EBBBFF;\
|
|||
color:#BBDAFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_storage {\
|
||||
color:#EBBBFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_storage.ace_type, .ace-tomorrow-night-blue .ace_support.ace_type{\
|
||||
color:#EBBBFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_variable {\
|
||||
color:#BBDAFF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_variable.ace_parameter {\
|
||||
color:#FFC58F;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-blue .ace_string {\
|
||||
color:#D1F1A9;\
|
||||
}\
|
||||
|
|
@ -172,6 +196,6 @@ background-color:#EBBBFF;\
|
|||
color:#D1F1A9;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #343434;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_keyword {\
|
||||
.ace-tomorrow-night-bright .ace_keyword, .ace-tomorrow-night-bright .ace_meta {\
|
||||
color:#C397D8;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -117,6 +117,10 @@ exports.cssText = "\
|
|||
color:#E78C45;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_constant.ace_other {\
|
||||
color:#EEEEEE;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_invalid {\
|
||||
color:#CED2CF;\
|
||||
background-color:#DF5F5F;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#DF5F5F;\
|
|||
background-color:#B798BF;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_support.ace_constant {\
|
||||
color:#E78C45;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_fold {\
|
||||
background-color: #7AA6DA;\
|
||||
border-color: #DEDEDE;\
|
||||
|
|
@ -136,6 +144,22 @@ background-color:#B798BF;\
|
|||
color:#7AA6DA;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_storage {\
|
||||
color:#C397D8;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_storage.ace_type, .ace-tomorrow-night-bright .ace_support.ace_type{\
|
||||
color:#C397D8;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_variable {\
|
||||
color:#7AA6DA;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_variable.ace_parameter {\
|
||||
color:#E78C45;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-bright .ace_string {\
|
||||
color:#B9CA4A;\
|
||||
}\
|
||||
|
|
@ -172,6 +196,6 @@ background-color:#B798BF;\
|
|||
color:#B9CA4A;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ exports.cssText = "\
|
|||
color: #6A6A6A;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_keyword {\
|
||||
.ace-tomorrow-night-eighties .ace_keyword, .ace-tomorrow-night-eighties .ace_meta {\
|
||||
color:#CC99CC;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -117,6 +117,10 @@ exports.cssText = "\
|
|||
color:#F99157;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_constant.ace_other {\
|
||||
color:#CCCCCC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_invalid {\
|
||||
color:#CDCDCD;\
|
||||
background-color:#F2777A;\
|
||||
|
|
@ -127,6 +131,10 @@ background-color:#F2777A;\
|
|||
background-color:#CC99CC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_support.ace_constant {\
|
||||
color:#F99157;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_fold {\
|
||||
background-color: #6699CC;\
|
||||
border-color: #CCCCCC;\
|
||||
|
|
@ -136,6 +144,22 @@ background-color:#CC99CC;\
|
|||
color:#6699CC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_storage {\
|
||||
color:#CC99CC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_storage.ace_type, .ace-tomorrow-night-eighties .ace_support.ace_type{\
|
||||
color:#CC99CC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_variable {\
|
||||
color:#6699CC;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_variable.ace_parameter {\
|
||||
color:#F99157;\
|
||||
}\
|
||||
\
|
||||
.ace-tomorrow-night-eighties .ace_string {\
|
||||
color:#99CC99;\
|
||||
}\
|
||||
|
|
@ -168,6 +192,6 @@ background-color:#CC99CC;\
|
|||
color:#99CC99;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: rgba(255, 255, 255, 0.25);\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_keyword {\
|
||||
.ace-twilight .ace_keyword, .ace-twilight .ace_meta {\
|
||||
color:#CDA869;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_constant {\
|
||||
.ace-twilight .ace_constant, .ace-twilight .ace_constant.ace_other {\
|
||||
color:#CF6A4C;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -124,6 +124,10 @@ color:#D2A8A1;\
|
|||
color:#9B859D;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_support.ace_constant {\
|
||||
color:#CF6A4C;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_fold {\
|
||||
background-color: #AC885B;\
|
||||
border-color: #F8F8F8;\
|
||||
|
|
@ -133,6 +137,14 @@ color:#D2A8A1;\
|
|||
color:#DAD085;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_storage {\
|
||||
color:#F9EE98;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_variable {\
|
||||
color:#AC885B;\
|
||||
}\
|
||||
\
|
||||
.ace-twilight .ace_string {\
|
||||
color:#8F9D6A;\
|
||||
}\
|
||||
|
|
@ -174,6 +186,6 @@ color:#5F5A60;\
|
|||
color:#F9EE98;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Schwartz <mr.pants AT gmail DOT com>
|
||||
* 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
|
||||
|
|
@ -101,11 +101,11 @@ exports.cssText = "\
|
|||
color: #404040;\
|
||||
}\
|
||||
\
|
||||
.ace-vibrant-ink .ace_keyword {\
|
||||
.ace-vibrant-ink .ace_keyword, .ace-vibrant-ink .ace_meta {\
|
||||
color:#FF6600;\
|
||||
}\
|
||||
\
|
||||
.ace-vibrant-ink .ace_constant {\
|
||||
.ace-vibrant-ink .ace_constant, .ace-vibrant-ink .ace_constant.ace_other {\
|
||||
color:#339999;\
|
||||
}\
|
||||
\
|
||||
|
|
@ -132,6 +132,14 @@ background-color:#000000;\
|
|||
color:#FFCC00;\
|
||||
}\
|
||||
\
|
||||
.ace-vibrant-ink .ace_variable {\
|
||||
color:#FFCC00;\
|
||||
}\
|
||||
\
|
||||
.ace-vibrant-ink .ace_variable.ace_parameter {\
|
||||
font-style:italic;\
|
||||
}\
|
||||
\
|
||||
.ace-vibrant-ink .ace_string {\
|
||||
color:#66FF00;\
|
||||
}\
|
||||
|
|
@ -157,6 +165,6 @@ color:#99CC99;\
|
|||
text-decoration:underline;\
|
||||
}";
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -56,17 +56,17 @@ module.exports = {
|
|||
" } // Real Tab.",
|
||||
"}"
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
|
||||
var iterator = new TokenIterator(session, 0, 0);
|
||||
assert.equal(iterator.getCurrentToken().value, "function");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 0);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 0);
|
||||
|
||||
|
||||
iterator.stepForward();
|
||||
assert.equal(iterator.getCurrentToken().value, " ");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 0);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 8);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 8);
|
||||
|
||||
var iterator = new TokenIterator(session, 0, 4);
|
||||
assert.equal(iterator.getCurrentToken().value, "function");
|
||||
|
|
@ -76,7 +76,7 @@ module.exports = {
|
|||
iterator.stepForward();
|
||||
assert.equal(iterator.getCurrentToken().value, " ");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 0);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 8);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 8);
|
||||
|
||||
var iterator = new TokenIterator(session, 2, 18);
|
||||
assert.equal(iterator.getCurrentToken().value, "items");
|
||||
|
|
@ -86,8 +86,8 @@ module.exports = {
|
|||
iterator.stepForward();
|
||||
assert.equal(iterator.getCurrentToken().value, "[");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 2);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 19);
|
||||
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 19);
|
||||
|
||||
var iterator = new TokenIterator(session, 4, 0);
|
||||
assert.equal(iterator.getCurrentToken().value, "}");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 4);
|
||||
|
|
@ -96,21 +96,21 @@ module.exports = {
|
|||
iterator.stepBackward();
|
||||
assert.equal(iterator.getCurrentToken().value, "// Real Tab.");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 3);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 6);
|
||||
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 6);
|
||||
|
||||
var iterator = new TokenIterator(session, 5, 0);
|
||||
assert.equal(iterator.getCurrentToken(), null);
|
||||
},
|
||||
|
||||
|
||||
"test: token iterator initialization in text document" : function() {
|
||||
var lines = [
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit,",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit,",
|
||||
"sed do eiusmod tempor incididunt ut labore et dolore magna",
|
||||
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation",
|
||||
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation",
|
||||
"ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"));
|
||||
|
||||
|
||||
var iterator = new TokenIterator(session, 0, 0);
|
||||
assert.equal(iterator.getCurrentToken().value, lines[0]);
|
||||
assert.equal(iterator.getCurrentTokenRow(), 0);
|
||||
|
|
@ -125,16 +125,16 @@ module.exports = {
|
|||
assert.equal(iterator.getCurrentToken().value, lines[2]);
|
||||
assert.equal(iterator.getCurrentTokenRow(), 2);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 0);
|
||||
|
||||
|
||||
var iterator = new TokenIterator(session, 3, lines[3].length-1);
|
||||
assert.equal(iterator.getCurrentToken().value, lines[3]);
|
||||
assert.equal(iterator.getCurrentTokenRow(), 3);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 0);
|
||||
|
||||
|
||||
var iterator = new TokenIterator(session, 4, 0);
|
||||
assert.equal(iterator.getCurrentToken(), null);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
"test: token iterator step forward in JavaScript document" : function() {
|
||||
var lines = [
|
||||
"function foo(items) {",
|
||||
|
|
@ -143,10 +143,10 @@ module.exports = {
|
|||
" } // Real Tab.",
|
||||
"}"
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
|
||||
var rows = session.getTokens(0, lines.length-1);
|
||||
var tokens = [];
|
||||
var tokens = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
tokens = tokens.concat(rows[i].tokens);
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ module.exports = {
|
|||
assert.equal(iterator.stepForward(), null);
|
||||
assert.equal(iterator.getCurrentToken(), null);
|
||||
},
|
||||
|
||||
|
||||
"test: token iterator step backward in JavaScript document" : function() {
|
||||
var lines = [
|
||||
"function foo(items) {",
|
||||
|
|
@ -165,13 +165,13 @@ module.exports = {
|
|||
" } // Real Tab.",
|
||||
"}"
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
|
||||
var rows = session.getTokens(0, lines.length-1);
|
||||
var tokens = [];
|
||||
var tokens = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
tokens = tokens.concat(rows[i].tokens);
|
||||
|
||||
|
||||
var iterator = new TokenIterator(session, 4, 0);
|
||||
for (var i = tokens.length-2; i >= 0; i--)
|
||||
assert.equal(iterator.stepBackward(), tokens[i]);
|
||||
|
|
@ -187,13 +187,13 @@ module.exports = {
|
|||
" } // Real Tab.",
|
||||
"}"
|
||||
];
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
var session = new EditSession(lines.join("\n"), new JavaScriptMode());
|
||||
|
||||
var iterator = new TokenIterator(session, 0, 0);
|
||||
|
||||
|
||||
iterator.stepForward();
|
||||
iterator.stepForward();
|
||||
|
||||
|
||||
assert.equal(iterator.getCurrentToken().value, "foo");
|
||||
assert.equal(iterator.getCurrentTokenRow(), 0);
|
||||
assert.equal(iterator.getCurrentTokenColumn(), 9);
|
||||
|
|
|
|||
|
|
@ -65,23 +65,30 @@ var Tokenizer = function(rules, flag) {
|
|||
var ruleRegExps = [];
|
||||
var matchTotal = 0;
|
||||
var mapping = this.matchMappings[key] = {};
|
||||
|
||||
|
||||
for ( var i = 0; i < state.length; i++) {
|
||||
|
||||
if (state[i].regex instanceof RegExp)
|
||||
state[i].regex = state[i].regex.toString().slice(1, -1);
|
||||
|
||||
// Count number of matching groups. 2 extra groups from the full match
|
||||
// And the catch-all on the end (used to force a match);
|
||||
var matchcount = new RegExp("(?:(" + state[i].regex + ")|(.))").exec("a").length - 2;
|
||||
|
||||
|
||||
// Replace any backreferences and offset appropriately.
|
||||
var adjustedregex = state[i].regex.replace(/\\([0-9]+)/g, function (match, digit) {
|
||||
return "\\" + (parseInt(digit, 10) + matchTotal + 1);
|
||||
});
|
||||
|
||||
|
||||
if (matchcount > 1 && state[i].token.length !== matchcount-1)
|
||||
throw new Error("Matching groups and length of the token array don't match in rule #" + i + " of state " + key);
|
||||
|
||||
mapping[matchTotal] = {
|
||||
rule: i,
|
||||
len: matchcount
|
||||
};
|
||||
matchTotal += matchcount;
|
||||
|
||||
|
||||
ruleRegExps.push(adjustedregex);
|
||||
}
|
||||
|
||||
|
|
@ -102,47 +109,47 @@ var Tokenizer = function(rules, flag) {
|
|||
var mapping = this.matchMappings[currentState];
|
||||
var re = this.regExps[currentState];
|
||||
re.lastIndex = 0;
|
||||
|
||||
|
||||
var match, tokens = [];
|
||||
|
||||
|
||||
var lastIndex = 0;
|
||||
|
||||
|
||||
var token = {
|
||||
type: null,
|
||||
value: ""
|
||||
};
|
||||
|
||||
|
||||
while (match = re.exec(line)) {
|
||||
var type = "text";
|
||||
var rule = null;
|
||||
var value = [match[0]];
|
||||
|
||||
for (var i = 0; i < match.length-2; i++) {
|
||||
if (match[i + 1] !== undefined) {
|
||||
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 (match[i + 1] === undefined)
|
||||
continue;
|
||||
|
||||
var next = rule.next;
|
||||
if (next && next !== currentState) {
|
||||
currentState = next;
|
||||
state = this.rules[currentState];
|
||||
mapping = this.matchMappings[currentState];
|
||||
lastIndex = re.lastIndex;
|
||||
rule = state[mapping[i].rule];
|
||||
|
||||
re = this.regExps[currentState];
|
||||
re.lastIndex = lastIndex;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
|
||||
var next = rule.next;
|
||||
if (next && next !== currentState) {
|
||||
currentState = next;
|
||||
state = this.rules[currentState];
|
||||
mapping = this.matchMappings[currentState];
|
||||
lastIndex = re.lastIndex;
|
||||
|
||||
re = this.regExps[currentState];
|
||||
re.lastIndex = lastIndex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (value[0]) {
|
||||
|
|
@ -151,13 +158,15 @@ var Tokenizer = function(rules, flag) {
|
|||
type = [type];
|
||||
}
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
if (!value[i])
|
||||
continue;
|
||||
|
||||
if ((!rule || rule.merge || type[i] === "text") && token.type === type[i]) {
|
||||
token.value += value[i];
|
||||
} else {
|
||||
if (token.type) {
|
||||
if (token.type)
|
||||
tokens.push(token);
|
||||
}
|
||||
|
||||
|
||||
token = {
|
||||
type: type[i],
|
||||
value: value[i]
|
||||
|
|
@ -165,10 +174,10 @@ var Tokenizer = function(rules, flag) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lastIndex == line.length)
|
||||
break;
|
||||
|
||||
|
||||
lastIndex = re.lastIndex;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ var oop = require("./lib/oop");
|
|||
var dom = require("./lib/dom");
|
||||
var event = require("./lib/event");
|
||||
var useragent = require("./lib/useragent");
|
||||
var config = require("./config");
|
||||
var net = require("./lib/net");
|
||||
var GutterLayer = require("./layer/gutter").Gutter;
|
||||
var MarkerLayer = require("./layer/marker").Marker;
|
||||
var TextLayer = require("./layer/text").Text;
|
||||
|
|
@ -847,17 +849,23 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$cursorLayer.showCursor();
|
||||
};
|
||||
|
||||
this.scrollSelectionIntoView = function(anchor, lead) {
|
||||
// first scroll anchor into view then scroll lead into view
|
||||
this.scrollCursorIntoView(anchor);
|
||||
this.scrollCursorIntoView(lead);
|
||||
};
|
||||
|
||||
/**
|
||||
* VirtualRenderer.scrollCursorIntoView() -> Void
|
||||
*
|
||||
* Scrolls the cursor into the first visibile area of the editor
|
||||
**/
|
||||
this.scrollCursorIntoView = function() {
|
||||
this.scrollCursorIntoView = function(cursor) {
|
||||
// the editor is not visible
|
||||
if (this.$size.scrollerHeight === 0)
|
||||
return;
|
||||
|
||||
var pos = this.$cursorLayer.getPixelPosition();
|
||||
var pos = this.$cursorLayer.getPixelPosition(cursor);
|
||||
|
||||
var left = pos.left;
|
||||
var top = pos.top;
|
||||
|
|
@ -1122,6 +1130,15 @@ var VirtualRenderer = function(container, theme) {
|
|||
style.left = "-10000px";
|
||||
};
|
||||
|
||||
this._loadTheme = function(name, callback) {
|
||||
if (!config.get("packaged"))
|
||||
return callback();
|
||||
|
||||
var base = name.split("/").pop();
|
||||
var filename = config.get("themePath") + "/theme-" + base + config.get("suffix");
|
||||
net.loadScript(filename, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* VirtualRenderer.setTheme(theme) -> Void
|
||||
* - theme (String): The path to a theme
|
||||
|
|
@ -1133,9 +1150,22 @@ var VirtualRenderer = function(container, theme) {
|
|||
|
||||
this.$themeValue = theme;
|
||||
if (!theme || typeof theme == "string") {
|
||||
theme = theme || "ace/theme/textmate";
|
||||
require([theme], function(theme) {
|
||||
afterLoad(theme);
|
||||
var moduleName = theme || "ace/theme/textmate";
|
||||
|
||||
var module;
|
||||
try {
|
||||
module = require(moduleName);
|
||||
} catch (e) {};
|
||||
if (module)
|
||||
return afterLoad(module);
|
||||
|
||||
_self._loadTheme(moduleName, function() {
|
||||
require([theme], function(module) {
|
||||
if (_self.$themeValue !== theme)
|
||||
return;
|
||||
|
||||
afterLoad(module);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
afterLoad(theme);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -40,14 +40,14 @@ define(function(require, exports, module) {
|
|||
|
||||
var oop = require("../lib/oop");
|
||||
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||
var config = require("../config");
|
||||
|
||||
var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
|
||||
|
||||
this.changeListener = this.changeListener.bind(this);
|
||||
|
||||
if (module.packaged) {
|
||||
var base = this.$guessBasePath();
|
||||
this.$worker = new Worker(base + packagedJs);
|
||||
if (config.get("packaged")) {
|
||||
this.$worker = new Worker(config.get("workerPath") + "/" + packagedJs);
|
||||
}
|
||||
else {
|
||||
var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
|
||||
|
|
@ -112,29 +112,6 @@ var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
|
|||
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 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)?(-noconflict)?\.js)(?:\?|$)/);
|
||||
if (m)
|
||||
return m[1] || m[2];
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
this.terminate = function() {
|
||||
this._emit("terminate", {});
|
||||
this.$worker.terminate();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue