|
|
CodeMirror.braceRangeFinder = function(cm, line) {
|
|
|
var lineText = cm.getLine(line);
|
|
|
var startChar = lineText.lastIndexOf("{");
|
|
|
if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return;
|
|
|
var tokenType = cm.getTokenAt({line: line, ch: startChar}).className;
|
|
|
var count = 1, lastLine = cm.lineCount(), end;
|
|
|
outer: for (var i = line + 1; i < lastLine; ++i) {
|
|
|
var text = cm.getLine(i), pos = 0;
|
|
|
for (;;) {
|
|
|
var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
|
|
|
if (nextOpen < 0) nextOpen = text.length;
|
|
|
if (nextClose < 0) nextClose = text.length;
|
|
|
pos = Math.min(nextOpen, nextClose);
|
|
|
if (pos == text.length) break;
|
|
|
if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
|
|
|
if (pos == nextOpen) ++count;
|
|
|
else if (!--count) { end = i; break outer; }
|
|
|
}
|
|
|
++pos;
|
|
|
}
|
|
|
}
|
|
|
if (end == null || end == line + 1) return;
|
|
|
return end;
|
|
|
};
|
|
|
|
|
|
|
|
|
CodeMirror.newFoldFunction = function(rangeFinder, markText) {
|
|
|
var folded = [];
|
|
|
if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">▼</div>%N%';
|
|
|
|
|
|
function isFolded(cm, n) {
|
|
|
for (var i = 0; i < folded.length; ++i) {
|
|
|
var start = cm.lineInfo(folded[i].start);
|
|
|
if (!start) folded.splice(i--, 1);
|
|
|
else if (start.line == n) return {pos: i, region: folded[i]};
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function expand(cm, region) {
|
|
|
cm.clearMarker(region.start);
|
|
|
for (var i = 0; i < region.hidden.length; ++i)
|
|
|
cm.showLine(region.hidden[i]);
|
|
|
}
|
|
|
|
|
|
return function(cm, line) {
|
|
|
cm.operation(function() {
|
|
|
var known = isFolded(cm, line);
|
|
|
if (known) {
|
|
|
folded.splice(known.pos, 1);
|
|
|
expand(cm, known.region);
|
|
|
} else {
|
|
|
var end = rangeFinder(cm, line);
|
|
|
if (end == null) return;
|
|
|
var hidden = [];
|
|
|
for (var i = line + 1; i < end; ++i) {
|
|
|
var handle = cm.hideLine(i);
|
|
|
if (handle) hidden.push(handle);
|
|
|
}
|
|
|
var first = cm.setMarker(line, markText);
|
|
|
var region = {start: first, hidden: hidden};
|
|
|
cm.onDeleteLine(first, function() { expand(cm, region); });
|
|
|
folded.push(region);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
};
|
|
|
|