diff options
Diffstat (limited to 'imports/codemirror/mode/r/r.js')
-rwxr-xr-x | imports/codemirror/mode/r/r.js | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/imports/codemirror/mode/r/r.js b/imports/codemirror/mode/r/r.js new file mode 100755 index 00000000..53647f23 --- /dev/null +++ b/imports/codemirror/mode/r/r.js | |||
@@ -0,0 +1,141 @@ | |||
1 | CodeMirror.defineMode("r", function(config) { | ||
2 | function wordObj(str) { | ||
3 | var words = str.split(" "), res = {}; | ||
4 | for (var i = 0; i < words.length; ++i) res[words[i]] = true; | ||
5 | return res; | ||
6 | } | ||
7 | var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); | ||
8 | var builtins = wordObj("list quote bquote eval return call parse deparse"); | ||
9 | var keywords = wordObj("if else repeat while function for in next break"); | ||
10 | var blockkeywords = wordObj("if else repeat while function for"); | ||
11 | var opChars = /[+\-*\/^<>=!&|~$:]/; | ||
12 | var curPunc; | ||
13 | |||
14 | function tokenBase(stream, state) { | ||
15 | curPunc = null; | ||
16 | var ch = stream.next(); | ||
17 | if (ch == "#") { | ||
18 | stream.skipToEnd(); | ||
19 | return "comment"; | ||
20 | } else if (ch == "0" && stream.eat("x")) { | ||
21 | stream.eatWhile(/[\da-f]/i); | ||
22 | return "number"; | ||
23 | } else if (ch == "." && stream.eat(/\d/)) { | ||
24 | stream.match(/\d*(?:e[+\-]?\d+)?/); | ||
25 | return "number"; | ||
26 | } else if (/\d/.test(ch)) { | ||
27 | stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); | ||
28 | return "number"; | ||
29 | } else if (ch == "'" || ch == '"') { | ||
30 | state.tokenize = tokenString(ch); | ||
31 | return "string"; | ||
32 | } else if (ch == "." && stream.match(/.[.\d]+/)) { | ||
33 | return "keyword"; | ||
34 | } else if (/[\w\.]/.test(ch) && ch != "_") { | ||
35 | stream.eatWhile(/[\w\.]/); | ||
36 | var word = stream.current(); | ||
37 | if (atoms.propertyIsEnumerable(word)) return "atom"; | ||
38 | if (keywords.propertyIsEnumerable(word)) { | ||
39 | if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block"; | ||
40 | return "keyword"; | ||
41 | } | ||
42 | if (builtins.propertyIsEnumerable(word)) return "builtin"; | ||
43 | return "variable"; | ||
44 | } else if (ch == "%") { | ||
45 | if (stream.skipTo("%")) stream.next(); | ||
46 | return "variable-2"; | ||
47 | } else if (ch == "<" && stream.eat("-")) { | ||
48 | return "arrow"; | ||
49 | } else if (ch == "=" && state.ctx.argList) { | ||
50 | return "arg-is"; | ||
51 | } else if (opChars.test(ch)) { | ||
52 | if (ch == "$") return "dollar"; | ||
53 | stream.eatWhile(opChars); | ||
54 | return "operator"; | ||
55 | } else if (/[\(\){}\[\];]/.test(ch)) { | ||
56 | curPunc = ch; | ||
57 | if (ch == ";") return "semi"; | ||
58 | return null; | ||
59 | } else { | ||
60 | return null; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | function tokenString(quote) { | ||
65 | return function(stream, state) { | ||
66 | if (stream.eat("\\")) { | ||
67 | var ch = stream.next(); | ||
68 | if (ch == "x") stream.match(/^[a-f0-9]{2}/i); | ||
69 | else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); | ||
70 | else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); | ||
71 | else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); | ||
72 | else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); | ||
73 | return "string-2"; | ||
74 | } else { | ||
75 | var next; | ||
76 | while ((next = stream.next()) != null) { | ||
77 | if (next == quote) { state.tokenize = tokenBase; break; } | ||
78 | if (next == "\\") { stream.backUp(1); break; } | ||
79 | } | ||
80 | return "string"; | ||
81 | } | ||
82 | }; | ||
83 | } | ||
84 | |||
85 | function push(state, type, stream) { | ||
86 | state.ctx = {type: type, | ||
87 | indent: state.indent, | ||
88 | align: null, | ||
89 | column: stream.column(), | ||
90 | prev: state.ctx}; | ||
91 | } | ||
92 | function pop(state) { | ||
93 | state.indent = state.ctx.indent; | ||
94 | state.ctx = state.ctx.prev; | ||
95 | } | ||
96 | |||
97 | return { | ||
98 | startState: function(base) { | ||
99 | return {tokenize: tokenBase, | ||
100 | ctx: {type: "top", | ||
101 | indent: -config.indentUnit, | ||
102 | align: false}, | ||
103 | indent: 0, | ||
104 | afterIdent: false}; | ||
105 | }, | ||
106 | |||
107 | token: function(stream, state) { | ||
108 | if (stream.sol()) { | ||
109 | if (state.ctx.align == null) state.ctx.align = false; | ||
110 | state.indent = stream.indentation(); | ||
111 | } | ||
112 | if (stream.eatSpace()) return null; | ||
113 | var style = state.tokenize(stream, state); | ||
114 | if (style != "comment" && state.ctx.align == null) state.ctx.align = true; | ||
115 | |||
116 | var ctype = state.ctx.type; | ||
117 | if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state); | ||
118 | if (curPunc == "{") push(state, "}", stream); | ||
119 | else if (curPunc == "(") { | ||
120 | push(state, ")", stream); | ||
121 | if (state.afterIdent) state.ctx.argList = true; | ||
122 | } | ||
123 | else if (curPunc == "[") push(state, "]", stream); | ||
124 | else if (curPunc == "block") push(state, "block", stream); | ||
125 | else if (curPunc == ctype) pop(state); | ||
126 | state.afterIdent = style == "variable" || style == "keyword"; | ||
127 | return style; | ||
128 | }, | ||
129 | |||
130 | indent: function(state, textAfter) { | ||
131 | if (state.tokenize != tokenBase) return 0; | ||
132 | var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, | ||
133 | closing = firstChar == ctx.type; | ||
134 | if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); | ||
135 | else if (ctx.align) return ctx.column + (closing ? 0 : 1); | ||
136 | else return ctx.indent + (closing ? 0 : config.indentUnit); | ||
137 | } | ||
138 | }; | ||
139 | }); | ||
140 | |||
141 | CodeMirror.defineMIME("text/x-rsrc", "r"); | ||