public/javascripts/erp_app/codemirror/mode/coffeescript/coffeescript.js in erp_app-3.0.7 vs public/javascripts/erp_app/codemirror/mode/coffeescript/coffeescript.js in erp_app-3.0.8
- old
+ new
@@ -2,35 +2,40 @@
* Link to the project's GitHub page:
* https://github.com/pickhardt/coffeescript-codemirror-mode
*/
CodeMirror.defineMode('coffeescript', function(conf) {
var ERRORCLASS = 'error';
-
+
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
-
+
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");
- var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
- var doubleOperators = new RegExp("^((\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
- var doubleDelimiters = new RegExp("^((\->)|(\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
+ var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\},:`=;\\.]');
+ var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
+ var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
- var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
+ var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");
+ var properties = new RegExp("^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*");
var wordOperators = wordRegexp(['and', 'or', 'not',
'is', 'isnt', 'in',
'instanceof', 'typeof']);
- var commonKeywords = ['break', 'by', 'catch', 'class', 'continue',
- 'debugger', 'delete', 'do', 'else', 'finally',
- 'for', 'in', 'of', 'if', 'new', 'return',
- 'switch', 'then', 'this', 'throw', 'try',
- 'unless', 'when', 'while', 'until', 'loop'];
- var keywords = wordRegexp(commonKeywords);
+ var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
+ 'switch', 'try', 'catch', 'finally', 'class'];
+ var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
+ 'do', 'in', 'of', 'new', 'return', 'then',
+ 'this', 'throw', 'when', 'until'];
+ var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
- var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
- var commonConstants = ['Infinity', 'NaN', 'undefined', 'true', 'false'];
+ indentKeywords = wordRegexp(indentKeywords);
+
+
+ var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
+ var regexPrefixes = new RegExp("^(/{3}|/)");
+ var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
var constants = wordRegexp(commonConstants);
// Tokenizers
function tokenBase(stream, state) {
// Handle scope changes
@@ -51,19 +56,31 @@
}
}
if (stream.eatSpace()) {
return null;
}
-
+
var ch = stream.peek();
-
- // Handle comments
+
+ // Handle docco title comment (single line)
+ if (stream.match("####")) {
+ stream.skipToEnd();
+ return 'comment';
+ }
+
+ // Handle multi line comments
+ if (stream.match("###")) {
+ state.tokenize = longComment;
+ return state.tokenize(stream, state);
+ }
+
+ // Single line comment
if (ch === '#') {
stream.skipToEnd();
return 'comment';
}
-
+
// Handle number literals
if (stream.match(/^-?[0-9\.]/, false)) {
var floatLiteral = false;
// Floats
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
@@ -73,11 +90,16 @@
floatLiteral = true;
}
if (stream.match(/^-?\.\d+/)) {
floatLiteral = true;
}
+
if (floatLiteral) {
+ // prevent from getting extra . on 1..
+ if (stream.peek() == "."){
+ stream.backUp(1);
+ }
return 'number';
}
// Integers
var intLiteral = false;
// Hex
@@ -94,17 +116,26 @@
}
if (intLiteral) {
return 'number';
}
}
-
+
// Handle strings
if (stream.match(stringPrefixes)) {
- state.tokenize = tokenStringFactory(stream.current());
+ state.tokenize = tokenFactory(stream.current(), 'string');
return state.tokenize(stream, state);
}
-
+ // Handle regex literals
+ if (stream.match(regexPrefixes)) {
+ if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
+ state.tokenize = tokenFactory(stream.current(), 'string-2');
+ return state.tokenize(stream, state);
+ } else {
+ stream.backUp(1);
+ }
+ }
+
// Handle operators and delimiters
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
return 'punctuation';
}
if (stream.match(doubleOperators)
@@ -113,62 +144,72 @@
return 'operator';
}
if (stream.match(singleDelimiters)) {
return 'punctuation';
}
-
+
if (stream.match(constants)) {
return 'atom';
}
-
+
if (stream.match(keywords)) {
return 'keyword';
}
-
+
if (stream.match(identifiers)) {
return 'variable';
}
+ if (stream.match(properties)) {
+ return 'property';
+ }
+
// Handle non-detected items
stream.next();
return ERRORCLASS;
}
-
- function tokenStringFactory(delimiter) {
- while ('rub'.indexOf(delimiter[0].toLowerCase()) >= 0) {
- delimiter = delimiter.substr(1);
- }
- var delim_re = new RegExp(delimiter);
+
+ function tokenFactory(delimiter, outclass) {
var singleline = delimiter.length == 1;
- var OUTCLASS = 'string';
-
return function tokenString(stream, state) {
while (!stream.eol()) {
- stream.eatWhile(/[^'"\\]/);
+ stream.eatWhile(/[^'"\/\\]/);
if (stream.eat('\\')) {
stream.next();
if (singleline && stream.eol()) {
- return OUTCLASS;
+ return outclass;
}
- } else if (stream.match(delim_re)) {
+ } else if (stream.match(delimiter)) {
state.tokenize = tokenBase;
- return OUTCLASS;
+ return outclass;
} else {
- stream.eat(/['"]/);
+ stream.eat(/['"\/]/);
}
}
if (singleline) {
if (conf.mode.singleLineStringErrors) {
- OUTCLASS = ERRORCLASS
+ outclass = ERRORCLASS
} else {
state.tokenize = tokenBase;
}
}
- return OUTCLASS;
+ return outclass;
};
}
-
+
+ function longComment(stream, state) {
+ while (!stream.eol()) {
+ stream.eatWhile(/[^#]/);
+ if (stream.match("###")) {
+ state.tokenize = tokenBase;
+ break;
+ }
+ stream.eatWhile("#");
+ }
+ return "comment"
+ }
+
function indent(stream, state, type) {
type = type || 'coffee';
var indentUnit = 0;
if (type === 'coffee') {
for (var i = 0; i < state.scopes.length; i++) {
@@ -183,11 +224,11 @@
state.scopes.unshift({
offset: indentUnit,
type: type
});
}
-
+
function dedent(stream, state) {
if (state.scopes.length == 1) return;
if (state.scopes[0].type === 'coffee') {
var _indent = stream.indentation();
var _indent_index = -1;
@@ -222,37 +263,34 @@
return 'variable';
} else {
return ERRORCLASS;
}
}
-
- // Handle decorators
- if (current === '@') {
- style = state.tokenize(stream, state);
- current = stream.current();
- if (style === 'variable') {
- return 'variable-2';
- } else {
- return ERRORCLASS;
- }
- }
-
+
// Handle scope changes.
- if (current === 'pass' || current === 'return') {
+ if (current === 'return') {
state.dedent += 1;
}
- if ((current === '->' &&
+ if (((current === '->' || current === '=>') &&
!state.lambda &&
state.scopes[0].type == 'coffee' &&
stream.peek() === '')
|| style === 'indent') {
indent(stream, state);
}
var delimiter_index = '[({'.indexOf(current);
if (delimiter_index !== -1) {
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
}
+ if (indentKeywords.exec(current)){
+ indent(stream, state);
+ }
+ if (current == 'then'){
+ dedent(stream, state);
+ }
+
+
if (style === 'dedent') {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
@@ -264,11 +302,11 @@
}
if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
if (state.scopes.length > 1) state.scopes.shift();
state.dedent -= 1;
}
-
+
return style;
}
var external = {
startState: function(basecolumn) {
@@ -278,30 +316,30 @@
lastToken: null,
lambda: false,
dedent: 0
};
},
-
+
token: function(stream, state) {
var style = tokenLexer(stream, state);
-
+
state.lastToken = {style:style, content: stream.current()};
-
+
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
-
+
return style;
},
-
+
indent: function(state, textAfter) {
if (state.tokenize != tokenBase) {
return 0;
}
-
+
return state.scopes[0].offset;
}
-
+
};
return external;
});
CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');