codemirror-rails 2.33 → 2.34
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/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +359 -453
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +4 -1
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +7 -8
- data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +101 -0
- data/vendor/assets/javascripts/codemirror/modes/css.js +336 -62
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +6 -1
- data/vendor/assets/javascripts/codemirror/modes/haxe.js +0 -3
- data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +5 -1
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +11 -12
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +131 -17
- data/vendor/assets/javascripts/codemirror/modes/php.js +4 -6
- data/vendor/assets/javascripts/codemirror/modes/shell.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/tiki.js +0 -7
- data/vendor/assets/javascripts/codemirror/modes/vb.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/xml.js +0 -8
- data/vendor/assets/javascripts/codemirror/utils/closetag.js +35 -35
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +147 -253
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +4 -8
- data/vendor/assets/javascripts/codemirror/utils/overlay.js +3 -1
- data/vendor/assets/javascripts/codemirror/utils/runmode-standalone.js +90 -0
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +1 -1
- data/vendor/assets/stylesheets/codemirror.css +2 -2
- metadata +14 -12
@@ -1,5 +1,5 @@
|
|
1
|
-
// CodeMirror version 2.
|
2
|
-
|
1
|
+
// CodeMirror version 2.34
|
2
|
+
|
3
3
|
// All functions that need access to the editor's state live inside
|
4
4
|
// the CodeMirror function. Below that, at the bottom of the file,
|
5
5
|
// some utilities are defined.
|
@@ -62,22 +62,13 @@ window.CodeMirror = (function() {
|
|
62
62
|
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
|
63
63
|
else if (ie_lt8) scrollbar.style.minWidth = "18px";
|
64
64
|
|
65
|
-
// Check for problem with IE innerHTML not working when we have a
|
66
|
-
// P (or similar) parent node.
|
67
|
-
try { charWidth(); }
|
68
|
-
catch (e) {
|
69
|
-
if (e.message.match(/runtime/i))
|
70
|
-
e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
|
71
|
-
throw e;
|
72
|
-
}
|
73
|
-
|
74
65
|
// Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
|
75
66
|
var poll = new Delayed(), highlight = new Delayed(), blinker;
|
76
67
|
|
77
68
|
// mode holds a mode API object. doc is the tree of Line objects,
|
78
|
-
//
|
79
|
-
// undo history (instance of History constructor).
|
80
|
-
var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]),
|
69
|
+
// frontier is the point up to which the content has been parsed,
|
70
|
+
// and history the undo history (instance of History constructor).
|
71
|
+
var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), frontier = 0, focused;
|
81
72
|
loadMode();
|
82
73
|
// The selection. These are always maintained to point at valid
|
83
74
|
// positions. Inverted is used to remember that the user is
|
@@ -89,7 +80,7 @@ window.CodeMirror = (function() {
|
|
89
80
|
overwrite = false, suppressEdits = false;
|
90
81
|
// Variables used by startOperation/endOperation to track what
|
91
82
|
// happened during the operation.
|
92
|
-
var updateInput, userSelChange, changes, textChanged, selectionChanged,
|
83
|
+
var updateInput, userSelChange, changes, textChanged, selectionChanged,
|
93
84
|
gutterDirty, callbacks;
|
94
85
|
// Current visible range (may be bigger than the view window).
|
95
86
|
var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
|
@@ -99,7 +90,6 @@ window.CodeMirror = (function() {
|
|
99
90
|
// Tracks the maximum line length so that the horizontal scrollbar
|
100
91
|
// can be kept static when scrolling.
|
101
92
|
var maxLine = getLine(0), updateMaxLine = false, maxLineChanged = true;
|
102
|
-
var tabCache = {};
|
103
93
|
var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
|
104
94
|
var goalColumn = null;
|
105
95
|
|
@@ -186,6 +176,7 @@ window.CodeMirror = (function() {
|
|
186
176
|
}
|
187
177
|
},
|
188
178
|
getOption: function(option) {return options[option];},
|
179
|
+
getMode: function() {return mode;},
|
189
180
|
undo: operation(undo),
|
190
181
|
redo: operation(redo),
|
191
182
|
indentLine: operation(function(n, dir) {
|
@@ -204,8 +195,18 @@ window.CodeMirror = (function() {
|
|
204
195
|
history.undone = histData.undone;
|
205
196
|
},
|
206
197
|
getHistory: function() {
|
207
|
-
|
208
|
-
|
198
|
+
function cp(arr) {
|
199
|
+
for (var i = 0, nw = [], nwelt; i < arr.length; ++i) {
|
200
|
+
nw.push(nwelt = []);
|
201
|
+
for (var j = 0, elt = arr[i]; j < elt.length; ++j) {
|
202
|
+
var old = [], cur = elt[j];
|
203
|
+
nwelt.push({start: cur.start, added: cur.added, old: old});
|
204
|
+
for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k]));
|
205
|
+
}
|
206
|
+
}
|
207
|
+
return nw;
|
208
|
+
}
|
209
|
+
return {done: cp(history.done), undone: cp(history.undone)};
|
209
210
|
},
|
210
211
|
matchBrackets: operation(function(){matchBrackets(true);}),
|
211
212
|
getTokenAt: operation(function(pos) {
|
@@ -374,6 +375,12 @@ window.CodeMirror = (function() {
|
|
374
375
|
for (var n = line; n; n = n.parent) n.height += diff;
|
375
376
|
}
|
376
377
|
|
378
|
+
function lineContent(line, wrapAt) {
|
379
|
+
if (!line.styles)
|
380
|
+
line.highlight(mode, line.stateAfter = getStateBefore(lineNo(line)), options.tabSize);
|
381
|
+
return line.getContent(options.tabSize, wrapAt, options.lineWrapping);
|
382
|
+
}
|
383
|
+
|
377
384
|
function setValue(code) {
|
378
385
|
var top = {line: 0, ch: 0};
|
379
386
|
updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},
|
@@ -572,11 +579,8 @@ window.CodeMirror = (function() {
|
|
572
579
|
e.dataTransfer.setData("Text", txt);
|
573
580
|
|
574
581
|
// Use dummy image instead of default browsers image.
|
575
|
-
if (
|
576
|
-
|
577
|
-
img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
|
578
|
-
e.dataTransfer.setDragImage(img, 0, 0);
|
579
|
-
}
|
582
|
+
if (e.dataTransfer.setDragImage)
|
583
|
+
e.dataTransfer.setDragImage(elt('img'), 0, 0);
|
580
584
|
}
|
581
585
|
|
582
586
|
function doHandleBinding(bound, dropShift) {
|
@@ -610,10 +614,11 @@ window.CodeMirror = (function() {
|
|
610
614
|
}, 50);
|
611
615
|
|
612
616
|
var name = keyNames[e_prop(e, "keyCode")], handled = false;
|
617
|
+
var flipCtrlCmd = opera && mac;
|
613
618
|
if (name == null || e.altGraphKey) return false;
|
614
619
|
if (e_prop(e, "altKey")) name = "Alt-" + name;
|
615
|
-
if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
|
616
|
-
if (e_prop(e, "metaKey")) name = "Cmd-" + name;
|
620
|
+
if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name;
|
621
|
+
if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name;
|
617
622
|
|
618
623
|
var stopped = false;
|
619
624
|
function stop() { stopped = true; }
|
@@ -689,7 +694,6 @@ window.CodeMirror = (function() {
|
|
689
694
|
focused = true;
|
690
695
|
if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
|
691
696
|
scroller.className += " CodeMirror-focused";
|
692
|
-
if (!leaveInputAlone) resetInput(true);
|
693
697
|
}
|
694
698
|
slowPoll();
|
695
699
|
restartBlink();
|
@@ -712,13 +716,16 @@ window.CodeMirror = (function() {
|
|
712
716
|
// Afterwards, set the selection to selFrom, selTo.
|
713
717
|
function updateLines(from, to, newText, selFrom, selTo) {
|
714
718
|
if (suppressEdits) return;
|
719
|
+
var old = [];
|
720
|
+
doc.iter(from.line, to.line + 1, function(line) {
|
721
|
+
old.push(newHL(line.text, line.markedSpans));
|
722
|
+
});
|
715
723
|
if (history) {
|
716
|
-
var old = [];
|
717
|
-
doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });
|
718
724
|
history.addChange(from.line, newText.length, old);
|
719
725
|
while (history.done.length > options.undoDepth) history.done.shift();
|
720
726
|
}
|
721
|
-
|
727
|
+
var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText);
|
728
|
+
updateLinesNoUndo(from, to, lines, selFrom, selTo);
|
722
729
|
}
|
723
730
|
function unredoHelper(from, to) {
|
724
731
|
if (!from.length) return;
|
@@ -726,11 +733,12 @@ window.CodeMirror = (function() {
|
|
726
733
|
for (var i = set.length - 1; i >= 0; i -= 1) {
|
727
734
|
var change = set[i];
|
728
735
|
var replaced = [], end = change.start + change.added;
|
729
|
-
doc.iter(change.start, end, function(line) { replaced.push(line.text); });
|
736
|
+
doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); });
|
730
737
|
out.push({start: change.start, added: change.old.length, old: replaced});
|
731
738
|
var pos = {line: change.start + change.old.length - 1,
|
732
|
-
ch: editEnd(replaced
|
733
|
-
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length},
|
739
|
+
ch: editEnd(hlText(lst(replaced)), hlText(lst(change.old)))};
|
740
|
+
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length},
|
741
|
+
change.old, pos, pos);
|
734
742
|
}
|
735
743
|
updateInput = true;
|
736
744
|
to.push(out);
|
@@ -738,66 +746,59 @@ window.CodeMirror = (function() {
|
|
738
746
|
function undo() {unredoHelper(history.done, history.undone);}
|
739
747
|
function redo() {unredoHelper(history.undone, history.done);}
|
740
748
|
|
741
|
-
function updateLinesNoUndo(from, to,
|
749
|
+
function updateLinesNoUndo(from, to, lines, selFrom, selTo) {
|
742
750
|
if (suppressEdits) return;
|
743
751
|
var recomputeMaxLength = false, maxLineLength = maxLine.text.length;
|
744
752
|
if (!options.lineWrapping)
|
745
753
|
doc.iter(from.line, to.line + 1, function(line) {
|
746
754
|
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
747
755
|
});
|
748
|
-
if (from.line != to.line ||
|
756
|
+
if (from.line != to.line || lines.length > 1) gutterDirty = true;
|
749
757
|
|
750
758
|
var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);
|
751
|
-
|
752
|
-
|
759
|
+
var lastHL = lst(lines);
|
760
|
+
|
761
|
+
// First adjust the line structure
|
762
|
+
if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") {
|
753
763
|
// This is a whole-line replace. Treated specially to make
|
754
764
|
// sure line objects move the way they are supposed to.
|
755
765
|
var added = [], prevLine = null;
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
} else lastLine.fixMarkStarts();
|
760
|
-
for (var i = 0, e = newText.length - 1; i < e; ++i)
|
761
|
-
added.push(Line.inheritMarks(newText[i], prevLine));
|
766
|
+
for (var i = 0, e = lines.length - 1; i < e; ++i)
|
767
|
+
added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
|
768
|
+
lastLine.update(lastLine.text, hlSpans(lastHL));
|
762
769
|
if (nlines) doc.remove(from.line, nlines, callbacks);
|
763
770
|
if (added.length) doc.insert(from.line, added);
|
764
771
|
} else if (firstLine == lastLine) {
|
765
|
-
if (
|
766
|
-
firstLine.
|
767
|
-
else {
|
768
|
-
|
769
|
-
|
770
|
-
firstLine.
|
771
|
-
|
772
|
-
for (var i = 1, e = newText.length - 1; i < e; ++i)
|
773
|
-
added.push(Line.inheritMarks(newText[i], firstLine));
|
774
|
-
added.push(lastLine);
|
772
|
+
if (lines.length == 1) {
|
773
|
+
firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + firstLine.text.slice(to.ch), hlSpans(lines[0]));
|
774
|
+
} else {
|
775
|
+
for (var added = [], i = 1, e = lines.length - 1; i < e; ++i)
|
776
|
+
added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
|
777
|
+
added.push(new Line(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL)));
|
778
|
+
firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
|
775
779
|
doc.insert(from.line + 1, added);
|
776
780
|
}
|
777
|
-
} else if (
|
778
|
-
firstLine.
|
779
|
-
lastLine.replace(null, to.ch, "");
|
780
|
-
firstLine.append(lastLine);
|
781
|
+
} else if (lines.length == 1) {
|
782
|
+
firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + lastLine.text.slice(to.ch), hlSpans(lines[0]));
|
781
783
|
doc.remove(from.line + 1, nlines, callbacks);
|
782
784
|
} else {
|
783
785
|
var added = [];
|
784
|
-
firstLine.
|
785
|
-
lastLine.
|
786
|
-
|
787
|
-
|
788
|
-
added.push(Line.inheritMarks(newText[i], firstLine));
|
786
|
+
firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
|
787
|
+
lastLine.update(hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL));
|
788
|
+
for (var i = 1, e = lines.length - 1; i < e; ++i)
|
789
|
+
added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
|
789
790
|
if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);
|
790
791
|
doc.insert(from.line + 1, added);
|
791
792
|
}
|
792
793
|
if (options.lineWrapping) {
|
793
794
|
var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
|
794
|
-
doc.iter(from.line, from.line +
|
795
|
+
doc.iter(from.line, from.line + lines.length, function(line) {
|
795
796
|
if (line.hidden) return;
|
796
797
|
var guess = Math.ceil(line.text.length / perLine) || 1;
|
797
798
|
if (guess != line.height) updateLineHeight(line, guess);
|
798
799
|
});
|
799
800
|
} else {
|
800
|
-
doc.iter(from.line, from.line +
|
801
|
+
doc.iter(from.line, from.line + lines.length, function(line) {
|
801
802
|
var l = line.text;
|
802
803
|
if (!line.hidden && l.length > maxLineLength) {
|
803
804
|
maxLine = line; maxLineLength = l.length; maxLineChanged = true;
|
@@ -807,26 +808,24 @@ window.CodeMirror = (function() {
|
|
807
808
|
if (recomputeMaxLength) updateMaxLine = true;
|
808
809
|
}
|
809
810
|
|
810
|
-
//
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
if (task < from.line) newWork.push(task);
|
816
|
-
else if (task > to.line) newWork.push(task + lendiff);
|
817
|
-
}
|
818
|
-
var hlEnd = from.line + Math.min(newText.length, 500);
|
819
|
-
highlightLines(from.line, hlEnd);
|
820
|
-
newWork.push(hlEnd);
|
821
|
-
work = newWork;
|
822
|
-
startWorker(100);
|
811
|
+
// Adjust frontier, schedule worker
|
812
|
+
frontier = Math.min(frontier, from.line);
|
813
|
+
startWorker(400);
|
814
|
+
|
815
|
+
var lendiff = lines.length - nlines - 1;
|
823
816
|
// Remember that these lines changed, for updating the display
|
824
817
|
changes.push({from: from.line, to: to.line + 1, diff: lendiff});
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
818
|
+
if (options.onChange) {
|
819
|
+
// Normalize lines to contain only strings, since that's what
|
820
|
+
// the change event handler expects
|
821
|
+
for (var i = 0; i < lines.length; ++i)
|
822
|
+
if (typeof lines[i] != "string") lines[i] = lines[i].text;
|
823
|
+
var changeObj = {from: from, to: to, text: lines};
|
824
|
+
if (textChanged) {
|
825
|
+
for (var cur = textChanged; cur.next; cur = cur.next) {}
|
826
|
+
cur.next = changeObj;
|
827
|
+
} else textChanged = changeObj;
|
828
|
+
}
|
830
829
|
|
831
830
|
// Update the selection
|
832
831
|
function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
|
@@ -888,7 +887,7 @@ window.CodeMirror = (function() {
|
|
888
887
|
var line = pos.line + code.length - (to.line - from.line) - 1;
|
889
888
|
var ch = pos.ch;
|
890
889
|
if (pos.line == to.line)
|
891
|
-
ch += code
|
890
|
+
ch += lst(code).length - (to.ch - (to.line == from.line ? from.ch : 0));
|
892
891
|
return {line: line, ch: ch};
|
893
892
|
}
|
894
893
|
var end;
|
@@ -906,7 +905,7 @@ window.CodeMirror = (function() {
|
|
906
905
|
});
|
907
906
|
}
|
908
907
|
function replaceRange1(code, from, to, computeSel) {
|
909
|
-
var endch = code.length == 1 ? code[0].length + from.ch : code
|
908
|
+
var endch = code.length == 1 ? code[0].length + from.ch : lst(code).length;
|
910
909
|
var newSel = computeSel({line: from.line + code.length - 1, ch: endch});
|
911
910
|
updateLines(from, to, code, newSel.from, newSel.to);
|
912
911
|
}
|
@@ -926,21 +925,17 @@ window.CodeMirror = (function() {
|
|
926
925
|
function slowPoll() {
|
927
926
|
if (pollingFast) return;
|
928
927
|
poll.set(options.pollInterval, function() {
|
929
|
-
startOperation();
|
930
928
|
readInput();
|
931
929
|
if (focused) slowPoll();
|
932
|
-
endOperation();
|
933
930
|
});
|
934
931
|
}
|
935
932
|
function fastPoll() {
|
936
933
|
var missed = false;
|
937
934
|
pollingFast = true;
|
938
935
|
function p() {
|
939
|
-
startOperation();
|
940
936
|
var changed = readInput();
|
941
937
|
if (!changed && !missed) {missed = true; poll.set(60, p);}
|
942
938
|
else {pollingFast = false; slowPoll();}
|
943
|
-
endOperation();
|
944
939
|
}
|
945
940
|
poll.set(20, p);
|
946
941
|
}
|
@@ -952,9 +947,10 @@ window.CodeMirror = (function() {
|
|
952
947
|
// supported or compatible enough yet to rely on.)
|
953
948
|
var prevInput = "";
|
954
949
|
function readInput() {
|
955
|
-
if (
|
950
|
+
if (!focused || hasSelection(input) || options.readOnly) return false;
|
956
951
|
var text = input.value;
|
957
952
|
if (text == prevInput) return false;
|
953
|
+
if (!nestedOperation) startOperation();
|
958
954
|
shiftSelecting = null;
|
959
955
|
var same = 0, l = Math.min(prevInput.length, text.length);
|
960
956
|
while (same < l && prevInput[same] == text[same]) ++same;
|
@@ -965,6 +961,7 @@ window.CodeMirror = (function() {
|
|
965
961
|
replaceSelection(text.slice(same), "end");
|
966
962
|
if (text.length > 1000) { input.value = prevInput = ""; }
|
967
963
|
else prevInput = text;
|
964
|
+
if (!nestedOperation) endOperation();
|
968
965
|
return true;
|
969
966
|
}
|
970
967
|
function resetInput(user) {
|
@@ -1090,6 +1087,7 @@ window.CodeMirror = (function() {
|
|
1090
1087
|
});
|
1091
1088
|
showingFrom = from; showingTo = to;
|
1092
1089
|
displayOffset = heightAtLine(doc, from);
|
1090
|
+
startWorker(100);
|
1093
1091
|
|
1094
1092
|
// Since this is all rather error prone, it is honoured with the
|
1095
1093
|
// only assertion in the whole file.
|
@@ -1176,7 +1174,7 @@ window.CodeMirror = (function() {
|
|
1176
1174
|
if (!nextIntact || nextIntact.from > j) {
|
1177
1175
|
if (line.hidden) var lineElement = elt("pre");
|
1178
1176
|
else {
|
1179
|
-
var lineElement = line
|
1177
|
+
var lineElement = lineContent(line);
|
1180
1178
|
if (line.className) lineElement.className = line.className;
|
1181
1179
|
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
1182
1180
|
if (line.bgClassName) {
|
@@ -1460,7 +1458,7 @@ window.CodeMirror = (function() {
|
|
1460
1458
|
var indentString = "", pos = 0;
|
1461
1459
|
if (options.indentWithTabs)
|
1462
1460
|
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
1463
|
-
|
1461
|
+
if (pos < indentation) indentString += spaceStr(indentation - pos);
|
1464
1462
|
|
1465
1463
|
if (indentString != curSpaceString)
|
1466
1464
|
replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
|
@@ -1469,8 +1467,8 @@ window.CodeMirror = (function() {
|
|
1469
1467
|
function loadMode() {
|
1470
1468
|
mode = CodeMirror.getMode(options, options.mode);
|
1471
1469
|
doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
|
1472
|
-
|
1473
|
-
startWorker();
|
1470
|
+
frontier = 0;
|
1471
|
+
startWorker(100);
|
1474
1472
|
}
|
1475
1473
|
function gutterChanged() {
|
1476
1474
|
var visible = options.gutter || options.lineNumbers;
|
@@ -1497,13 +1495,6 @@ window.CodeMirror = (function() {
|
|
1497
1495
|
}
|
1498
1496
|
changes.push({from: 0, to: doc.size});
|
1499
1497
|
}
|
1500
|
-
function makeTab(col) {
|
1501
|
-
var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
|
1502
|
-
if (cached) return cached;
|
1503
|
-
for (var str = "", i = 0; i < w; ++i) str += " ";
|
1504
|
-
var span = elt("span", str, "cm-tab");
|
1505
|
-
return (tabCache[w] = {element: span, width: w});
|
1506
|
-
}
|
1507
1498
|
function themeChanged() {
|
1508
1499
|
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
|
1509
1500
|
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
|
@@ -1514,74 +1505,71 @@ window.CodeMirror = (function() {
|
|
1514
1505
|
(style ? " cm-keymap-" + style : "");
|
1515
1506
|
}
|
1516
1507
|
|
1517
|
-
function TextMarker() { this.
|
1508
|
+
function TextMarker(type, style) { this.lines = []; this.type = type; if (style) this.style = style; }
|
1518
1509
|
TextMarker.prototype.clear = operation(function() {
|
1519
1510
|
var min = Infinity, max = -Infinity;
|
1520
|
-
for (var i = 0
|
1521
|
-
var line = this.
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1511
|
+
for (var i = 0; i < this.lines.length; ++i) {
|
1512
|
+
var line = this.lines[i];
|
1513
|
+
var span = getMarkedSpanFor(line.markedSpans, this, true);
|
1514
|
+
if (span.from != null || span.to != null) {
|
1515
|
+
var lineN = lineNo(line);
|
1516
|
+
min = Math.min(min, lineN); max = Math.max(max, lineN);
|
1517
|
+
}
|
1527
1518
|
}
|
1528
1519
|
if (min != Infinity)
|
1529
1520
|
changes.push({from: min, to: max + 1});
|
1521
|
+
this.lines.length = 0;
|
1530
1522
|
});
|
1531
1523
|
TextMarker.prototype.find = function() {
|
1532
1524
|
var from, to;
|
1533
|
-
for (var i = 0
|
1534
|
-
var line = this.
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
if (found != null) {
|
1541
|
-
if (mark.from != null) from = {line: found, ch: mark.from};
|
1542
|
-
if (mark.to != null) to = {line: found, ch: mark.to};
|
1543
|
-
}
|
1544
|
-
}
|
1545
|
-
}
|
1525
|
+
for (var i = 0; i < this.lines.length; ++i) {
|
1526
|
+
var line = this.lines[i];
|
1527
|
+
var span = getMarkedSpanFor(line.markedSpans, this);
|
1528
|
+
if (span.from != null || span.to != null) {
|
1529
|
+
var found = lineNo(line);
|
1530
|
+
if (span.from != null) from = {line: found, ch: span.from};
|
1531
|
+
if (span.to != null) to = {line: found, ch: span.to};
|
1546
1532
|
}
|
1547
1533
|
}
|
1548
|
-
|
1534
|
+
if (this.type == "bookmark") return from;
|
1535
|
+
return from && {from: from, to: to};
|
1549
1536
|
};
|
1550
1537
|
|
1551
|
-
function markText(from, to, className) {
|
1538
|
+
function markText(from, to, className, options) {
|
1552
1539
|
from = clipPos(from); to = clipPos(to);
|
1553
|
-
var
|
1554
|
-
if (
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
}
|
1540
|
+
var marker = new TextMarker("range", className);
|
1541
|
+
if (options) for (var opt in options) if (options.hasOwnProperty(opt))
|
1542
|
+
marker[opt] = options[opt];
|
1543
|
+
var curLine = from.line;
|
1544
|
+
doc.iter(curLine, to.line + 1, function(line) {
|
1545
|
+
var span = {from: curLine == from.line ? from.ch : null,
|
1546
|
+
to: curLine == to.line ? to.ch : null,
|
1547
|
+
marker: marker};
|
1548
|
+
(line.markedSpans || (line.markedSpans = [])).push(span);
|
1549
|
+
marker.lines.push(line);
|
1550
|
+
++curLine;
|
1551
|
+
});
|
1565
1552
|
changes.push({from: from.line, to: to.line + 1});
|
1566
|
-
return
|
1553
|
+
return marker;
|
1567
1554
|
}
|
1568
1555
|
|
1569
1556
|
function setBookmark(pos) {
|
1570
1557
|
pos = clipPos(pos);
|
1571
|
-
var
|
1572
|
-
|
1573
|
-
|
1558
|
+
var marker = new TextMarker("bookmark"), line = getLine(pos.line);
|
1559
|
+
var span = {from: pos.ch, to: pos.ch, marker: marker};
|
1560
|
+
(line.markedSpans || (line.markedSpans = [])).push(span);
|
1561
|
+
marker.lines.push(line);
|
1562
|
+
return marker;
|
1574
1563
|
}
|
1575
1564
|
|
1576
1565
|
function findMarksAt(pos) {
|
1577
1566
|
pos = clipPos(pos);
|
1578
|
-
var markers = [],
|
1579
|
-
if (
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
markers.push(m.marker || m);
|
1567
|
+
var markers = [], spans = getLine(pos.line).markedSpans;
|
1568
|
+
if (spans) for (var i = 0; i < spans.length; ++i) {
|
1569
|
+
var span = spans[i];
|
1570
|
+
if ((span.from == null || span.from <= pos.ch) &&
|
1571
|
+
(span.to == null || span.to >= pos.ch))
|
1572
|
+
markers.push(span.marker);
|
1585
1573
|
}
|
1586
1574
|
return markers;
|
1587
1575
|
}
|
@@ -1656,40 +1644,11 @@ window.CodeMirror = (function() {
|
|
1656
1644
|
markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
|
1657
1645
|
}
|
1658
1646
|
|
1659
|
-
// These are used to go from pixel positions to character
|
1660
|
-
// positions, taking varying character widths into account.
|
1661
|
-
function charFromX(line, x) {
|
1662
|
-
if (x <= 0) return 0;
|
1663
|
-
var lineObj = getLine(line), text = lineObj.text;
|
1664
|
-
function getX(len) {
|
1665
|
-
return measureLine(lineObj, len).left;
|
1666
|
-
}
|
1667
|
-
var from = 0, fromX = 0, to = text.length, toX;
|
1668
|
-
// Guess a suitable upper bound for our search.
|
1669
|
-
var estimated = Math.min(to, Math.ceil(x / charWidth()));
|
1670
|
-
for (;;) {
|
1671
|
-
var estX = getX(estimated);
|
1672
|
-
if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
|
1673
|
-
else {toX = estX; to = estimated; break;}
|
1674
|
-
}
|
1675
|
-
if (x > toX) return to;
|
1676
|
-
// Try to guess a suitable lower bound as well.
|
1677
|
-
estimated = Math.floor(to * 0.8); estX = getX(estimated);
|
1678
|
-
if (estX < x) {from = estimated; fromX = estX;}
|
1679
|
-
// Do a binary search between these bounds.
|
1680
|
-
for (;;) {
|
1681
|
-
if (to - from <= 1) return (toX - x > x - fromX) ? from : to;
|
1682
|
-
var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
|
1683
|
-
if (middleX > x) {to = middle; toX = middleX;}
|
1684
|
-
else {from = middle; fromX = middleX;}
|
1685
|
-
}
|
1686
|
-
}
|
1687
|
-
|
1688
1647
|
function measureLine(line, ch) {
|
1689
1648
|
if (ch == 0) return {top: 0, left: 0};
|
1690
1649
|
var wbr = options.lineWrapping && ch < line.text.length &&
|
1691
1650
|
spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
|
1692
|
-
var pre = line
|
1651
|
+
var pre = lineContent(line, ch);
|
1693
1652
|
removeChildrenAndAdd(measure, pre);
|
1694
1653
|
var anchor = pre.anchor;
|
1695
1654
|
var top = anchor.offsetTop, left = anchor.offsetLeft;
|
@@ -1800,6 +1759,7 @@ window.CodeMirror = (function() {
|
|
1800
1759
|
var offL = eltOffset(lineSpace, true);
|
1801
1760
|
return coordsChar(x - offL.left, y - offL.top);
|
1802
1761
|
}
|
1762
|
+
var detectingSelectAll;
|
1803
1763
|
function onContextMenu(e) {
|
1804
1764
|
var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
|
1805
1765
|
if (!pos || opera) return; // Opera is difficult.
|
@@ -1811,19 +1771,30 @@ window.CodeMirror = (function() {
|
|
1811
1771
|
input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
|
1812
1772
|
"px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
|
1813
1773
|
"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
|
1814
|
-
leaveInputAlone = true;
|
1815
|
-
var val = input.value = getSelection();
|
1816
1774
|
focusInput();
|
1817
|
-
|
1775
|
+
resetInput(true);
|
1776
|
+
// Adds "Select all" to context menu in FF
|
1777
|
+
if (posEq(sel.from, sel.to)) input.value = prevInput = " ";
|
1778
|
+
|
1818
1779
|
function rehide() {
|
1819
|
-
var newVal = splitLines(input.value).join("\n");
|
1820
|
-
if (newVal != val && !options.readOnly) operation(replaceSelection)(newVal, "end");
|
1821
1780
|
inputDiv.style.position = "relative";
|
1822
1781
|
input.style.cssText = oldCSS;
|
1823
1782
|
if (ie_lt9) scrollbar.scrollTop = scrollPos;
|
1824
|
-
leaveInputAlone = false;
|
1825
|
-
resetInput(true);
|
1826
1783
|
slowPoll();
|
1784
|
+
|
1785
|
+
// Try to detect the user choosing select-all
|
1786
|
+
if (input.selectionStart != null) {
|
1787
|
+
clearTimeout(detectingSelectAll);
|
1788
|
+
var extval = input.value = " " + (posEq(sel.from, sel.to) ? "" : input.value), i = 0;
|
1789
|
+
prevInput = " ";
|
1790
|
+
input.selectionStart = 1; input.selectionEnd = extval.length;
|
1791
|
+
detectingSelectAll = setTimeout(function poll(){
|
1792
|
+
if (prevInput == " " && input.selectionStart == 0)
|
1793
|
+
operation(commands.selectAll)(instance);
|
1794
|
+
else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
|
1795
|
+
else resetInput();
|
1796
|
+
}, 200);
|
1797
|
+
}
|
1827
1798
|
}
|
1828
1799
|
|
1829
1800
|
if (gecko) {
|
@@ -1907,70 +1878,39 @@ window.CodeMirror = (function() {
|
|
1907
1878
|
return minline;
|
1908
1879
|
}
|
1909
1880
|
function getStateBefore(n) {
|
1910
|
-
var
|
1881
|
+
var pos = findStartLine(n), state = pos && getLine(pos-1).stateAfter;
|
1911
1882
|
if (!state) state = startState(mode);
|
1912
1883
|
else state = copyState(mode, state);
|
1913
|
-
doc.iter(
|
1914
|
-
line.
|
1915
|
-
line.stateAfter = copyState(mode, state);
|
1884
|
+
doc.iter(pos, n, function(line) {
|
1885
|
+
line.process(mode, state, options.tabSize);
|
1886
|
+
line.stateAfter = (pos == n - 1 || pos % 5 == 0) ? copyState(mode, state) : null;
|
1916
1887
|
});
|
1917
|
-
if (start < n) changes.push({from: start, to: n});
|
1918
|
-
if (n < doc.size && !getLine(n).stateAfter) work.push(n);
|
1919
1888
|
return state;
|
1920
1889
|
}
|
1921
|
-
function highlightLines(start, end) {
|
1922
|
-
var state = getStateBefore(start);
|
1923
|
-
doc.iter(start, end, function(line) {
|
1924
|
-
line.highlight(mode, state, options.tabSize);
|
1925
|
-
line.stateAfter = copyState(mode, state);
|
1926
|
-
});
|
1927
|
-
}
|
1928
1890
|
function highlightWorker() {
|
1929
|
-
|
1930
|
-
var
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
var start = findStartLine(task), state = start && getLine(start-1).stateAfter;
|
1936
|
-
if (state) state = copyState(mode, state);
|
1937
|
-
else state = startState(mode);
|
1938
|
-
|
1939
|
-
var unchanged = 0, compare = mode.compareStates, realChange = false,
|
1940
|
-
i = start, bail = false;
|
1941
|
-
doc.iter(i, doc.size, function(line) {
|
1942
|
-
var hadState = line.stateAfter;
|
1943
|
-
if (+new Date > end) {
|
1944
|
-
work.push(i);
|
1945
|
-
startWorker(options.workDelay);
|
1946
|
-
if (realChange) changes.push({from: task, to: i + 1});
|
1947
|
-
return (bail = true);
|
1948
|
-
}
|
1949
|
-
var changed = line.highlight(mode, state, options.tabSize);
|
1950
|
-
if (changed) realChange = true;
|
1891
|
+
if (frontier >= showingTo) return;
|
1892
|
+
var end = +new Date + options.workTime, state = copyState(mode, getStateBefore(frontier));
|
1893
|
+
var startFrontier = frontier;
|
1894
|
+
doc.iter(frontier, showingTo, function(line) {
|
1895
|
+
if (frontier >= showingFrom) { // Visible
|
1896
|
+
line.highlight(mode, state, options.tabSize);
|
1951
1897
|
line.stateAfter = copyState(mode, state);
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
});
|
1965
|
-
if (bail) return;
|
1966
|
-
if (realChange) changes.push({from: task, to: i + 1});
|
1967
|
-
}
|
1968
|
-
if (foundWork && options.onHighlightComplete)
|
1969
|
-
options.onHighlightComplete(instance);
|
1898
|
+
} else {
|
1899
|
+
line.process(mode, state, options.tabSize);
|
1900
|
+
line.stateAfter = frontier % 5 == 0 ? copyState(mode, state) : null;
|
1901
|
+
}
|
1902
|
+
++frontier;
|
1903
|
+
if (+new Date > end) {
|
1904
|
+
startWorker(options.workDelay);
|
1905
|
+
return true;
|
1906
|
+
}
|
1907
|
+
});
|
1908
|
+
if (showingTo > startFrontier && frontier >= showingFrom)
|
1909
|
+
operation(function() {changes.push({from: startFrontier, to: frontier});})();
|
1970
1910
|
}
|
1971
1911
|
function startWorker(time) {
|
1972
|
-
if (
|
1973
|
-
|
1912
|
+
if (frontier < showingTo)
|
1913
|
+
highlight.set(time, highlightWorker);
|
1974
1914
|
}
|
1975
1915
|
|
1976
1916
|
// Operations are used to wrap changes in such a way that each
|
@@ -2005,8 +1945,7 @@ window.CodeMirror = (function() {
|
|
2005
1945
|
if (newScrollPos) scrollCursorIntoView();
|
2006
1946
|
if (selectionChanged) restartBlink();
|
2007
1947
|
|
2008
|
-
if (focused &&
|
2009
|
-
(updateInput === true || (updateInput !== false && selectionChanged)))
|
1948
|
+
if (focused && (updateInput === true || (updateInput !== false && selectionChanged)))
|
2010
1949
|
resetInput(userSelChange);
|
2011
1950
|
|
2012
1951
|
if (selectionChanged && options.matchBrackets)
|
@@ -2070,7 +2009,6 @@ window.CodeMirror = (function() {
|
|
2070
2009
|
onCursorActivity: null,
|
2071
2010
|
onViewportChange: null,
|
2072
2011
|
onGutterClick: null,
|
2073
|
-
onHighlightComplete: null,
|
2074
2012
|
onUpdate: null,
|
2075
2013
|
onFocus: null, onBlur: null, onScroll: null,
|
2076
2014
|
matchBrackets: false,
|
@@ -2113,7 +2051,13 @@ window.CodeMirror = (function() {
|
|
2113
2051
|
var spec = CodeMirror.resolveMode(spec);
|
2114
2052
|
var mfactory = modes[spec.name];
|
2115
2053
|
if (!mfactory) return CodeMirror.getMode(options, "text/plain");
|
2116
|
-
|
2054
|
+
var modeObj = mfactory(options, spec);
|
2055
|
+
if (modeExtensions.hasOwnProperty(spec.name)) {
|
2056
|
+
var exts = modeExtensions[spec.name];
|
2057
|
+
for (var prop in exts) if (exts.hasOwnProperty(prop)) modeObj[prop] = exts[prop];
|
2058
|
+
}
|
2059
|
+
modeObj.name = spec.name;
|
2060
|
+
return modeObj;
|
2117
2061
|
};
|
2118
2062
|
CodeMirror.listModes = function() {
|
2119
2063
|
var list = [];
|
@@ -2133,6 +2077,13 @@ window.CodeMirror = (function() {
|
|
2133
2077
|
extensions[name] = func;
|
2134
2078
|
};
|
2135
2079
|
|
2080
|
+
var modeExtensions = CodeMirror.modeExtensions = {};
|
2081
|
+
CodeMirror.extendMode = function(mode, properties) {
|
2082
|
+
var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
|
2083
|
+
for (var prop in properties) if (properties.hasOwnProperty(prop))
|
2084
|
+
exts[prop] = properties[prop];
|
2085
|
+
};
|
2086
|
+
|
2136
2087
|
var commands = CodeMirror.commands = {
|
2137
2088
|
selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
|
2138
2089
|
killLine: function(cm) {
|
@@ -2335,6 +2286,14 @@ window.CodeMirror = (function() {
|
|
2335
2286
|
return mode.startState ? mode.startState(a1, a2) : true;
|
2336
2287
|
}
|
2337
2288
|
CodeMirror.startState = startState;
|
2289
|
+
CodeMirror.innerMode = function(mode, state) {
|
2290
|
+
while (mode.innerMode) {
|
2291
|
+
var info = mode.innerMode(state);
|
2292
|
+
state = info.state;
|
2293
|
+
mode = info.mode;
|
2294
|
+
}
|
2295
|
+
return info || {mode: mode, state: state};
|
2296
|
+
};
|
2338
2297
|
|
2339
2298
|
// The character stream used by a mode's parser.
|
2340
2299
|
function StringStream(string, tabSize) {
|
@@ -2383,6 +2342,7 @@ window.CodeMirror = (function() {
|
|
2383
2342
|
}
|
2384
2343
|
} else {
|
2385
2344
|
var match = this.string.slice(this.pos).match(pattern);
|
2345
|
+
if (match && match.index > 0) return null;
|
2386
2346
|
if (match && consume !== false) this.pos += match[0].length;
|
2387
2347
|
return match;
|
2388
2348
|
}
|
@@ -2391,69 +2351,123 @@ window.CodeMirror = (function() {
|
|
2391
2351
|
};
|
2392
2352
|
CodeMirror.StringStream = StringStream;
|
2393
2353
|
|
2394
|
-
function
|
2395
|
-
this.from = from; this.to = to; this.
|
2354
|
+
function MarkedSpan(from, to, marker) {
|
2355
|
+
this.from = from; this.to = to; this.marker = marker;
|
2396
2356
|
}
|
2397
|
-
MarkedText.prototype = {
|
2398
|
-
attach: function(line) { this.marker.set.push(line); },
|
2399
|
-
detach: function(line) {
|
2400
|
-
var ix = indexOf(this.marker.set, line);
|
2401
|
-
if (ix > -1) this.marker.set.splice(ix, 1);
|
2402
|
-
},
|
2403
|
-
split: function(pos, lenBefore) {
|
2404
|
-
if (this.to <= pos && this.to != null) return null;
|
2405
|
-
var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
|
2406
|
-
var to = this.to == null ? null : this.to - pos + lenBefore;
|
2407
|
-
return new MarkedText(from, to, this.style, this.marker);
|
2408
|
-
},
|
2409
|
-
dup: function() { return new MarkedText(null, null, this.style, this.marker); },
|
2410
|
-
clipTo: function(fromOpen, from, toOpen, to, diff) {
|
2411
|
-
if (fromOpen && to > this.from && (to < this.to || this.to == null))
|
2412
|
-
this.from = null;
|
2413
|
-
else if (this.from != null && this.from >= from)
|
2414
|
-
this.from = Math.max(to, this.from) + diff;
|
2415
|
-
if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
|
2416
|
-
this.to = null;
|
2417
|
-
else if (this.to != null && this.to > from)
|
2418
|
-
this.to = to < this.to ? this.to + diff : from;
|
2419
|
-
},
|
2420
|
-
isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
|
2421
|
-
sameSet: function(x) { return this.marker == x.marker; }
|
2422
|
-
};
|
2423
2357
|
|
2424
|
-
function
|
2425
|
-
|
2358
|
+
function getMarkedSpanFor(spans, marker, del) {
|
2359
|
+
if (spans) for (var i = 0; i < spans.length; ++i) {
|
2360
|
+
var span = spans[i];
|
2361
|
+
if (span.marker == marker) {
|
2362
|
+
if (del) spans.splice(i, 1);
|
2363
|
+
return span;
|
2364
|
+
}
|
2365
|
+
}
|
2426
2366
|
}
|
2427
|
-
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2367
|
+
|
2368
|
+
function markedSpansBefore(old, startCh, endCh) {
|
2369
|
+
if (old) for (var i = 0, nw; i < old.length; ++i) {
|
2370
|
+
var span = old[i], marker = span.marker;
|
2371
|
+
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
|
2372
|
+
if (startsBefore || marker.type == "bookmark" && span.from == startCh && span.from != endCh) {
|
2373
|
+
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
|
2374
|
+
(nw || (nw = [])).push({from: span.from,
|
2375
|
+
to: endsAfter ? null : span.to,
|
2376
|
+
marker: marker});
|
2434
2377
|
}
|
2435
|
-
}
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2378
|
+
}
|
2379
|
+
return nw;
|
2380
|
+
}
|
2381
|
+
|
2382
|
+
function markedSpansAfter(old, endCh) {
|
2383
|
+
if (old) for (var i = 0, nw; i < old.length; ++i) {
|
2384
|
+
var span = old[i], marker = span.marker;
|
2385
|
+
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
|
2386
|
+
if (endsAfter || marker.type == "bookmark" && span.from == endCh) {
|
2387
|
+
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
|
2388
|
+
(nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
|
2389
|
+
to: span.to == null ? null : span.to - endCh,
|
2390
|
+
marker: marker});
|
2442
2391
|
}
|
2443
|
-
}
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2392
|
+
}
|
2393
|
+
return nw;
|
2394
|
+
}
|
2395
|
+
|
2396
|
+
function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) {
|
2397
|
+
if (!oldFirst && !oldLast) return newText;
|
2398
|
+
// Get the spans that 'stick out' on both sides
|
2399
|
+
var first = markedSpansBefore(oldFirst, startCh);
|
2400
|
+
var last = markedSpansAfter(oldLast, endCh);
|
2401
|
+
|
2402
|
+
// Next, merge those two ends
|
2403
|
+
var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0);
|
2404
|
+
if (first) {
|
2405
|
+
// Fix up .to properties of first
|
2406
|
+
for (var i = 0; i < first.length; ++i) {
|
2407
|
+
var span = first[i];
|
2408
|
+
if (span.to == null) {
|
2409
|
+
var found = getMarkedSpanFor(last, span.marker);
|
2410
|
+
if (!found) span.to = startCh;
|
2411
|
+
else if (sameLine) span.to = found.to == null ? null : found.to + offset;
|
2412
|
+
}
|
2454
2413
|
}
|
2455
2414
|
}
|
2456
|
-
|
2415
|
+
if (last) {
|
2416
|
+
// Fix up .from in last (or move them into first in case of sameLine)
|
2417
|
+
for (var i = 0; i < last.length; ++i) {
|
2418
|
+
var span = last[i];
|
2419
|
+
if (span.to != null) span.to += offset;
|
2420
|
+
if (span.from == null) {
|
2421
|
+
var found = getMarkedSpanFor(first, span.marker);
|
2422
|
+
if (!found) {
|
2423
|
+
span.from = offset;
|
2424
|
+
if (sameLine) (first || (first = [])).push(span);
|
2425
|
+
}
|
2426
|
+
} else {
|
2427
|
+
span.from += offset;
|
2428
|
+
if (sameLine) (first || (first = [])).push(span);
|
2429
|
+
}
|
2430
|
+
}
|
2431
|
+
}
|
2432
|
+
|
2433
|
+
var newMarkers = [newHL(newText[0], first)];
|
2434
|
+
if (!sameLine) {
|
2435
|
+
// Fill gap with whole-line-spans
|
2436
|
+
var gap = newText.length - 2, gapMarkers;
|
2437
|
+
if (gap > 0 && first)
|
2438
|
+
for (var i = 0; i < first.length; ++i)
|
2439
|
+
if (first[i].to == null)
|
2440
|
+
(gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
|
2441
|
+
for (var i = 0; i < gap; ++i)
|
2442
|
+
newMarkers.push(newHL(newText[i+1], gapMarkers));
|
2443
|
+
newMarkers.push(newHL(lst(newText), last));
|
2444
|
+
}
|
2445
|
+
return newMarkers;
|
2446
|
+
}
|
2447
|
+
|
2448
|
+
// hl stands for history-line, a data structure that can be either a
|
2449
|
+
// string (line without markers) or a {text, markedSpans} object.
|
2450
|
+
function hlText(val) { return typeof val == "string" ? val : val.text; }
|
2451
|
+
function hlSpans(val) { return typeof val == "string" ? null : val.markedSpans; }
|
2452
|
+
function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
|
2453
|
+
|
2454
|
+
function detachMarkedSpans(line) {
|
2455
|
+
var spans = line.markedSpans;
|
2456
|
+
if (!spans) return;
|
2457
|
+
for (var i = 0; i < spans.length; ++i) {
|
2458
|
+
var lines = spans[i].marker.lines;
|
2459
|
+
var ix = indexOf(lines, line);
|
2460
|
+
lines.splice(ix, 1);
|
2461
|
+
}
|
2462
|
+
line.markedSpans = null;
|
2463
|
+
}
|
2464
|
+
|
2465
|
+
function attachMarkedSpans(line, spans) {
|
2466
|
+
if (!spans) return;
|
2467
|
+
for (var i = 0; i < spans.length; ++i)
|
2468
|
+
var marker = spans[i].marker.lines.push(line);
|
2469
|
+
line.markedSpans = spans;
|
2470
|
+
}
|
2457
2471
|
|
2458
2472
|
// When measuring the position of the end of a line, different
|
2459
2473
|
// browsers require different approaches. If an empty span is added,
|
@@ -2467,142 +2481,32 @@ window.CodeMirror = (function() {
|
|
2467
2481
|
|
2468
2482
|
// Line objects. These hold state related to a line, including
|
2469
2483
|
// highlighting info (the styles array).
|
2470
|
-
function Line(text,
|
2471
|
-
this.styles = styles || [text, null];
|
2484
|
+
function Line(text, markedSpans) {
|
2472
2485
|
this.text = text;
|
2473
2486
|
this.height = 1;
|
2487
|
+
attachMarkedSpans(this, markedSpans);
|
2474
2488
|
}
|
2475
|
-
Line.inheritMarks = function(text, orig) {
|
2476
|
-
var ln = new Line(text), mk = orig && orig.marked;
|
2477
|
-
if (mk) {
|
2478
|
-
for (var i = 0; i < mk.length; ++i) {
|
2479
|
-
if (mk[i].to == null && mk[i].style) {
|
2480
|
-
var newmk = ln.marked || (ln.marked = []), mark = mk[i];
|
2481
|
-
var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);
|
2482
|
-
}
|
2483
|
-
}
|
2484
|
-
}
|
2485
|
-
return ln;
|
2486
|
-
};
|
2487
2489
|
Line.prototype = {
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
copyStyles(to, this.text.length, this.styles, st);
|
2494
|
-
this.styles = st;
|
2495
|
-
this.text = this.text.slice(0, from) + text + this.text.slice(to);
|
2496
|
-
this.stateAfter = null;
|
2497
|
-
if (mk) {
|
2498
|
-
var diff = text.length - (to - from);
|
2499
|
-
for (var i = 0; i < mk.length; ++i) {
|
2500
|
-
var mark = mk[i];
|
2501
|
-
mark.clipTo(from == null, from || 0, to_ == null, to, diff);
|
2502
|
-
if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}
|
2503
|
-
}
|
2504
|
-
}
|
2505
|
-
},
|
2506
|
-
// Split a part off a line, keeping styles and markers intact.
|
2507
|
-
split: function(pos, textBefore) {
|
2508
|
-
var st = [textBefore, null], mk = this.marked;
|
2509
|
-
copyStyles(pos, this.text.length, this.styles, st);
|
2510
|
-
var taken = new Line(textBefore + this.text.slice(pos), st);
|
2511
|
-
if (mk) {
|
2512
|
-
for (var i = 0; i < mk.length; ++i) {
|
2513
|
-
var mark = mk[i];
|
2514
|
-
var newmark = mark.split(pos, textBefore.length);
|
2515
|
-
if (newmark) {
|
2516
|
-
if (!taken.marked) taken.marked = [];
|
2517
|
-
taken.marked.push(newmark); newmark.attach(taken);
|
2518
|
-
if (newmark == mark) mk.splice(i--, 1);
|
2519
|
-
}
|
2520
|
-
}
|
2521
|
-
}
|
2522
|
-
return taken;
|
2523
|
-
},
|
2524
|
-
append: function(line) {
|
2525
|
-
var mylen = this.text.length, mk = line.marked, mymk = this.marked;
|
2526
|
-
this.text += line.text;
|
2527
|
-
copyStyles(0, line.text.length, line.styles, this.styles);
|
2528
|
-
if (mymk) {
|
2529
|
-
for (var i = 0; i < mymk.length; ++i)
|
2530
|
-
if (mymk[i].to == null) mymk[i].to = mylen;
|
2531
|
-
}
|
2532
|
-
if (mk && mk.length) {
|
2533
|
-
if (!mymk) this.marked = mymk = [];
|
2534
|
-
outer: for (var i = 0; i < mk.length; ++i) {
|
2535
|
-
var mark = mk[i];
|
2536
|
-
if (!mark.from) {
|
2537
|
-
for (var j = 0; j < mymk.length; ++j) {
|
2538
|
-
var mymark = mymk[j];
|
2539
|
-
if (mymark.to == mylen && mymark.sameSet(mark)) {
|
2540
|
-
mymark.to = mark.to == null ? null : mark.to + mylen;
|
2541
|
-
if (mymark.isDead()) {
|
2542
|
-
mymark.detach(this);
|
2543
|
-
mk.splice(i--, 1);
|
2544
|
-
}
|
2545
|
-
continue outer;
|
2546
|
-
}
|
2547
|
-
}
|
2548
|
-
}
|
2549
|
-
mymk.push(mark);
|
2550
|
-
mark.attach(this);
|
2551
|
-
mark.from += mylen;
|
2552
|
-
if (mark.to != null) mark.to += mylen;
|
2553
|
-
}
|
2554
|
-
}
|
2555
|
-
},
|
2556
|
-
fixMarkEnds: function(other) {
|
2557
|
-
var mk = this.marked, omk = other.marked;
|
2558
|
-
if (!mk) return;
|
2559
|
-
outer: for (var i = 0; i < mk.length; ++i) {
|
2560
|
-
var mark = mk[i], close = mark.to == null;
|
2561
|
-
if (close && omk) {
|
2562
|
-
for (var j = 0; j < omk.length; ++j) {
|
2563
|
-
var om = omk[j];
|
2564
|
-
if (!om.sameSet(mark) || om.from != null) continue;
|
2565
|
-
if (mark.from == this.text.length && om.to == 0) {
|
2566
|
-
omk.splice(j, 1);
|
2567
|
-
mk.splice(i--, 1);
|
2568
|
-
continue outer;
|
2569
|
-
} else {
|
2570
|
-
close = false; break;
|
2571
|
-
}
|
2572
|
-
}
|
2573
|
-
}
|
2574
|
-
if (close) mark.to = this.text.length;
|
2575
|
-
}
|
2576
|
-
},
|
2577
|
-
fixMarkStarts: function() {
|
2578
|
-
var mk = this.marked;
|
2579
|
-
if (!mk) return;
|
2580
|
-
for (var i = 0; i < mk.length; ++i)
|
2581
|
-
if (mk[i].from == null) mk[i].from = 0;
|
2582
|
-
},
|
2583
|
-
addMark: function(mark) {
|
2584
|
-
mark.attach(this);
|
2585
|
-
if (this.marked == null) this.marked = [];
|
2586
|
-
this.marked.push(mark);
|
2587
|
-
this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});
|
2490
|
+
update: function(text, markedSpans) {
|
2491
|
+
this.text = text;
|
2492
|
+
this.stateAfter = this.styles = null;
|
2493
|
+
detachMarkedSpans(this);
|
2494
|
+
attachMarkedSpans(this, markedSpans);
|
2588
2495
|
},
|
2589
2496
|
// Run the given mode's parser over a line, update the styles
|
2590
2497
|
// array, which contains alternating fragments of text and CSS
|
2591
2498
|
// classes.
|
2592
2499
|
highlight: function(mode, state, tabSize) {
|
2593
|
-
var stream = new StringStream(this.text, tabSize), st = this.styles
|
2594
|
-
var
|
2500
|
+
var stream = new StringStream(this.text, tabSize), st = this.styles || (this.styles = []);
|
2501
|
+
var pos = st.length = 0;
|
2595
2502
|
if (this.text == "" && mode.blankLine) mode.blankLine(state);
|
2596
2503
|
while (!stream.eol()) {
|
2597
|
-
var style = mode.token(stream, state);
|
2598
|
-
var substr = this.text.slice(stream.start, stream.pos);
|
2504
|
+
var style = mode.token(stream, state), substr = stream.current();
|
2599
2505
|
stream.start = stream.pos;
|
2600
|
-
if (pos && st[pos-1] == style)
|
2506
|
+
if (pos && st[pos-1] == style) {
|
2601
2507
|
st[pos-2] += substr;
|
2602
|
-
else if (substr) {
|
2603
|
-
if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;
|
2508
|
+
} else if (substr) {
|
2604
2509
|
st[pos++] = substr; st[pos++] = style;
|
2605
|
-
prevWord = curWord; curWord = st[pos];
|
2606
2510
|
}
|
2607
2511
|
// Give up when line is ridiculously long
|
2608
2512
|
if (stream.pos > 5000) {
|
@@ -2610,12 +2514,14 @@ window.CodeMirror = (function() {
|
|
2610
2514
|
break;
|
2611
2515
|
}
|
2612
2516
|
}
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2517
|
+
},
|
2518
|
+
process: function(mode, state, tabSize) {
|
2519
|
+
var stream = new StringStream(this.text, tabSize);
|
2520
|
+
if (this.text == "" && mode.blankLine) mode.blankLine(state);
|
2521
|
+
while (!stream.eol() && stream.pos <= 5000) {
|
2522
|
+
mode.token(stream, state);
|
2523
|
+
stream.start = stream.pos;
|
2524
|
+
}
|
2619
2525
|
},
|
2620
2526
|
// Fetch the parser token for a given character. Useful for hacks
|
2621
2527
|
// that want to inspect the mode state (say, for completion).
|
@@ -2634,7 +2540,7 @@ window.CodeMirror = (function() {
|
|
2634
2540
|
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
|
2635
2541
|
// Produces an HTML fragment for the line, taking selection,
|
2636
2542
|
// marking, and highlighting into account.
|
2637
|
-
|
2543
|
+
getContent: function(tabSize, wrapAt, compensateForWrapping) {
|
2638
2544
|
var first = true, col = 0, specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
|
2639
2545
|
var pre = elt("pre");
|
2640
2546
|
function span_(html, text, style) {
|
@@ -2658,9 +2564,9 @@ window.CodeMirror = (function() {
|
|
2658
2564
|
if (!m) break;
|
2659
2565
|
pos += skipped + 1;
|
2660
2566
|
if (m[0] == "\t") {
|
2661
|
-
var
|
2662
|
-
content.appendChild(
|
2663
|
-
col +=
|
2567
|
+
var tabWidth = tabSize - col % tabSize;
|
2568
|
+
content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
|
2569
|
+
col += tabWidth;
|
2664
2570
|
} else {
|
2665
2571
|
var token = elt("span", "\u2022", "cm-invalidchar");
|
2666
2572
|
token.title = "\\u" + m[0].charCodeAt(0).toString(16);
|
@@ -2681,7 +2587,7 @@ window.CodeMirror = (function() {
|
|
2681
2587
|
if (wrapAt > outPos) {
|
2682
2588
|
span_(html, text.slice(0, wrapAt - outPos), style);
|
2683
2589
|
// See comment at the definition of spanAffectsWrapping
|
2684
|
-
if (
|
2590
|
+
if (compensateForWrapping) html.appendChild(elt("wbr"));
|
2685
2591
|
}
|
2686
2592
|
html.appendChild(anchor);
|
2687
2593
|
var cut = wrapAt - outPos;
|
@@ -2702,7 +2608,7 @@ window.CodeMirror = (function() {
|
|
2702
2608
|
};
|
2703
2609
|
}
|
2704
2610
|
|
2705
|
-
var st = this.styles, allText = this.text, marked = this.
|
2611
|
+
var st = this.styles, allText = this.text, marked = this.markedSpans;
|
2706
2612
|
var len = allText.length;
|
2707
2613
|
function styleToClass(style) {
|
2708
2614
|
if (!style) return null;
|
@@ -2718,13 +2624,14 @@ window.CodeMirror = (function() {
|
|
2718
2624
|
span(pre, str, styleToClass(style));
|
2719
2625
|
}
|
2720
2626
|
} else {
|
2627
|
+
marked.sort(function(a, b) { return a.from - b.from; });
|
2721
2628
|
var pos = 0, i = 0, text = "", style, sg = 0;
|
2722
2629
|
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
|
2723
2630
|
var advanceMarks = function() {
|
2724
2631
|
var m;
|
2725
2632
|
while (markpos < marked.length &&
|
2726
2633
|
((m = marked[markpos]).from == pos || m.from == null)) {
|
2727
|
-
if (m.
|
2634
|
+
if (m.marker.type == "range") marks.push(m);
|
2728
2635
|
++markpos;
|
2729
2636
|
}
|
2730
2637
|
nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
|
@@ -2743,8 +2650,12 @@ window.CodeMirror = (function() {
|
|
2743
2650
|
if (text) {
|
2744
2651
|
var end = pos + text.length;
|
2745
2652
|
var appliedStyle = style;
|
2746
|
-
for (var j = 0; j < marks.length; ++j)
|
2747
|
-
|
2653
|
+
for (var j = 0; j < marks.length; ++j) {
|
2654
|
+
var mark = marks[j];
|
2655
|
+
appliedStyle = (appliedStyle ? appliedStyle + " " : "") + mark.marker.style;
|
2656
|
+
if (mark.marker.endStyle && mark.to === Math.min(end, upto)) appliedStyle += " " + mark.marker.endStyle;
|
2657
|
+
if (mark.marker.startStyle && mark.from === pos) appliedStyle += " " + mark.marker.startStyle;
|
2658
|
+
}
|
2748
2659
|
span(pre, end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
2749
2660
|
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
2750
2661
|
pos = end;
|
@@ -2757,24 +2668,9 @@ window.CodeMirror = (function() {
|
|
2757
2668
|
},
|
2758
2669
|
cleanUp: function() {
|
2759
2670
|
this.parent = null;
|
2760
|
-
|
2761
|
-
for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);
|
2671
|
+
detachMarkedSpans(this);
|
2762
2672
|
}
|
2763
2673
|
};
|
2764
|
-
// Utility used by replace and split above
|
2765
|
-
function copyStyles(from, to, source, dest) {
|
2766
|
-
for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {
|
2767
|
-
var part = source[i], end = pos + part.length;
|
2768
|
-
if (state == 0) {
|
2769
|
-
if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
|
2770
|
-
if (end >= from) state = 1;
|
2771
|
-
} else if (state == 1) {
|
2772
|
-
if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
|
2773
|
-
else dest.push(part, source[i+1]);
|
2774
|
-
}
|
2775
|
-
pos = end;
|
2776
|
-
}
|
2777
|
-
}
|
2778
2674
|
|
2779
2675
|
// Data structure that holds the sequence of lines.
|
2780
2676
|
function LeafChunk(lines) {
|
@@ -2975,7 +2871,7 @@ window.CodeMirror = (function() {
|
|
2975
2871
|
History.prototype = {
|
2976
2872
|
addChange: function(start, added, old) {
|
2977
2873
|
this.undone.length = 0;
|
2978
|
-
var time = +new Date, cur = this.done
|
2874
|
+
var time = +new Date, cur = lst(this.done), last = cur && lst(cur);
|
2979
2875
|
var dtime = time - this.time;
|
2980
2876
|
|
2981
2877
|
if (this.compound && cur && !this.closed) {
|
@@ -3121,10 +3017,19 @@ window.CodeMirror = (function() {
|
|
3121
3017
|
return box;
|
3122
3018
|
}
|
3123
3019
|
|
3124
|
-
// Get a node's text content.
|
3125
3020
|
function eltText(node) {
|
3126
3021
|
return node.textContent || node.innerText || node.nodeValue || "";
|
3127
3022
|
}
|
3023
|
+
|
3024
|
+
var spaceStrs = [""];
|
3025
|
+
function spaceStr(n) {
|
3026
|
+
while (spaceStrs.length <= n)
|
3027
|
+
spaceStrs.push(lst(spaceStrs) + " ");
|
3028
|
+
return spaceStrs[n];
|
3029
|
+
}
|
3030
|
+
|
3031
|
+
function lst(arr) { return arr[arr.length-1]; }
|
3032
|
+
|
3128
3033
|
function selectInput(node) {
|
3129
3034
|
if (ios) { // Mobile Safari apparently has a bug where select() is broken.
|
3130
3035
|
node.selectionStart = 0;
|
@@ -3158,7 +3063,6 @@ window.CodeMirror = (function() {
|
|
3158
3063
|
e.appendChild(document.createTextNode(str));
|
3159
3064
|
} else e.textContent = str;
|
3160
3065
|
}
|
3161
|
-
CodeMirror.setTextContent = setTextContent;
|
3162
3066
|
|
3163
3067
|
// Used to position the cursor after an undo/redo by finding the
|
3164
3068
|
// last edited character.
|
@@ -3233,5 +3137,7 @@ window.CodeMirror = (function() {
|
|
3233
3137
|
for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
|
3234
3138
|
})();
|
3235
3139
|
|
3140
|
+
CodeMirror.version = "2.34";
|
3141
|
+
|
3236
3142
|
return CodeMirror;
|
3237
3143
|
})();
|