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