File modules/editor/codemirror/mode/oz/oz.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("oz", function (conf) { 15 16 function wordRegexp(words) { 17 return new RegExp("^((" + words.join(")|(") + "))\\b"); 18 } 19 20 var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/; 21 var doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/; 22 var tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/; 23 24 var middle = ["in", "then", "else", "of", "elseof", "elsecase", "elseif", "catch", 25 "finally", "with", "require", "prepare", "import", "export", "define", "do"]; 26 var end = ["end"]; 27 28 var atoms = wordRegexp(["true", "false", "nil", "unit"]); 29 var commonKeywords = wordRegexp(["andthen", "at", "attr", "declare", "feat", "from", "lex", 30 "mod", "div", "mode", "orelse", "parser", "prod", "prop", "scanner", "self", "syn", "token"]); 31 var openingKeywords = wordRegexp(["local", "proc", "fun", "case", "class", "if", "cond", "or", "dis", 32 "choice", "not", "thread", "try", "raise", "lock", "for", "suchthat", "meth", "functor"]); 33 var middleKeywords = wordRegexp(middle); 34 var endKeywords = wordRegexp(end); 35 36 // Tokenizers 37 function tokenBase(stream, state) { 38 if (stream.eatSpace()) { 39 return null; 40 } 41 42 // Brackets 43 if(stream.match(/[{}]/)) { 44 return "bracket"; 45 } 46 47 // Special [] keyword 48 if (stream.match(/(\[])/)) { 49 return "keyword" 50 } 51 52 // Operators 53 if (stream.match(tripleOperators) || stream.match(doubleOperators)) { 54 return "operator"; 55 } 56 57 // Atoms 58 if(stream.match(atoms)) { 59 return 'atom'; 60 } 61 62 // Opening keywords 63 var matched = stream.match(openingKeywords); 64 if (matched) { 65 if (!state.doInCurrentLine) 66 state.currentIndent++; 67 else 68 state.doInCurrentLine = false; 69 70 // Special matching for signatures 71 if(matched[0] == "proc" || matched[0] == "fun") 72 state.tokenize = tokenFunProc; 73 else if(matched[0] == "class") 74 state.tokenize = tokenClass; 75 else if(matched[0] == "meth") 76 state.tokenize = tokenMeth; 77 78 return 'keyword'; 79 } 80 81 // Middle and other keywords 82 if (stream.match(middleKeywords) || stream.match(commonKeywords)) { 83 return "keyword" 84 } 85 86 // End keywords 87 if (stream.match(endKeywords)) { 88 state.currentIndent--; 89 return 'keyword'; 90 } 91 92 // Eat the next char for next comparisons 93 var ch = stream.next(); 94 95 // Strings 96 if (ch == '"' || ch == "'") { 97 state.tokenize = tokenString(ch); 98 return state.tokenize(stream, state); 99 } 100 101 // Numbers 102 if (/[~\d]/.test(ch)) { 103 if (ch == "~") { 104 if(! /^[0-9]/.test(stream.peek())) 105 return null; 106 else if (( stream.next() == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/)) 107 return "number"; 108 } 109 110 if ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/)) 111 return "number"; 112 113 return null; 114 } 115 116 // Comments 117 if (ch == "%") { 118 stream.skipToEnd(); 119 return 'comment'; 120 } 121 else if (ch == "/") { 122 if (stream.eat("*")) { 123 state.tokenize = tokenComment; 124 return tokenComment(stream, state); 125 } 126 } 127 128 // Single operators 129 if(singleOperators.test(ch)) { 130 return "operator"; 131 } 132 133 // If nothing match, we skip the entire alphanumerical block 134 stream.eatWhile(/\w/); 135 136 return "variable"; 137 } 138 139 function tokenClass(stream, state) { 140 if (stream.eatSpace()) { 141 return null; 142 } 143 stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/); 144 state.tokenize = tokenBase; 145 return "variable-3" 146 } 147 148 function tokenMeth(stream, state) { 149 if (stream.eatSpace()) { 150 return null; 151 } 152 stream.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/); 153 state.tokenize = tokenBase; 154 return "def" 155 } 156 157 function tokenFunProc(stream, state) { 158 if (stream.eatSpace()) { 159 return null; 160 } 161 162 if(!state.hasPassedFirstStage && stream.eat("{")) { 163 state.hasPassedFirstStage = true; 164 return "bracket"; 165 } 166 else if(state.hasPassedFirstStage) { 167 stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/); 168 state.hasPassedFirstStage = false; 169 state.tokenize = tokenBase; 170 return "def" 171 } 172 else { 173 state.tokenize = tokenBase; 174 return null; 175 } 176 } 177 178 function tokenComment(stream, state) { 179 var maybeEnd = false, ch; 180 while (ch = stream.next()) { 181 if (ch == "/" && maybeEnd) { 182 state.tokenize = tokenBase; 183 break; 184 } 185 maybeEnd = (ch == "*"); 186 } 187 return "comment"; 188 } 189 190 function tokenString(quote) { 191 return function (stream, state) { 192 var escaped = false, next, end = false; 193 while ((next = stream.next()) != null) { 194 if (next == quote && !escaped) { 195 end = true; 196 break; 197 } 198 escaped = !escaped && next == "\\"; 199 } 200 if (end || !escaped) 201 state.tokenize = tokenBase; 202 return "string"; 203 }; 204 } 205 206 function buildElectricInputRegEx() { 207 // Reindentation should occur on [] or on a match of any of 208 // the block closing keywords, at the end of a line. 209 var allClosings = middle.concat(end); 210 return new RegExp("[\\[\\]]|(" + allClosings.join("|") + ")$"); 211 } 212 213 return { 214 215 startState: function () { 216 return { 217 tokenize: tokenBase, 218 currentIndent: 0, 219 doInCurrentLine: false, 220 hasPassedFirstStage: false 221 }; 222 }, 223 224 token: function (stream, state) { 225 if (stream.sol()) 226 state.doInCurrentLine = 0; 227 228 return state.tokenize(stream, state); 229 }, 230 231 indent: function (state, textAfter) { 232 var trueText = textAfter.replace(/^\s+|\s+$/g, ''); 233 234 if (trueText.match(endKeywords) || trueText.match(middleKeywords) || trueText.match(/(\[])/)) 235 return conf.indentUnit * (state.currentIndent - 1); 236 237 if (state.currentIndent < 0) 238 return 0; 239 240 return state.currentIndent * conf.indentUnit; 241 }, 242 fold: "indent", 243 electricInput: buildElectricInputRegEx(), 244 lineComment: "%", 245 blockCommentStart: "/*", 246 blockCommentEnd: "*/" 247 }; 248 }); 249 250 CodeMirror.defineMIME("text/x-oz", "oz"); 251 252 });
Download modules/editor/codemirror/mode/oz/oz.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.