aboutsummaryrefslogtreecommitdiff
path: root/imports/codemirror/mode/coffeescript/coffeescript.js
diff options
context:
space:
mode:
Diffstat (limited to 'imports/codemirror/mode/coffeescript/coffeescript.js')
-rwxr-xr-ximports/codemirror/mode/coffeescript/coffeescript.js325
1 files changed, 325 insertions, 0 deletions
diff --git a/imports/codemirror/mode/coffeescript/coffeescript.js b/imports/codemirror/mode/coffeescript/coffeescript.js
new file mode 100755
index 00000000..d4d57239
--- /dev/null
+++ b/imports/codemirror/mode/coffeescript/coffeescript.js
@@ -0,0 +1,325 @@
1/**
2 * Link to the project's GitHub page:
3 * https://github.com/pickhardt/coffeescript-codemirror-mode
4 */
5CodeMirror.defineMode('coffeescript', function(conf) {
6 var ERRORCLASS = 'error';
7
8 function wordRegexp(words) {
9 return new RegExp("^((" + words.join(")|(") + "))\\b");
10 }
11
12 var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");
13 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
14 var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
15 var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
16 var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
17 var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
18
19 var wordOperators = wordRegexp(['and', 'or', 'not',
20 'is', 'isnt', 'in',
21 'instanceof', 'typeof']);
22 var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
23 'switch', 'try', 'catch', 'finally', 'class'];
24 var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
25 'do', 'in', 'of', 'new', 'return', 'then',
26 'this', 'throw', 'when', 'until'];
27
28 var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
29
30 indentKeywords = wordRegexp(indentKeywords);
31
32
33 var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
34 var regexPrefixes = new RegExp("^(/{3}|/)");
35 var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
36 var constants = wordRegexp(commonConstants);
37
38 // Tokenizers
39 function tokenBase(stream, state) {
40 // Handle scope changes
41 if (stream.sol()) {
42 var scopeOffset = state.scopes[0].offset;
43 if (stream.eatSpace()) {
44 var lineOffset = stream.indentation();
45 if (lineOffset > scopeOffset) {
46 return 'indent';
47 } else if (lineOffset < scopeOffset) {
48 return 'dedent';
49 }
50 return null;
51 } else {
52 if (scopeOffset > 0) {
53 dedent(stream, state);
54 }
55 }
56 }
57 if (stream.eatSpace()) {
58 return null;
59 }
60
61 var ch = stream.peek();
62
63 // Handle comments
64 if (ch === '#') {
65 stream.skipToEnd();
66 return 'comment';
67 }
68
69 // Handle number literals
70 if (stream.match(/^-?[0-9\.]/, false)) {
71 var floatLiteral = false;
72 // Floats
73 if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
74 floatLiteral = true;
75 }
76 if (stream.match(/^-?\d+\.\d*/)) {
77 floatLiteral = true;
78 }
79 if (stream.match(/^-?\.\d+/)) {
80 floatLiteral = true;
81 }
82 if (floatLiteral) {
83 return 'number';
84 }
85 // Integers
86 var intLiteral = false;
87 // Hex
88 if (stream.match(/^-?0x[0-9a-f]+/i)) {
89 intLiteral = true;
90 }
91 // Decimal
92 if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
93 intLiteral = true;
94 }
95 // Zero by itself with no other piece of number.
96 if (stream.match(/^-?0(?![\dx])/i)) {
97 intLiteral = true;
98 }
99 if (intLiteral) {
100 return 'number';
101 }
102 }
103
104 // Handle strings
105 if (stream.match(stringPrefixes)) {
106 state.tokenize = tokenFactory(stream.current(), 'string');
107 return state.tokenize(stream, state);
108 }
109 // Handle regex literals
110 if (stream.match(regexPrefixes)) {
111 if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
112 state.tokenize = tokenFactory(stream.current(), 'string-2');
113 return state.tokenize(stream, state);
114 } else {
115 stream.backUp(1);
116 }
117 }
118
119 // Handle operators and delimiters
120 if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
121 return 'punctuation';
122 }
123 if (stream.match(doubleOperators)
124 || stream.match(singleOperators)
125 || stream.match(wordOperators)) {
126 return 'operator';
127 }
128 if (stream.match(singleDelimiters)) {
129 return 'punctuation';
130 }
131
132 if (stream.match(constants)) {
133 return 'atom';
134 }
135
136 if (stream.match(keywords)) {
137 return 'keyword';
138 }
139
140 if (stream.match(identifiers)) {
141 return 'variable';
142 }
143
144 // Handle non-detected items
145 stream.next();
146 return ERRORCLASS;
147 }
148
149 function tokenFactory(delimiter, outclass) {
150 var delim_re = new RegExp(delimiter);
151 var singleline = delimiter.length == 1;
152
153 return function tokenString(stream, state) {
154 while (!stream.eol()) {
155 stream.eatWhile(/[^'"\/\\]/);
156 if (stream.eat('\\')) {
157 stream.next();
158 if (singleline && stream.eol()) {
159 return outclass;
160 }
161 } else if (stream.match(delim_re)) {
162 state.tokenize = tokenBase;
163 return outclass;
164 } else {
165 stream.eat(/['"\/]/);
166 }
167 }
168 if (singleline) {
169 if (conf.mode.singleLineStringErrors) {
170 outclass = ERRORCLASS
171 } else {
172 state.tokenize = tokenBase;
173 }
174 }
175 return outclass;
176 };
177 }
178
179 function indent(stream, state, type) {
180 type = type || 'coffee';
181 var indentUnit = 0;
182 if (type === 'coffee') {
183 for (var i = 0; i < state.scopes.length; i++) {
184 if (state.scopes[i].type === 'coffee') {
185 indentUnit = state.scopes[i].offset + conf.indentUnit;
186 break;
187 }
188 }
189 } else {
190 indentUnit = stream.column() + stream.current().length;
191 }
192 state.scopes.unshift({
193 offset: indentUnit,
194 type: type
195 });
196 }
197
198 function dedent(stream, state) {
199 if (state.scopes.length == 1) return;
200 if (state.scopes[0].type === 'coffee') {
201 var _indent = stream.indentation();
202 var _indent_index = -1;
203 for (var i = 0; i < state.scopes.length; ++i) {
204 if (_indent === state.scopes[i].offset) {
205 _indent_index = i;
206 break;
207 }
208 }
209 if (_indent_index === -1) {
210 return true;
211 }
212 while (state.scopes[0].offset !== _indent) {
213 state.scopes.shift();
214 }
215 return false
216 } else {
217 state.scopes.shift();
218 return false;
219 }