File modules/editor/codemirror/mode/julia/julia.js

Last commit: Sun Dec 17 01:14:09 2017 +0100	Jan Dankert	Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://codemirror.net/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("julia", function(config, parserConf) { 15 function wordRegexp(words, end) { 16 if (typeof end === "undefined") { end = "\\b"; } 17 return new RegExp("^((" + words.join(")|(") + "))" + end); 18 } 19 20 var octChar = "\\\\[0-7]{1,3}"; 21 var hexChar = "\\\\x[A-Fa-f0-9]{1,2}"; 22 var sChar = "\\\\[abefnrtv0%?'\"\\\\]"; 23 var uChar = "([^\\u0027\\u005C\\uD800-\\uDFFF]|[\\uD800-\\uDFFF][\\uDC00-\\uDFFF])"; 24 25 var operators = parserConf.operators || wordRegexp([ 26 "[<>]:", "[<>=]=", "<<=?", ">>>?=?", "=>", "->", "\\/\\/", 27 "[\\\\%*+\\-<>!=\\/^|&\\u00F7\\u22BB]=?", "\\?", "\\$", "~", ":", 28 "\\u00D7", "\\u2208", "\\u2209", "\\u220B", "\\u220C", "\\u2218", 29 "\\u221A", "\\u221B", "\\u2229", "\\u222A", "\\u2260", "\\u2264", 30 "\\u2265", "\\u2286", "\\u2288", "\\u228A", "\\u22C5", 31 "\\b(in|isa)\\b(?!\.?\\()"], ""); 32 var delimiters = parserConf.delimiters || /^[;,()[\]{}]/; 33 var identifiers = parserConf.identifiers || 34 /^[_A-Za-z\u00A1-\u2217\u2219-\uFFFF][\w\u00A1-\u2217\u2219-\uFFFF]*!*/; 35 36 var chars = wordRegexp([octChar, hexChar, sChar, uChar], "'"); 37 var openers = wordRegexp(["begin", "function", "type", "struct", "immutable", 38 "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", 39 "finally", "catch", "do"]); 40 var closers = wordRegexp(["end", "else", "elseif", "catch", "finally"]); 41 var keywords = wordRegexp(["if", "else", "elseif", "while", "for", "begin", 42 "let", "end", "do", "try", "catch", "finally", "return", "break", 43 "continue", "global", "local", "const", "export", "import", "importall", 44 "using", "function", "where", "macro", "module", "baremodule", "struct", 45 "type", "mutable", "immutable", "quote", "typealias", "abstract", 46 "primitive", "bitstype"]); 47 var builtins = wordRegexp(["true", "false", "nothing", "NaN", "Inf"]); 48 49 var macro = /^@[_A-Za-z][\w]*/; 50 var symbol = /^:[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/; 51 var stringPrefixes = /^(`|([_A-Za-z\u00A1-\uFFFF]*"("")?))/; 52 53 function inArray(state) { 54 return inGenerator(state, '[') 55 } 56 57 function inGenerator(state, bracket) { 58 var curr = currentScope(state), 59 prev = currentScope(state, 1); 60 if (typeof(bracket) === "undefined") { bracket = '('; } 61 if (curr === bracket || (prev === bracket && curr === "for")) { 62 return true; 63 } 64 return false; 65 } 66 67 function currentScope(state, n) { 68 if (typeof(n) === "undefined") { n = 0; } 69 if (state.scopes.length <= n) { 70 return null; 71 } 72 return state.scopes[state.scopes.length - (n + 1)]; 73 } 74 75 // tokenizers 76 function tokenBase(stream, state) { 77 // Handle multiline comments 78 if (stream.match(/^#=/, false)) { 79 state.tokenize = tokenComment; 80 return state.tokenize(stream, state); 81 } 82 83 // Handle scope changes 84 var leavingExpr = state.leavingExpr; 85 if (stream.sol()) { 86 leavingExpr = false; 87 } 88 state.leavingExpr = false; 89 90 if (leavingExpr) { 91 if (stream.match(/^'+/)) { 92 return "operator"; 93 } 94 } 95 96 if (stream.match(/\.{4,}/)) { 97 return "error"; 98 } else if (stream.match(/\.{1,3}/)) { 99 return "operator"; 100 } 101 102 if (stream.eatSpace()) { 103 return null; 104 } 105 106 var ch = stream.peek(); 107 108 // Handle single line comments 109 if (ch === '#') { 110 stream.skipToEnd(); 111 return "comment"; 112 } 113 114 if (ch === '[') { 115 state.scopes.push('['); 116 } 117 118 if (ch === '(') { 119 state.scopes.push('('); 120 } 121 122 var scope = currentScope(state); 123 124 if (inArray(state) && ch === ']') { 125 if (scope === "for") { state.scopes.pop(); } 126 state.scopes.pop(); 127 state.leavingExpr = true; 128 } 129 130 if (inGenerator(state) && ch === ')') { 131 if (scope === "for") { state.scopes.pop(); } 132 state.scopes.pop(); 133 state.leavingExpr = true; 134 } 135 136 if (inArray(state)) { 137 if (state.lastToken == "end" && stream.match(/^:/)) { 138 return "operator"; 139 } 140 if (stream.match(/^end/)) { 141 return "number"; 142 } 143 } 144 145 var match; 146 if (match = stream.match(openers, false)) { 147 state.scopes.push(match[0]); 148 } 149 150 if (stream.match(closers, false)) { 151 state.scopes.pop(); 152 } 153 154 // Handle type annotations 155 if (stream.match(/^::(?![:\$])/)) { 156 state.tokenize = tokenAnnotation; 157 return state.tokenize(stream, state); 158 } 159 160 // Handle symbols 161 if (!leavingExpr && stream.match(symbol) || 162 stream.match(/:([<>]:|<<=?|>>>?=?|->|\/\/|\.{2,3}|[\.\\%*+\-<>!\/^|&]=?|[~\?\$])/)) { 163 return "builtin"; 164 } 165 166 // Handle parametric types 167 //if (stream.match(/^{[^}]*}(?=\()/)) { 168 // return "builtin"; 169 //} 170 171 // Handle operators and Delimiters 172 if (stream.match(operators)) { 173 return "operator"; 174 } 175 176 // Handle Number Literals 177 if (stream.match(/^\.?\d/, false)) { 178 var imMatcher = RegExp(/^im\b/); 179 var numberLiteral = false; 180 // Floats 181 if (stream.match(/^\d*\.(?!\.)\d*([Eef][\+\-]?\d+)?/i)) { numberLiteral = true; } 182 if (stream.match(/^\d+\.(?!\.)\d*/)) { numberLiteral = true; } 183 if (stream.match(/^\.\d+/)) { numberLiteral = true; } 184 if (stream.match(/^0x\.[0-9a-f]+p[\+\-]?\d+/i)) { numberLiteral = true; } 185 // Integers 186 if (stream.match(/^0x[0-9a-f]+/i)) { numberLiteral = true; } // Hex 187 if (stream.match(/^0b[01]+/i)) { numberLiteral = true; } // Binary 188 if (stream.match(/^0o[0-7]+/i)) { numberLiteral = true; } // Octal 189 if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { numberLiteral = true; } // Decimal 190 // Zero by itself with no other piece of number. 191 if (stream.match(/^0(?![\dx])/i)) { numberLiteral = true; } 192 if (numberLiteral) { 193 // Integer literals may be "long" 194 stream.match(imMatcher); 195 state.leavingExpr = true; 196 return "number"; 197 } 198 } 199 200 // Handle Chars 201 if (stream.match(/^'/)) { 202 state.tokenize = tokenChar; 203 return state.tokenize(stream, state); 204 } 205 206 // Handle Strings 207 if (stream.match(stringPrefixes)) { 208 state.tokenize = tokenStringFactory(stream.current()); 209 return state.tokenize(stream, state); 210 } 211 212 if (stream.match(macro)) { 213 return "meta"; 214 } 215 216 if (stream.match(delimiters)) { 217 return null; 218 } 219 220 if (stream.match(keywords)) { 221 return "keyword"; 222 } 223 224 if (stream.match(builtins)) { 225 return "builtin"; 226 } 227 228 var isDefinition = state.isDefinition || state.lastToken == "function" || 229 state.lastToken == "macro" || state.lastToken == "type" || 230 state.lastToken == "struct" || state.lastToken == "immutable"; 231 232 if (stream.match(identifiers)) { 233 if (isDefinition) { 234 if (stream.peek() === '.') { 235 state.isDefinition = true; 236 return "variable"; 237 } 238 state.isDefinition = false; 239 return "def"; 240 } 241 if (stream.match(/^({[^}]*})*\(/, false)) { 242 state.tokenize = tokenCallOrDef; 243 return state.tokenize(stream, state); 244 } 245 state.leavingExpr = true; 246 return "variable"; 247 } 248 249 // Handle non-detected items 250 stream.next(); 251 return "error"; 252 } 253 254 function tokenCallOrDef(stream, state) { 255 var match = stream.match(/^(\(\s*)/); 256 if (match) { 257 if (state.firstParenPos < 0) 258 state.firstParenPos = state.scopes.length; 259 state.scopes.push('('); 260 state.charsAdvanced += match[1].length; 261 } 262 if (currentScope(state) == '(' && stream.match(/^\)/)) { 263 state.scopes.pop(); 264 state.charsAdvanced += 1; 265 if (state.scopes.length <= state.firstParenPos) { 266 var isDefinition = stream.match(/^(\s*where\s+[^\s=]+)*\s*?=(?!=)/, false); 267 stream.backUp(state.charsAdvanced); 268 state.firstParenPos = -1; 269 state.charsAdvanced = 0; 270 state.tokenize = tokenBase; 271 if (isDefinition) 272 return "def"; 273 return "builtin"; 274 } 275 } 276 // Unfortunately javascript does not support multiline strings, so we have 277 // to undo anything done upto here if a function call or definition splits 278 // over two or more lines. 279 if (stream.match(/^$/g, false)) { 280 stream.backUp(state.charsAdvanced); 281 while (state.scopes.length > state.firstParenPos) 282 state.scopes.pop(); 283 state.firstParenPos = -1; 284 state.charsAdvanced = 0; 285 state.tokenize = tokenBase; 286 return "builtin"; 287 } 288 state.charsAdvanced += stream.match(/^([^()]*)/)[1].length; 289 return state.tokenize(stream, state); 290 } 291 292 function tokenAnnotation(stream, state) { 293 stream.match(/.*?(?=,|;|{|}|\(|\)|=|$|\s)/); 294 if (stream.match(/^{/)) { 295 state.nestedLevels++; 296 } else if (stream.match(/^}/)) { 297 state.nestedLevels--; 298 } 299 if (state.nestedLevels > 0) { 300 stream.match(/.*?(?={|})/) || stream.next(); 301 } else if (state.nestedLevels == 0) { 302 state.tokenize = tokenBase; 303 } 304 return "builtin"; 305 } 306 307 function tokenComment(stream, state) { 308 if (stream.match(/^#=/)) { 309 state.nestedLevels++; 310 } 311 if (!stream.match(/.*?(?=(#=|=#))/)) { 312 stream.skipToEnd(); 313 } 314 if (stream.match(/^=#/)) { 315 state.nestedLevels--; 316 if (state.nestedLevels == 0) 317 state.tokenize = tokenBase; 318 } 319 return "comment"; 320 } 321 322 function tokenChar(stream, state) { 323 var isChar = false, match; 324 if (stream.match(chars)) { 325 isChar = true; 326 } else if (match = stream.match(/\\u([a-f0-9]{1,4})(?=')/i)) { 327 var value = parseInt(match[1], 16); 328 if (value <= 55295 || value >= 57344) { // (U+0,U+D7FF), (U+E000,U+FFFF) 329 isChar = true; 330 stream.next(); 331 } 332 } else if (match = stream.match(/\\U([A-Fa-f0-9]{5,8})(?=')/)) { 333 var value = parseInt(match[1], 16); 334 if (value <= 1114111) { // U+10FFFF 335 isChar = true; 336 stream.next(); 337 } 338 } 339 if (isChar) { 340 state.leavingExpr = true; 341 state.tokenize = tokenBase; 342 return "string"; 343 } 344 if (!stream.match(/^[^']+(?=')/)) { stream.skipToEnd(); } 345 if (stream.match(/^'/)) { state.tokenize = tokenBase; } 346 return "error"; 347 } 348 349 function tokenStringFactory(delimiter) { 350 if (delimiter.substr(-3) === '"""') { 351 delimiter = '"""'; 352 } else if (delimiter.substr(-1) === '"') { 353 delimiter = '"'; 354 } 355 function tokenString(stream, state) { 356 if (stream.eat('\\')) { 357 stream.next(); 358 } else if (stream.match(delimiter)) { 359 state.tokenize = tokenBase; 360 state.leavingExpr = true; 361 return "string"; 362 } else { 363 stream.eat(/[`"]/); 364 } 365 stream.eatWhile(/[^\\`"]/); 366 return "string"; 367 } 368 return tokenString; 369 } 370 371 var external = { 372 startState: function() { 373 return { 374 tokenize: tokenBase, 375 scopes: [], 376 lastToken: null, 377 leavingExpr: false, 378 isDefinition: false, 379 nestedLevels: 0, 380 charsAdvanced: 0, 381 firstParenPos: -1 382 }; 383 }, 384 385 token: function(stream, state) { 386 var style = state.tokenize(stream, state); 387 var current = stream.current(); 388 389 if (current && style) { 390 state.lastToken = current; 391 } 392 393 return style; 394 }, 395 396 indent: function(state, textAfter) { 397 var delta = 0; 398 if ( textAfter === ']' || textAfter === ')' || textAfter === "end" || 399 textAfter === "else" || textAfter === "catch" || textAfter === "elseif" || 400 textAfter === "finally" ) { 401 delta = -1; 402 } 403 return (state.scopes.length + delta) * config.indentUnit; 404 }, 405 406 electricInput: /\b(end|else|catch|finally)\b/, 407 blockCommentStart: "#=", 408 blockCommentEnd: "=#", 409 lineComment: "#", 410 fold: "indent" 411 }; 412 return external; 413 }); 414 415 416 CodeMirror.defineMIME("text/x-julia", "julia"); 417 418 });
Download modules/editor/codemirror/mode/julia/julia.js
History Sun, 17 Dec 2017 01:14:09 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.