File modules/editor/codemirror/mode/stex/stex.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 /* 5 * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de) 6 * Licence: MIT 7 */ 8 9 (function(mod) { 10 if (typeof exports == "object" && typeof module == "object") // CommonJS 11 mod(require("../../lib/codemirror")); 12 else if (typeof define == "function" && define.amd) // AMD 13 define(["../../lib/codemirror"], mod); 14 else // Plain browser env 15 mod(CodeMirror); 16 })(function(CodeMirror) { 17 "use strict"; 18 19 CodeMirror.defineMode("stex", function() { 20 "use strict"; 21 22 function pushCommand(state, command) { 23 state.cmdState.push(command); 24 } 25 26 function peekCommand(state) { 27 if (state.cmdState.length > 0) { 28 return state.cmdState[state.cmdState.length - 1]; 29 } else { 30 return null; 31 } 32 } 33 34 function popCommand(state) { 35 var plug = state.cmdState.pop(); 36 if (plug) { 37 plug.closeBracket(); 38 } 39 } 40 41 // returns the non-default plugin closest to the end of the list 42 function getMostPowerful(state) { 43 var context = state.cmdState; 44 for (var i = context.length - 1; i >= 0; i--) { 45 var plug = context[i]; 46 if (plug.name == "DEFAULT") { 47 continue; 48 } 49 return plug; 50 } 51 return { styleIdentifier: function() { return null; } }; 52 } 53 54 function addPluginPattern(pluginName, cmdStyle, styles) { 55 return function () { 56 this.name = pluginName; 57 this.bracketNo = 0; 58 this.style = cmdStyle; 59 this.styles = styles; 60 this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin 61 62 this.styleIdentifier = function() { 63 return this.styles[this.bracketNo - 1] || null; 64 }; 65 this.openBracket = function() { 66 this.bracketNo++; 67 return "bracket"; 68 }; 69 this.closeBracket = function() {}; 70 }; 71 } 72 73 var plugins = {}; 74 75 plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]); 76 plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]); 77 plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]); 78 plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]); 79 plugins["end"] = addPluginPattern("end", "tag", ["atom"]); 80 81 plugins["DEFAULT"] = function () { 82 this.name = "DEFAULT"; 83 this.style = "tag"; 84 85 this.styleIdentifier = this.openBracket = this.closeBracket = function() {}; 86 }; 87 88 function setState(state, f) { 89 state.f = f; 90 } 91 92 // called when in a normal (no environment) context 93 function normal(source, state) { 94 var plug; 95 // Do we look like '\command' ? If so, attempt to apply the plugin 'command' 96 if (source.match(/^\\[a-zA-Z@]+/)) { 97 var cmdName = source.current().slice(1); 98 plug = plugins[cmdName] || plugins["DEFAULT"]; 99 plug = new plug(); 100 pushCommand(state, plug); 101 setState(state, beginParams); 102 return plug.style; 103 } 104 105 // escape characters 106 if (source.match(/^\\[$&%#{}_]/)) { 107 return "tag"; 108 } 109 110 // white space control characters 111 if (source.match(/^\\[,;!\/\\]/)) { 112 return "tag"; 113 } 114 115 // find if we're starting various math modes 116 if (source.match("\\[")) { 117 setState(state, function(source, state){ return inMathMode(source, state, "\\]"); }); 118 return "keyword"; 119 } 120 if (source.match("$$")) { 121 setState(state, function(source, state){ return inMathMode(source, state, "$$"); }); 122 return "keyword"; 123 } 124 if (source.match("$")) { 125 setState(state, function(source, state){ return inMathMode(source, state, "$"); }); 126 return "keyword"; 127 } 128 129 var ch = source.next(); 130 if (ch == "%") { 131 source.skipToEnd(); 132 return "comment"; 133 } else if (ch == '}' || ch == ']') { 134 plug = peekCommand(state); 135 if (plug) { 136 plug.closeBracket(ch); 137 setState(state, beginParams); 138 } else { 139 return "error"; 140 } 141 return "bracket"; 142 } else if (ch == '{' || ch == '[') { 143 plug = plugins["DEFAULT"]; 144 plug = new plug(); 145 pushCommand(state, plug); 146 return "bracket"; 147 } else if (/\d/.test(ch)) { 148 source.eatWhile(/[\w.%]/); 149 return "atom"; 150 } else { 151 source.eatWhile(/[\w\-_]/); 152 plug = getMostPowerful(state); 153 if (plug.name == 'begin') { 154 plug.argument = source.current(); 155 } 156 return plug.styleIdentifier(); 157 } 158 } 159 160 function inMathMode(source, state, endModeSeq) { 161 if (source.eatSpace()) { 162 return null; 163 } 164 if (source.match(endModeSeq)) { 165 setState(state, normal); 166 return "keyword"; 167 } 168 if (source.match(/^\\[a-zA-Z@]+/)) { 169 return "tag"; 170 } 171 if (source.match(/^[a-zA-Z]+/)) { 172 return "variable-2"; 173 } 174 // escape characters 175 if (source.match(/^\\[$&%#{}_]/)) { 176 return "tag"; 177 } 178 // white space control characters 179 if (source.match(/^\\[,;!\/]/)) { 180 return "tag"; 181 } 182 // special math-mode characters 183 if (source.match(/^[\^_&]/)) { 184 return "tag"; 185 } 186 // non-special characters 187 if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) { 188 return null; 189 } 190 if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) { 191 return "number"; 192 } 193 var ch = source.next(); 194 if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") { 195 return "bracket"; 196 } 197 198 if (ch == "%") { 199 source.skipToEnd(); 200 return "comment"; 201 } 202 return "error"; 203 } 204 205 function beginParams(source, state) { 206 var ch = source.peek(), lastPlug; 207 if (ch == '{' || ch == '[') { 208 lastPlug = peekCommand(state); 209 lastPlug.openBracket(ch); 210 source.eat(ch); 211 setState(state, normal); 212 return "bracket"; 213 } 214 if (/[ \t\r]/.test(ch)) { 215 source.eat(ch); 216 return null; 217 } 218 setState(state, normal); 219 popCommand(state); 220 221 return normal(source, state); 222 } 223 224 return { 225 startState: function() { 226 return { 227 cmdState: [], 228 f: normal 229 }; 230 }, 231 copyState: function(s) { 232 return { 233 cmdState: s.cmdState.slice(), 234 f: s.f 235 }; 236 }, 237 token: function(stream, state) { 238 return state.f(stream, state); 239 }, 240 blankLine: function(state) { 241 state.f = normal; 242 state.cmdState.length = 0; 243 }, 244 lineComment: "%" 245 }; 246 }); 247 248 CodeMirror.defineMIME("text/x-stex", "stex"); 249 CodeMirror.defineMIME("text/x-latex", "stex"); 250 251 });
Download modules/editor/codemirror/mode/stex/stex.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.