comparison .cms/lib/codemirror/mode/groovy/groovy.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:78edf6b517a0
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
14 CodeMirror.defineMode("groovy", function(config) {
15 function words(str) {
16 var obj = {}, words = str.split(" ");
17 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
18 return obj;
19 }
20 var keywords = words(
21 "abstract as assert boolean break byte case catch char class const continue def default " +
22 "do double else enum extends final finally float for goto if implements import in " +
23 "instanceof int interface long native new package private protected public return " +
24 "short static strictfp super switch synchronized threadsafe throw throws trait transient " +
25 "try void volatile while");
26 var blockKeywords = words("catch class def do else enum finally for if interface switch trait try while");
27 var standaloneKeywords = words("return break continue");
28 var atoms = words("null true false this");
29
30 var curPunc;
31 function tokenBase(stream, state) {
32 var ch = stream.next();
33 if (ch == '"' || ch == "'") {
34 return startString(ch, stream, state);
35 }
36 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
37 curPunc = ch;
38 return null;
39 }
40 if (/\d/.test(ch)) {
41 stream.eatWhile(/[\w\.]/);
42 if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
43 return "number";
44 }
45 if (ch == "/") {
46 if (stream.eat("*")) {
47 state.tokenize.push(tokenComment);
48 return tokenComment(stream, state);
49 }
50 if (stream.eat("/")) {
51 stream.skipToEnd();
52 return "comment";
53 }
54 if (expectExpression(state.lastToken, false)) {
55 return startString(ch, stream, state);
56 }
57 }
58 if (ch == "-" && stream.eat(">")) {
59 curPunc = "->";
60 return null;
61 }
62 if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
63 stream.eatWhile(/[+\-*&%=<>|~]/);
64 return "operator";
65 }
66 stream.eatWhile(/[\w\$_]/);
67 if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
68 if (state.lastToken == ".") return "property";
69 if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
70 var cur = stream.current();
71 if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
72 if (keywords.propertyIsEnumerable(cur)) {
73 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
74 else if (standaloneKeywords.propertyIsEnumerable(cur)) curPunc = "standalone";
75 return "keyword";
76 }
77 return "variable";
78 }
79 tokenBase.isBase = true;
80
81 function startString(quote, stream, state) {
82 var tripleQuoted = false;
83 if (quote != "/" && stream.eat(quote)) {
84 if (stream.eat(quote)) tripleQuoted = true;
85 else return "string";
86 }
87 function t(stream, state) {
88 var escaped = false, next, end = !tripleQuoted;
89 while ((next = stream.next()) != null) {
90 if (next == quote && !escaped) {
91 if (!tripleQuoted) { break; }
92 if (stream.match(quote + quote)) { end = true; break; }
93 }
94 if (quote == '"' && next == "$" && !escaped) {
95 if (stream.eat("{")) {
96 state.tokenize.push(tokenBaseUntilBrace());
97 return "string";
98 } else if (stream.match(/^\w/, false)) {
99 state.tokenize.push(tokenVariableDeref);
100 return "string";
101 }
102 }
103 escaped = !escaped && next == "\\";
104 }
105 if (end) state.tokenize.pop();
106 return "string";
107 }
108 state.tokenize.push(t);
109 return t(stream, state);
110 }
111
112 function tokenBaseUntilBrace() {
113 var depth = 1;
114 function t(stream, state) {
115 if (stream.peek() == "}") {
116 depth--;
117 if (depth == 0) {
118 state.tokenize.pop();
119 return state.tokenize[state.tokenize.length-1](stream, state);
120 }
121 } else if (stream.peek() == "{") {
122 depth++;
123 }
124 return tokenBase(stream, state);
125 }
126 t.isBase = true;
127 return t;
128 }
129
130 function tokenVariableDeref(stream, state) {
131 var next = stream.match(/^(\.|[\w\$_]+)/)
132 if (!next || !stream.match(next[0] == "." ? /^[\w$_]/ : /^\./)) state.tokenize.pop()
133 if (!next) return state.tokenize[state.tokenize.length-1](stream, state)
134 return next[0] == "." ? null : "variable"
135 }
136
137 function tokenComment(stream, state) {
138 var maybeEnd = false, ch;
139 while (ch = stream.next()) {
140 if (ch == "/" && maybeEnd) {
141 state.tokenize.pop();
142 break;
143 }
144 maybeEnd = (ch == "*");
145 }
146 return "comment";
147 }
148
149 function expectExpression(last, newline) {
150 return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
151 last == "newstatement" || last == "keyword" || last == "proplabel" ||
152 (last == "standalone" && !newline);
153 }
154
155 function Context(indented, column, type, align, prev) {
156 this.indented = indented;
157 this.column = column;
158 this.type = type;
159 this.align = align;
160 this.prev = prev;
161 }
162 function pushContext(state, col, type) {
163 return state.context = new Context(state.indented, col, type, null, state.context);
164 }
165 function popContext(state) {
166 var t = state.context.type;
167 if (t == ")" || t == "]" || t == "}")
168 state.indented = state.context.indented;
169 return state.context = state.context.prev;
170 }
171
172 // Interface
173
174 return {
175 startState: function(basecolumn) {
176 return {
177 tokenize: [tokenBase],
178 context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
179 indented: 0,
180 startOfLine: true,
181 lastToken: null
182 };
183 },
184
185 token: function(stream, state) {
186 var ctx = state.context;
187 if (stream.sol()) {
188 if (ctx.align == null) ctx.align = false;
189 state.indented = stream.indentation();
190 state.startOfLine = true;
191 // Automatic semicolon insertion
192 if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) {
193 popContext(state); ctx = state.context;
194 }
195 }
196 if (stream.eatSpace()) return null;
197 curPunc = null;
198 var style = state.tokenize[state.tokenize.length-1](stream, state);
199 if (style == "comment") return style;
200 if (ctx.align == null) ctx.align = true;
201
202 if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
203 // Handle indentation for {x -> \n ... }
204 else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
205 popContext(state);
206 state.context.align = false;
207 }
208 else if (curPunc == "{") pushContext(state, stream.column(), "}");
209 else if (curPunc == "[") pushContext(state, stream.column(), "]");
210 else if (curPunc == "(") pushContext(state, stream.column(), ")");
211 else if (curPunc == "}") {
212 while (ctx.type == "statement") ctx = popContext(state);
213 if (ctx.type == "}") ctx = popContext(state);
214 while (ctx.type == "statement") ctx = popContext(state);
215 }
216 else if (curPunc == ctx.type) popContext(state);
217 else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
218 pushContext(state, stream.column(), "statement");
219 state.startOfLine = false;
220 state.lastToken = curPunc || style;
221 return style;
222 },
223
224 indent: function(state, textAfter) {
225 if (!state.tokenize[state.tokenize.length-1].isBase) return CodeMirror.Pass;
226 var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
227 if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) ctx = ctx.prev;
228 var closing = firstChar == ctx.type;
229 if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
230 else if (ctx.align) return ctx.column + (closing ? 0 : 1);
231 else return ctx.indented + (closing ? 0 : config.indentUnit);
232 },
233
234 electricChars: "{}",
235 closeBrackets: {triples: "'\""},
236 fold: "brace",
237 blockCommentStart: "/*",
238 blockCommentEnd: "*/",
239 lineComment: "//"
240 };
241 });
242
243 CodeMirror.defineMIME("text/x-groovy", "groovy");
244
245 });