codemirror-rails 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/codemirror-rails-0.2.1.gem +0 -0
- data/lib/codemirror/rails/version.rb +2 -2
- data/upgrade_codemirror_stable.rb +36 -0
- data/vendor/assets/javascripts/codemirror.js +45 -32
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +308 -0
- data/vendor/assets/javascripts/codemirror/modes/php.js +6 -1
- data/vendor/assets/javascripts/codemirror/modes/python.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/r.js +134 -0
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +182 -0
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +182 -181
- data/vendor/assets/javascripts/codemirror/modes/velocity.js +146 -0
- data/vendor/assets/javascripts/codemirror/modes/xmlpure.js +481 -0
- data/vendor/assets/stylesheets/codemirror/themes/default.css +1 -0
- data/vendor/assets/stylesheets/codemirror/themes/elegant.css +9 -0
- data/vendor/assets/stylesheets/codemirror/themes/neat.css +8 -0
- data/vendor/assets/stylesheets/codemirror/themes/night.css +20 -0
- metadata +12 -4
- data/codemirror-rails-0.1.2.gem +0 -0
- data/codemirror-rails-0.2.0.gem +0 -0
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
# wget codemirror zip
|
5
|
+
# unzip codemirror
|
6
|
+
# copy css
|
7
|
+
# copy javascript
|
8
|
+
|
9
|
+
unless codemirror = ARGV.shift
|
10
|
+
raise 'Usage: ./upgrade_codemirror_stable.rb [CodeMirror-x.xx]'
|
11
|
+
end
|
12
|
+
|
13
|
+
base_path = File.dirname(__FILE__)
|
14
|
+
vendor = "#{base_path}/vendor/assets"
|
15
|
+
stable = "#{base_path}/#{codemirror}"
|
16
|
+
|
17
|
+
puts vendor
|
18
|
+
puts stable
|
19
|
+
|
20
|
+
globs_to_copy = {
|
21
|
+
'lib/codemirror.css' => 'stylesheets/codemirror.css',
|
22
|
+
'lib/codemirror.js' => 'javascripts/codemirror.js',
|
23
|
+
'lib/overlay.js' => 'javascripts/codemirror/overlay.js',
|
24
|
+
'lib/runmode.js' => 'javascripts/codemirror/runmode.js',
|
25
|
+
'theme/*.css' => 'stylesheets/codemirror/themes/',
|
26
|
+
'mode/**/*.js' => 'javascripts/codemirror/modes/',
|
27
|
+
'mode/**/*.css' => 'stylesheets/codemirror/modes/'
|
28
|
+
}
|
29
|
+
|
30
|
+
globs_to_copy.each do |glob_from, to|
|
31
|
+
dest = "#{vendor}/#{to}"
|
32
|
+
Dir.glob("#{stable}/#{glob_from}").each do |src|
|
33
|
+
puts "#{src} => #{to}"
|
34
|
+
FileUtils.copy src, dest
|
35
|
+
end
|
36
|
+
end
|
@@ -119,7 +119,7 @@ var CodeMirror = (function() {
|
|
119
119
|
focus: function(){focusInput(); onFocus(); fastPoll();},
|
120
120
|
setOption: function(option, value) {
|
121
121
|
options[option] = value;
|
122
|
-
if (option == "lineNumbers" || option == "gutter") gutterChanged();
|
122
|
+
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber") gutterChanged();
|
123
123
|
else if (option == "mode" || option == "indentUnit") loadMode();
|
124
124
|
else if (option == "readOnly" && value == "nocursor") input.blur();
|
125
125
|
else if (option == "theme") scroller.className = scroller.className.replace(/cm-s-\w+/, "cm-s-" + value);
|
@@ -127,7 +127,9 @@ var CodeMirror = (function() {
|
|
127
127
|
getOption: function(option) {return options[option];},
|
128
128
|
undo: operation(undo),
|
129
129
|
redo: operation(redo),
|
130
|
-
indentLine: operation(function(n) {
|
130
|
+
indentLine: operation(function(n, dir) {
|
131
|
+
if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract");
|
132
|
+
}),
|
131
133
|
historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
|
132
134
|
matchBrackets: operation(function(){matchBrackets(true);}),
|
133
135
|
getTokenAt: function(pos) {
|
@@ -200,7 +202,8 @@ var CodeMirror = (function() {
|
|
200
202
|
refresh: function(){updateDisplay(true);},
|
201
203
|
getInputField: function(){return input;},
|
202
204
|
getWrapperElement: function(){return wrapper;},
|
203
|
-
getScrollerElement: function(){return scroller;}
|
205
|
+
getScrollerElement: function(){return scroller;},
|
206
|
+
getGutterElement: function(){return gutter;}
|
204
207
|
};
|
205
208
|
|
206
209
|
function setValue(code) {
|
@@ -340,6 +343,7 @@ var CodeMirror = (function() {
|
|
340
343
|
if (mod && code == 90) {undo(); return e_preventDefault(e);} // ctrl-z
|
341
344
|
if (mod && ((e.shiftKey && code == 90) || code == 89)) {redo(); return e_preventDefault(e);} // ctrl-shift-z, ctrl-y
|
342
345
|
}
|
346
|
+
if (code == 36) { if (options.smartHome) { smartHome(); return e_preventDefault(e); } }
|
343
347
|
|
344
348
|
// Key id to use in the movementKeys map. We also pass it to
|
345
349
|
// fastPoll in order to 'self learn'. We need this because
|
@@ -347,14 +351,16 @@ var CodeMirror = (function() {
|
|
347
351
|
// its start when it is inverted and a movement key is pressed
|
348
352
|
// (and later restore it again), shouldn't be used for
|
349
353
|
// non-movement keys.
|
350
|
-
curKeyId = (mod ? "c" : "") + code;
|
351
|
-
if (sel.inverted && movementKeys
|
354
|
+
curKeyId = (mod ? "c" : "") + (e.altKey ? "a" : "") + code;
|
355
|
+
if (sel.inverted && movementKeys[curKeyId] === true) {
|
352
356
|
var range = selRange(input);
|
353
357
|
if (range) {
|
354
358
|
reducedSelection = {anchor: range.start};
|
355
359
|
setSelRange(input, range.start, range.start);
|
356
360
|
}
|
357
361
|
}
|
362
|
+
// Don't save the key as a movementkey unless it had a modifier
|
363
|
+
if (!mod && !e.altKey) curKeyId = null;
|
358
364
|
fastPoll(curKeyId);
|
359
365
|
}
|
360
366
|
function onKeyUp(e) {
|
@@ -566,7 +572,10 @@ var CodeMirror = (function() {
|
|
566
572
|
function p() {
|
567
573
|
startOperation();
|
568
574
|
var changed = readInput();
|
569
|
-
if (changed
|
575
|
+
if (changed && keyId) {
|
576
|
+
if (changed == "moved" && movementKeys[keyId] == null) movementKeys[keyId] = true;
|
577
|
+
if (changed == "changed") movementKeys[keyId] = false;
|
578
|
+
}
|
570
579
|
if (!changed && !missed) {missed = true; poll.set(80, p);}
|
571
580
|
else {pollingFast = false; slowPoll();}
|
572
581
|
endOperation();
|
@@ -663,6 +672,12 @@ var CodeMirror = (function() {
|
|
663
672
|
if (options.readOnly != "nocursor") input.focus();
|
664
673
|
}
|
665
674
|
|
675
|
+
function scrollEditorIntoView() {
|
676
|
+
if (!cursor.getBoundingClientRect) return;
|
677
|
+
var rect = cursor.getBoundingClientRect();
|
678
|
+
var winH = window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight;
|
679
|
+
if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();
|
680
|
+
}
|
666
681
|
function scrollCursorIntoView() {
|
667
682
|
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
|
668
683
|
return scrollIntoView(cursor.x, cursor.y, cursor.x, cursor.yBot);
|
@@ -766,8 +781,8 @@ var CodeMirror = (function() {
|
|
766
781
|
if (different) {
|
767
782
|
lastHeight = scroller.clientHeight;
|
768
783
|
code.style.height = (lines.length * lineHeight() + 2 * paddingTop()) + "px";
|
769
|
-
updateGutter();
|
770
784
|
}
|
785
|
+
if (different || updates.length) updateGutter();
|
771
786
|
|
772
787
|
if (maxWidth == null) maxWidth = stringWidth(maxLine);
|
773
788
|
if (maxWidth > scroller.clientWidth) {
|
@@ -871,10 +886,12 @@ var CodeMirror = (function() {
|
|
871
886
|
}
|
872
887
|
function updateCursor() {
|
873
888
|
var head = sel.inverted ? sel.from : sel.to, lh = lineHeight();
|
874
|
-
var x = charX(head.line, head.ch)
|
889
|
+
var x = charX(head.line, head.ch);
|
875
890
|
inputDiv.style.top = (head.line * lh - scroller.scrollTop) + "px";
|
891
|
+
inputDiv.style.left = (x - scroller.scrollLeft) + "px";
|
876
892
|
if (posEq(sel.from, sel.to)) {
|
877
|
-
cursor.style.top =
|
893
|
+
cursor.style.top = (head.line - showingFrom) * lh + "px";
|
894
|
+
cursor.style.left = x + "px";
|
878
895
|
cursor.style.display = "";
|
879
896
|
}
|
880
897
|
else cursor.style.display = "none";
|
@@ -994,6 +1011,10 @@ var CodeMirror = (function() {
|
|
994
1011
|
}
|
995
1012
|
return true;
|
996
1013
|
}
|
1014
|
+
function smartHome() {
|
1015
|
+
var firstNonWS = Math.max(0, lines[sel.from.line].text.search(/\S/));
|
1016
|
+
setCursor(sel.from.line, sel.from.ch <= firstNonWS && sel.from.ch ? 0 : firstNonWS, true);
|
1017
|
+
}
|
997
1018
|
|
998
1019
|
function indentLine(n, how) {
|
999
1020
|
if (how == "smart") {
|
@@ -1190,8 +1211,8 @@ var CodeMirror = (function() {
|
|
1190
1211
|
|
1191
1212
|
var oldCSS = input.style.cssText;
|
1192
1213
|
inputDiv.style.position = "absolute";
|
1193
|
-
input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (
|
1194
|
-
"px; left: " + (
|
1214
|
+
input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
|
1215
|
+
"px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
|
1195
1216
|
"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
|
1196
1217
|
leaveInputAlone = true;
|
1197
1218
|
var val = input.value = getSelection();
|
@@ -1284,7 +1305,7 @@ var CodeMirror = (function() {
|
|
1284
1305
|
if (line.stateAfter) return search;
|
1285
1306
|
var indented = line.indentation();
|
1286
1307
|
if (minline == null || minindent > indented) {
|
1287
|
-
minline = search;
|
1308
|
+
minline = search - 1;
|
1288
1309
|
minindent = indented;
|
1289
1310
|
}
|
1290
1311
|
}
|
@@ -1321,25 +1342,26 @@ var CodeMirror = (function() {
|
|
1321
1342
|
if (state) state = copyState(mode, state);
|
1322
1343
|
else state = startState(mode);
|
1323
1344
|
|
1324
|
-
var unchanged = 0, compare = mode.compareStates;
|
1345
|
+
var unchanged = 0, compare = mode.compareStates, realChange = false;
|
1325
1346
|
for (var i = start, l = lines.length; i < l; ++i) {
|
1326
1347
|
var line = lines[i], hadState = line.stateAfter;
|
1327
1348
|
if (+new Date > end) {
|
1328
1349
|
work.push(i);
|
1329
1350
|
startWorker(options.workDelay);
|
1330
|
-
changes.push({from: task, to: i + 1});
|
1351
|
+
if (realChange) changes.push({from: task, to: i + 1});
|
1331
1352
|
return;
|
1332
1353
|
}
|
1333
1354
|
var changed = line.highlight(mode, state);
|
1355
|
+
if (changed) realChange = true;
|
1334
1356
|
line.stateAfter = copyState(mode, state);
|
1335
1357
|
if (compare) {
|
1336
1358
|
if (hadState && compare(hadState, state)) break;
|
1337
1359
|
} else {
|
1338
|
-
if (changed || !hadState) unchanged = 0;
|
1360
|
+
if (changed !== false || !hadState) unchanged = 0;
|
1339
1361
|
else if (++unchanged > 3) break;
|
1340
1362
|
}
|
1341
1363
|
}
|
1342
|
-
changes.push({from: task, to: i + 1});
|
1364
|
+
if (realChange) changes.push({from: task, to: i + 1});
|
1343
1365
|
}
|
1344
1366
|
if (foundWork && options.onHighlightComplete)
|
1345
1367
|
options.onHighlightComplete(instance);
|
@@ -1362,7 +1384,7 @@ var CodeMirror = (function() {
|
|
1362
1384
|
if (changes.length) updateDisplay(changes);
|
1363
1385
|
else if (selectionChanged) updateCursor();
|
1364
1386
|
if (reScroll) scrollCursorIntoView();
|
1365
|
-
if (selectionChanged) restartBlink();
|
1387
|
+
if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
|
1366
1388
|
|
1367
1389
|
// updateInput can be set to a boolean value to force/prevent an
|
1368
1390
|
// update.
|
@@ -1527,6 +1549,7 @@ var CodeMirror = (function() {
|
|
1527
1549
|
gutter: false,
|
1528
1550
|
firstLineNumber: 1,
|
1529
1551
|
readOnly: false,
|
1552
|
+
smartHome: true,
|
1530
1553
|
onChange: null,
|
1531
1554
|
onCursorActivity: null,
|
1532
1555
|
onGutterClick: null,
|
@@ -1660,7 +1683,7 @@ var CodeMirror = (function() {
|
|
1660
1683
|
if (ok) {++this.pos; return ch;}
|
1661
1684
|
},
|
1662
1685
|
eatWhile: function(match) {
|
1663
|
-
var start = this.
|
1686
|
+
var start = this.pos;
|
1664
1687
|
while (this.eat(match)){}
|
1665
1688
|
return this.pos > start;
|
1666
1689
|
},
|
@@ -1769,10 +1792,10 @@ var CodeMirror = (function() {
|
|
1769
1792
|
}
|
1770
1793
|
if (st.length != pos) {st.length = pos; changed = true;}
|
1771
1794
|
if (pos && st[pos-2] != prevWord) changed = true;
|
1772
|
-
// Short lines with simple highlights
|
1773
|
-
//
|
1774
|
-
// contexts.
|
1775
|
-
return changed || (st.length < 5 && this.text.length < 10);
|
1795
|
+
// Short lines with simple highlights return null, and are
|
1796
|
+
// counted as changed by the driver because they are likely to
|
1797
|
+
// highlight the same way in various contexts.
|
1798
|
+
return changed || (st.length < 5 && this.text.length < 10 ? null : false);
|
1776
1799
|
},
|
1777
1800
|
// Fetch the parser token for a given character. Useful for hacks
|
1778
1801
|
// that want to inspect the mode state (say, for completion).
|
@@ -1930,16 +1953,6 @@ var CodeMirror = (function() {
|
|
1930
1953
|
else if (e.button & 2) return 3;
|
1931
1954
|
else if (e.button & 4) return 2;
|
1932
1955
|
}
|
1933
|
-
function e_pageX(e) {
|
1934
|
-
if (e.pageX != null) return e.pageX;
|
1935
|
-
var doc = e_target(e).ownerDocument;
|
1936
|
-
return e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
|
1937
|
-
}
|
1938
|
-
function e_pageY(e) {
|
1939
|
-
if (e.pageY != null) return e.pageY;
|
1940
|
-
var doc = e_target(e).ownerDocument;
|
1941
|
-
return e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
|
1942
|
-
}
|
1943
1956
|
|
1944
1957
|
// Event handler registration. If disconnect is true, it'll return a
|
1945
1958
|
// function that unregisters the handler.
|
@@ -0,0 +1,308 @@
|
|
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 commonKeywords = ['break', 'by', 'catch', 'class', 'continue',
|
23
|
+
'debugger', 'delete', 'do', 'else', 'finally',
|
24
|
+
'for', 'in', 'of', 'if', 'new', 'return',
|
25
|
+
'switch', 'then', 'this', 'throw', 'try',
|
26
|
+
'unless', 'when', 'while', 'until', 'loop'];
|
27
|
+
var keywords = wordRegexp(commonKeywords);
|
28
|
+
|
29
|
+
|
30
|
+
var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
|
31
|
+
var commonConstants = ['Infinity', 'NaN', 'undefined', 'true', 'false'];
|
32
|
+
var constants = wordRegexp(commonConstants);
|
33
|
+
|
34
|
+
// Tokenizers
|
35
|
+
function tokenBase(stream, state) {
|
36
|
+
// Handle scope changes
|
37
|
+
if (stream.sol()) {
|
38
|
+
var scopeOffset = state.scopes[0].offset;
|
39
|
+
if (stream.eatSpace()) {
|
40
|
+
var lineOffset = stream.indentation();
|
41
|
+
if (lineOffset > scopeOffset) {
|
42
|
+
return 'indent';
|
43
|
+
} else if (lineOffset < scopeOffset) {
|
44
|
+
return 'dedent';
|
45
|
+
}
|
46
|
+
return null;
|
47
|
+
} else {
|
48
|
+
if (scopeOffset > 0) {
|
49
|
+
dedent(stream, state);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
if (stream.eatSpace()) {
|
54
|
+
return null;
|
55
|
+
}
|
56
|
+
|
57
|
+
var ch = stream.peek();
|
58
|
+
|
59
|
+
// Handle comments
|
60
|
+
if (ch === '#') {
|
61
|
+
stream.skipToEnd();
|
62
|
+
return 'comment';
|
63
|
+
}
|
64
|
+
|
65
|
+
// Handle number literals
|
66
|
+
if (stream.match(/^-?[0-9\.]/, false)) {
|
67
|
+
var floatLiteral = false;
|
68
|
+
// Floats
|
69
|
+
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
|
70
|
+
floatLiteral = true;
|
71
|
+
}
|
72
|
+
if (stream.match(/^-?\d+\.\d*/)) {
|
73
|
+
floatLiteral = true;
|
74
|
+
}
|
75
|
+
if (stream.match(/^-?\.\d+/)) {
|
76
|
+
floatLiteral = true;
|
77
|
+
}
|
78
|
+
if (floatLiteral) {
|
79
|
+
return 'number';
|
80
|
+
}
|
81
|
+
// Integers
|
82
|
+
var intLiteral = false;
|
83
|
+
// Hex
|
84
|
+
if (stream.match(/^-?0x[0-9a-f]+/i)) {
|
85
|
+
intLiteral = true;
|
86
|
+
}
|
87
|
+
// Decimal
|
88
|
+
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
|
89
|
+
intLiteral = true;
|
90
|
+
}
|
91
|
+
// Zero by itself with no other piece of number.
|
92
|
+
if (stream.match(/^-?0(?![\dx])/i)) {
|
93
|
+
intLiteral = true;
|
94
|
+
}
|
95
|
+
if (intLiteral) {
|
96
|
+
return 'number';
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
// Handle strings
|
101
|
+
if (stream.match(stringPrefixes)) {
|
102
|
+
state.tokenize = tokenStringFactory(stream.current());
|
103
|
+
return state.tokenize(stream, state);
|
104
|
+
}
|
105
|
+
|
106
|
+
// Handle operators and delimiters
|
107
|
+
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
|
108
|
+
return 'punctuation';
|
109
|
+
}
|
110
|
+
if (stream.match(doubleOperators)
|
111
|
+
|| stream.match(singleOperators)
|
112
|
+
|| stream.match(wordOperators)) {
|
113
|
+
return 'operator';
|
114
|
+
}
|
115
|
+
if (stream.match(singleDelimiters)) {
|
116
|
+
return 'punctuation';
|
117
|
+
}
|
118
|
+
|
119
|
+
if (stream.match(constants)) {
|
120
|
+
return 'atom';
|
121
|
+
}
|
122
|
+
|
123
|
+
if (stream.match(keywords)) {
|
124
|
+
return 'keyword';
|
125
|
+
}
|
126
|
+
|
127
|
+
if (stream.match(identifiers)) {
|
128
|
+
return 'variable';
|
129
|
+
}
|
130
|
+
|
131
|
+
// Handle non-detected items
|
132
|
+
stream.next();
|
133
|
+
return ERRORCLASS;
|
134
|
+
}
|
135
|
+
|
136
|
+
function tokenStringFactory(delimiter) {
|
137
|
+
while ('rub'.indexOf(delimiter[0].toLowerCase()) >= 0) {
|
138
|
+
delimiter = delimiter.substr(1);
|
139
|
+
}
|
140
|
+
var delim_re = new RegExp(delimiter);
|
141
|
+
var singleline = delimiter.length == 1;
|
142
|
+
var OUTCLASS = 'string';
|
143
|
+
|
144
|
+
return function tokenString(stream, state) {
|
145
|
+
while (!stream.eol()) {
|
146
|
+
stream.eatWhile(/[^'"\\]/);
|
147
|
+
if (stream.eat('\\')) {
|
148
|
+
stream.next();
|
149
|
+
if (singleline && stream.eol()) {
|
150
|
+
return OUTCLASS;
|
151
|
+
}
|
152
|
+
} else if (stream.match(delim_re)) {
|
153
|
+
state.tokenize = tokenBase;
|
154
|
+
return OUTCLASS;
|
155
|
+
} else {
|
156
|
+
stream.eat(/['"]/);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
if (singleline) {
|
160
|
+
if (conf.mode.singleLineStringErrors) {
|
161
|
+
OUTCLASS = ERRORCLASS
|
162
|
+
} else {
|
163
|
+
state.tokenize = tokenBase;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
return OUTCLASS;
|
167
|
+
};
|
168
|
+
}
|
169
|
+
|
170
|
+
function indent(stream, state, type) {
|
171
|
+
type = type || 'coffee';
|
172
|
+
var indentUnit = 0;
|
173
|
+
if (type === 'coffee') {
|
174
|
+
for (var i = 0; i < state.scopes.length; i++) {
|
175
|
+
if (state.scopes[i].type === 'coffee') {
|
176
|
+
indentUnit = state.scopes[i].offset + conf.indentUnit;
|
177
|
+
break;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
} else {
|
181
|
+
indentUnit = stream.column() + stream.current().length;
|
182
|
+
}
|
183
|
+
state.scopes.unshift({
|
184
|
+
offset: indentUnit,
|
185
|
+
type: type
|
186
|
+
});
|
187
|
+
}
|
188
|
+
|
189
|
+
function dedent(stream, state) {
|
190
|
+
if (state.scopes.length == 1) return;
|
191
|
+
if (state.scopes[0].type === 'coffee') {
|
192
|
+
var _indent = stream.indentation();
|
193
|
+
var _indent_index = -1;
|
194
|
+
for (var i = 0; i < state.scopes.length; ++i) {
|
195
|
+
if (_indent === state.scopes[i].offset) {
|
196
|
+
_indent_index = i;
|
197
|
+
break;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
if (_indent_index === -1) {
|
201
|
+
return true;
|
202
|
+
}
|
203
|
+
while (state.scopes[0].offset !== _indent) {
|
204
|
+
state.scopes.shift();
|
205
|
+
}
|
206
|
+
return false
|
207
|
+
} else {
|
208
|
+
state.scopes.shift();
|
209
|
+
return false;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
function tokenLexer(stream, state) {
|
214
|
+
var style = state.tokenize(stream, state);
|
215
|
+
var current = stream.current();
|
216
|
+
|
217
|
+
// Handle '.' connected identifiers
|
218
|
+
if (current === '.') {
|
219
|
+
style = state.tokenize(stream, state);
|
220
|
+
current = stream.current();
|
221
|
+
if (style === 'variable') {
|
222
|
+
return 'variable';
|
223
|
+
} else {
|
224
|
+
return ERRORCLASS;
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
// Handle decorators
|
229
|
+
if (current === '@') {
|
230
|
+
style = state.tokenize(stream, state);
|
231
|
+
current = stream.current();
|
232
|
+
if (style === 'variable') {
|
233
|
+
return 'variable-2';
|
234
|
+
} else {
|
235
|
+
return ERRORCLASS;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
// Handle scope changes.
|
240
|
+
if (current === 'pass' || current === 'return') {
|
241
|
+
state.dedent += 1;
|
242
|
+
}
|
243
|
+
if ((current === '->' &&
|
244
|
+
!state.lambda &&
|
245
|
+
state.scopes[0].type == 'coffee' &&
|
246
|
+
stream.peek() === '')
|
247
|
+
|| style === 'indent') {
|
248
|
+
indent(stream, state);
|
249
|
+
}
|
250
|
+
var delimiter_index = '[({'.indexOf(current);
|
251
|
+
if (delimiter_index !== -1) {
|
252
|
+
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
|
253
|
+
}
|
254
|
+
if (style === 'dedent') {
|
255
|
+
if (dedent(stream, state)) {
|
256
|
+
return ERRORCLASS;
|
257
|
+
}
|
258
|
+
}
|
259
|
+
delimiter_index = '])}'.indexOf(current);
|
260
|
+
if (delimiter_index !== -1) {
|
261
|
+
if (dedent(stream, state)) {
|
262
|
+
return ERRORCLASS;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
|
266
|
+
if (state.scopes.length > 1) state.scopes.shift();
|
267
|
+
state.dedent -= 1;
|
268
|
+
}
|
269
|
+
|
270
|
+
return style;
|
271
|
+
}
|
272
|
+
|
273
|
+
var external = {
|
274
|
+
startState: function(basecolumn) {
|
275
|
+
return {
|
276
|
+
tokenize: tokenBase,
|
277
|
+
scopes: [{offset:basecolumn || 0, type:'coffee'}],
|
278
|
+
lastToken: null,
|
279
|
+
lambda: false,
|
280
|
+
dedent: 0
|
281
|
+
};
|
282
|
+
},
|
283
|
+
|
284
|
+
token: function(stream, state) {
|
285
|
+
var style = tokenLexer(stream, state);
|
286
|
+
|
287
|
+
state.lastToken = {style:style, content: stream.current()};
|
288
|
+
|
289
|
+
if (stream.eol() && stream.lambda) {
|
290
|
+
state.lambda = false;
|
291
|
+
}
|
292
|
+
|
293
|
+
return style;
|
294
|
+
},
|
295
|
+
|
296
|
+
indent: function(state, textAfter) {
|
297
|
+
if (state.tokenize != tokenBase) {
|
298
|
+
return 0;
|
299
|
+
}
|
300
|
+
|
301
|
+
return state.scopes[0].offset;
|
302
|
+
}
|
303
|
+
|
304
|
+
};
|
305
|
+
return external;
|
306
|
+
});
|
307
|
+
|
308
|
+
CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');
|