LaravelTest
433 строки · 12.6 Кб
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4(function(mod) {5if (typeof exports == "object" && typeof module == "object") // CommonJS6mod(require("../../lib/codemirror"));7else if (typeof define == "function" && define.amd) // AMD8define(["../../lib/codemirror"], mod);9else // Plain browser env10mod(CodeMirror);11})(function(CodeMirror) {12"use strict";13
14CodeMirror.defineMode("crystal", function(config) {15function wordRegExp(words, end) {16return new RegExp((end ? "" : "^") + "(?:" + words.join("|") + ")" + (end ? "$" : "\\b"));17}18
19function chain(tokenize, stream, state) {20state.tokenize.push(tokenize);21return tokenize(stream, state);22}23
24var operators = /^(?:[-+/%|&^]|\*\*?|[<>]{2})/;25var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/;26var indexingOperators = /^(?:\[\][?=]?)/;27var anotherOperators = /^(?:\.(?:\.{2})?|->|[?:])/;28var idents = /^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;29var types = /^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;30var keywords = wordRegExp([31"abstract", "alias", "as", "asm", "begin", "break", "case", "class", "def", "do",32"else", "elsif", "end", "ensure", "enum", "extend", "for", "fun", "if",33"include", "instance_sizeof", "lib", "macro", "module", "next", "of", "out", "pointerof",34"private", "protected", "rescue", "return", "require", "select", "sizeof", "struct",35"super", "then", "type", "typeof", "uninitialized", "union", "unless", "until", "when", "while", "with",36"yield", "__DIR__", "__END_LINE__", "__FILE__", "__LINE__"37]);38var atomWords = wordRegExp(["true", "false", "nil", "self"]);39var indentKeywordsArray = [40"def", "fun", "macro",41"class", "module", "struct", "lib", "enum", "union",42"do", "for"43];44var indentKeywords = wordRegExp(indentKeywordsArray);45var indentExpressionKeywordsArray = ["if", "unless", "case", "while", "until", "begin", "then"];46var indentExpressionKeywords = wordRegExp(indentExpressionKeywordsArray);47var dedentKeywordsArray = ["end", "else", "elsif", "rescue", "ensure"];48var dedentKeywords = wordRegExp(dedentKeywordsArray);49var dedentPunctualsArray = ["\\)", "\\}", "\\]"];50var dedentPunctuals = new RegExp("^(?:" + dedentPunctualsArray.join("|") + ")$");51var nextTokenizer = {52"def": tokenFollowIdent, "fun": tokenFollowIdent, "macro": tokenMacroDef,53"class": tokenFollowType, "module": tokenFollowType, "struct": tokenFollowType,54"lib": tokenFollowType, "enum": tokenFollowType, "union": tokenFollowType55};56var matching = {"[": "]", "{": "}", "(": ")", "<": ">"};57
58function tokenBase(stream, state) {59if (stream.eatSpace()) {60return null;61}62
63// Macros64if (state.lastToken != "\\" && stream.match("{%", false)) {65return chain(tokenMacro("%", "%"), stream, state);66}67
68if (state.lastToken != "\\" && stream.match("{{", false)) {69return chain(tokenMacro("{", "}"), stream, state);70}71
72// Comments73if (stream.peek() == "#") {74stream.skipToEnd();75return "comment";76}77
78// Variables and keywords79var matched;80if (stream.match(idents)) {81stream.eat(/[?!]/);82
83matched = stream.current();84if (stream.eat(":")) {85return "atom";86} else if (state.lastToken == ".") {87return "property";88} else if (keywords.test(matched)) {89if (indentKeywords.test(matched)) {90if (!(matched == "fun" && state.blocks.indexOf("lib") >= 0) && !(matched == "def" && state.lastToken == "abstract")) {91state.blocks.push(matched);92state.currentIndent += 1;93}94} else if ((state.lastStyle == "operator" || !state.lastStyle) && indentExpressionKeywords.test(matched)) {95state.blocks.push(matched);96state.currentIndent += 1;97} else if (matched == "end") {98state.blocks.pop();99state.currentIndent -= 1;100}101
102if (nextTokenizer.hasOwnProperty(matched)) {103state.tokenize.push(nextTokenizer[matched]);104}105
106return "keyword";107} else if (atomWords.test(matched)) {108return "atom";109}110
111return "variable";112}113
114// Class variables and instance variables115// or attributes116if (stream.eat("@")) {117if (stream.peek() == "[") {118return chain(tokenNest("[", "]", "meta"), stream, state);119}120
121stream.eat("@");122stream.match(idents) || stream.match(types);123return "variable-2";124}125
126// Constants and types127if (stream.match(types)) {128return "tag";129}130
131// Symbols or ':' operator132if (stream.eat(":")) {133if (stream.eat("\"")) {134return chain(tokenQuote("\"", "atom", false), stream, state);135} else if (stream.match(idents) || stream.match(types) ||136stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) {137return "atom";138}139stream.eat(":");140return "operator";141}142
143// Strings144if (stream.eat("\"")) {145return chain(tokenQuote("\"", "string", true), stream, state);146}147
148// Strings or regexps or macro variables or '%' operator149if (stream.peek() == "%") {150var style = "string";151var embed = true;152var delim;153
154if (stream.match("%r")) {155// Regexps156style = "string-2";157delim = stream.next();158} else if (stream.match("%w")) {159embed = false;160delim = stream.next();161} else if (stream.match("%q")) {162embed = false;163delim = stream.next();164} else {165if(delim = stream.match(/^%([^\w\s=])/)) {166delim = delim[1];167} else if (stream.match(/^%[a-zA-Z_\u009F-\uFFFF][\w\u009F-\uFFFF]*/)) {168// Macro variables169return "meta";170} else if (stream.eat('%')) {171// '%' operator172return "operator";173}174}175
176if (matching.hasOwnProperty(delim)) {177delim = matching[delim];178}179return chain(tokenQuote(delim, style, embed), stream, state);180}181
182// Here Docs183if (matched = stream.match(/^<<-('?)([A-Z]\w*)\1/)) {184return chain(tokenHereDoc(matched[2], !matched[1]), stream, state)185}186
187// Characters188if (stream.eat("'")) {189stream.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/);190stream.eat("'");191return "atom";192}193
194// Numbers195if (stream.eat("0")) {196if (stream.eat("x")) {197stream.match(/^[0-9a-fA-F_]+/);198} else if (stream.eat("o")) {199stream.match(/^[0-7_]+/);200} else if (stream.eat("b")) {201stream.match(/^[01_]+/);202}203return "number";204}205
206if (stream.eat(/^\d/)) {207stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?/);208return "number";209}210
211// Operators212if (stream.match(operators)) {213stream.eat("="); // Operators can follow assign symbol.214return "operator";215}216
217if (stream.match(conditionalOperators) || stream.match(anotherOperators)) {218return "operator";219}220
221// Parens and braces222if (matched = stream.match(/[({[]/, false)) {223matched = matched[0];224return chain(tokenNest(matched, matching[matched], null), stream, state);225}226
227// Escapes228if (stream.eat("\\")) {229stream.next();230return "meta";231}232
233stream.next();234return null;235}236
237function tokenNest(begin, end, style, started) {238return function (stream, state) {239if (!started && stream.match(begin)) {240state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true);241state.currentIndent += 1;242return style;243}244
245var nextStyle = tokenBase(stream, state);246if (stream.current() === end) {247state.tokenize.pop();248state.currentIndent -= 1;249nextStyle = style;250}251
252return nextStyle;253};254}255
256function tokenMacro(begin, end, started) {257return function (stream, state) {258if (!started && stream.match("{" + begin)) {259state.currentIndent += 1;260state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true);261return "meta";262}263
264if (stream.match(end + "}")) {265state.currentIndent -= 1;266state.tokenize.pop();267return "meta";268}269
270return tokenBase(stream, state);271};272}273
274function tokenMacroDef(stream, state) {275if (stream.eatSpace()) {276return null;277}278
279var matched;280if (matched = stream.match(idents)) {281if (matched == "def") {282return "keyword";283}284stream.eat(/[?!]/);285}286
287state.tokenize.pop();288return "def";289}290
291function tokenFollowIdent(stream, state) {292if (stream.eatSpace()) {293return null;294}295
296if (stream.match(idents)) {297stream.eat(/[!?]/);298} else {299stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators);300}301state.tokenize.pop();302return "def";303}304
305function tokenFollowType(stream, state) {306if (stream.eatSpace()) {307return null;308}309
310stream.match(types);311state.tokenize.pop();312return "def";313}314
315function tokenQuote(end, style, embed) {316return function (stream, state) {317var escaped = false;318
319while (stream.peek()) {320if (!escaped) {321if (stream.match("{%", false)) {322state.tokenize.push(tokenMacro("%", "%"));323return style;324}325
326if (stream.match("{{", false)) {327state.tokenize.push(tokenMacro("{", "}"));328return style;329}330
331if (embed && stream.match("#{", false)) {332state.tokenize.push(tokenNest("#{", "}", "meta"));333return style;334}335
336var ch = stream.next();337
338if (ch == end) {339state.tokenize.pop();340return style;341}342
343escaped = embed && ch == "\\";344} else {345stream.next();346escaped = false;347}348}349
350return style;351};352}353
354function tokenHereDoc(phrase, embed) {355return function (stream, state) {356if (stream.sol()) {357stream.eatSpace()358if (stream.match(phrase)) {359state.tokenize.pop();360return "string";361}362}363
364var escaped = false;365while (stream.peek()) {366if (!escaped) {367if (stream.match("{%", false)) {368state.tokenize.push(tokenMacro("%", "%"));369return "string";370}371
372if (stream.match("{{", false)) {373state.tokenize.push(tokenMacro("{", "}"));374return "string";375}376
377if (embed && stream.match("#{", false)) {378state.tokenize.push(tokenNest("#{", "}", "meta"));379return "string";380}381
382escaped = embed && stream.next() == "\\";383} else {384stream.next();385escaped = false;386}387}388
389return "string";390}391}392
393return {394startState: function () {395return {396tokenize: [tokenBase],397currentIndent: 0,398lastToken: null,399lastStyle: null,400blocks: []401};402},403
404token: function (stream, state) {405var style = state.tokenize[state.tokenize.length - 1](stream, state);406var token = stream.current();407
408if (style && style != "comment") {409state.lastToken = token;410state.lastStyle = style;411}412
413return style;414},415
416indent: function (state, textAfter) {417textAfter = textAfter.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g, "");418
419if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) {420return config.indentUnit * (state.currentIndent - 1);421}422
423return config.indentUnit * state.currentIndent;424},425
426fold: "indent",427electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true),428lineComment: '#'429};430});431
432CodeMirror.defineMIME("text/x-crystal", "crystal");433});434