Merge master

This commit is contained in:
Garen Torikian 2012-04-09 21:33:39 -07:00
commit 1c5320f84e
406 changed files with 82454 additions and 34265 deletions

View file

@ -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

View file

@ -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);

View file

@ -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
View 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(); });
}
});

View file

@ -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];

View file

@ -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

View file

@ -395,6 +395,7 @@ function setupSettingPanel(settingDiv, settingOpener, api, options) {
svg: "SVG",
textile: "Textile",
groovy: "Groovy",
liquid: "Liquid",
Scala: "Scala"
},
theme: {

View file

@ -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;

View 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;
});

View file

@ -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

View file

@ -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];
};
});

View file

@ -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

View file

@ -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'];
});

View file

@ -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

View file

@ -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);

View file

@ -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);
},

View file

@ -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);

View file

@ -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") ]);
};

View file

@ -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);
}
};

View file

@ -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) {

View file

@ -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
View 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;
});

View 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;
});

View 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()
}

View file

@ -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"],

View file

@ -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
View 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;
});

View 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
View 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;
});

View 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;
});

View 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;
});

View file

@ -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
};
});

View file

@ -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
View 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;
});

View 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

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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}]);

View file

@ -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'));
};
});

View file

@ -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 () {
};
});

View file

@ -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;\
}";

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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)\
}";

View file

@ -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);\
}\
\

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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;\
}\

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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();