diff options
Diffstat (limited to 'imports/codemirror/mode/coffeescript/coffeescript.js')
-rwxr-xr-x | imports/codemirror/mode/coffeescript/coffeescript.js | 325 |
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 | */ | ||
5 | CodeMirror.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; | ||