File modules/editor/codemirror/mode/r/r.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.registerHelper("wordChars", "r", /[\w.]/); 15 16 CodeMirror.defineMode("r", function(config) { 17 function wordObj(str) { 18 var words = str.split(" "), res = {}; 19 for (var i = 0; i < words.length; ++i) res[words[i]] = true; 20 return res; 21 } 22 var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); 23 var builtins = wordObj("list quote bquote eval return call parse deparse"); 24 var keywords = wordObj("if else repeat while function for in next break"); 25 var blockkeywords = wordObj("if else repeat while function for"); 26 var opChars = /[+\-*\/^<>=!&|~$:]/; 27 var curPunc; 28 29 function tokenBase(stream, state) { 30 curPunc = null; 31 var ch = stream.next(); 32 if (ch == "#") { 33 stream.skipToEnd(); 34 return "comment"; 35 } else if (ch == "0" && stream.eat("x")) { 36 stream.eatWhile(/[\da-f]/i); 37 return "number"; 38 } else if (ch == "." && stream.eat(/\d/)) { 39 stream.match(/\d*(?:e[+\-]?\d+)?/); 40 return "number"; 41 } else if (/\d/.test(ch)) { 42 stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); 43 return "number"; 44 } else if (ch == "'" || ch == '"') { 45 state.tokenize = tokenString(ch); 46 return "string"; 47 } else if (ch == "`") { 48 stream.match(/[^`]+`/); 49 return "variable-3"; 50 } else if (ch == "." && stream.match(/.[.\d]+/)) { 51 return "keyword"; 52 } else if (/[\w\.]/.test(ch) && ch != "_") { 53 stream.eatWhile(/[\w\.]/); 54 var word = stream.current(); 55 if (atoms.propertyIsEnumerable(word)) return "atom"; 56 if (keywords.propertyIsEnumerable(word)) { 57 // Block keywords start new blocks, except 'else if', which only starts 58 // one new block for the 'if', no block for the 'else'. 59 if (blockkeywords.propertyIsEnumerable(word) && 60 !stream.match(/\s*if(\s+|$)/, false)) 61 curPunc = "block"; 62 return "keyword"; 63 } 64 if (builtins.propertyIsEnumerable(word)) return "builtin"; 65 return "variable"; 66 } else if (ch == "%") { 67 if (stream.skipTo("%")) stream.next(); 68 return "operator variable-2"; 69 } else if ( 70 (ch == "<" && stream.eat("-")) || 71 (ch == "<" && stream.match("<-")) || 72 (ch == "-" && stream.match(/>>?/)) 73 ) { 74 return "operator arrow"; 75 } else if (ch == "=" && state.ctx.argList) { 76 return "arg-is"; 77 } else if (opChars.test(ch)) { 78 if (ch == "$") return "operator dollar"; 79 stream.eatWhile(opChars); 80 return "operator"; 81 } else if (/[\(\){}\[\];]/.test(ch)) { 82 curPunc = ch; 83 if (ch == ";") return "semi"; 84 return null; 85 } else { 86 return null; 87 } 88 } 89 90 function tokenString(quote) { 91 return function(stream, state) { 92 if (stream.eat("\\")) { 93 var ch = stream.next(); 94 if (ch == "x") stream.match(/^[a-f0-9]{2}/i); 95 else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); 96 else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); 97 else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); 98 else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); 99 return "string-2"; 100 } else { 101 var next; 102 while ((next = stream.next()) != null) { 103 if (next == quote) { state.tokenize = tokenBase; break; } 104 if (next == "\\") { stream.backUp(1); break; } 105 } 106 return "string"; 107 } 108 }; 109 } 110 111 var ALIGN_YES = 1, ALIGN_NO = 2, BRACELESS = 4 112 113 function push(state, type, stream) { 114 state.ctx = {type: type, 115 indent: state.indent, 116 flags: 0, 117 column: stream.column(), 118 prev: state.ctx}; 119 } 120 function setFlag(state, flag) { 121 var ctx = state.ctx 122 state.ctx = {type: ctx.type, 123 indent: ctx.indent, 124 flags: ctx.flags | flag, 125 column: ctx.column, 126 prev: ctx.prev} 127 } 128 function pop(state) { 129 state.indent = state.ctx.indent; 130 state.ctx = state.ctx.prev; 131 } 132 133 return { 134 startState: function() { 135 return {tokenize: tokenBase, 136 ctx: {type: "top", 137 indent: -config.indentUnit, 138 flags: ALIGN_NO}, 139 indent: 0, 140 afterIdent: false}; 141 }, 142 143 token: function(stream, state) { 144 if (stream.sol()) { 145 if ((state.ctx.flags & 3) == 0) state.ctx.flags |= ALIGN_NO 146 if (state.ctx.flags & BRACELESS) pop(state) 147 state.indent = stream.indentation(); 148 } 149 if (stream.eatSpace()) return null; 150 var style = state.tokenize(stream, state); 151 if (style != "comment" && (state.ctx.flags & ALIGN_NO) == 0) setFlag(state, ALIGN_YES) 152 153 if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && state.ctx.type == "block") pop(state); 154 if (curPunc == "{") push(state, "}", stream); 155 else if (curPunc == "(") { 156 push(state, ")", stream); 157 if (state.afterIdent) state.ctx.argList = true; 158 } 159 else if (curPunc == "[") push(state, "]", stream); 160 else if (curPunc == "block") push(state, "block", stream); 161 else if (curPunc == state.ctx.type) pop(state); 162 else if (state.ctx.type == "block" && style != "comment") setFlag(state, BRACELESS) 163 state.afterIdent = style == "variable" || style == "keyword"; 164 return style; 165 }, 166 167 indent: function(state, textAfter) { 168 if (state.tokenize != tokenBase) return 0; 169 var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, 170 closing = firstChar == ctx.type; 171 if (ctx.flags & BRACELESS) ctx = ctx.prev 172 if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); 173 else if (ctx.flags & ALIGN_YES) return ctx.column + (closing ? 0 : 1); 174 else return ctx.indent + (closing ? 0 : config.indentUnit); 175 }, 176 177 lineComment: "#" 178 }; 179 }); 180 181 CodeMirror.defineMIME("text/x-rsrc", "r"); 182 183 });
Downloadmodules/editor/codemirror/mode/r/r.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.