add fold detection rules for python and c style languages

This commit is contained in:
nightwing 2011-11-28 18:09:39 +04:00
commit 4677db58d8
9 changed files with 250 additions and 51 deletions

View file

@ -534,27 +534,7 @@ function Folding() {
range.start.column++;
} else {
var iterator = new TokenIterator(this, cursor.row, cursor.column);
var token = iterator.getCurrentToken();
if (token && /^comment|string/.test(token.type)) {
do {
t = iterator.stepBackward();
} while(t && t.type == token.type)
iterator.stepForward();
range.start.row = iterator.getCurrentTokenRow();
range.start.column = iterator.getCurrentTokenColumn() + 2;
var iterator = new TokenIterator(this, cursor.row, cursor.column);
do {
t = iterator.stepForward();
} while(t && t.type == token.type)
t = iterator.stepBackward();
range.end.row = iterator.getCurrentTokenRow();
range.end.column = iterator.getCurrentTokenColumn() + t.value.length - 1;
}
range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
}
} else {
var folds = this.getFoldsInRange(range);
@ -574,7 +554,6 @@ function Folding() {
return
}
var placeholder = "...";
if (!range.isMultiLine()) {
placeholder = this.getTextRange(range);
@ -586,12 +565,212 @@ function Folding() {
this.addFold(placeholder, range);
};
// structured folding
this.$setFolding = function(mode) {
this.getCommentFoldRange = function(row, column) {
var iterator = new TokenIterator(this, row, column);
var token = iterator.getCurrentToken();
if (token && /^comment|string/.test(token.type)) {
var range = new Range;
do {
t = iterator.stepBackward();
} while(t && t.type == token.type)
iterator.stepForward();
range.start.row = iterator.getCurrentTokenRow();
range.start.column = iterator.getCurrentTokenColumn() + 2;
var iterator = new TokenIterator(this, row, column);
do {
t = iterator.stepForward();
} while(t && t.type == token.type)
t = iterator.stepBackward();
range.end.row = iterator.getCurrentTokenRow();
range.end.column = iterator.getCurrentTokenColumn() + t.value.length - 1;
return range
}
};
this.onFoldWidgetClick = function(e) {
this.foldAll = function() {
var foldWidgets = this.foldWidgets
for (var row = foldWidgets.length; row--; ) {
if (foldWidgets[row] == null)
foldWidgets[row] = this.getFoldWidget(row)
if (foldWidgets[row] != "start")
continue
var range = this.getFoldWidgetRange(row);
console.log(row, range)
if (range)
this.addFold("...", range)
}
}
// structured folding
this.$setFolding = function(mode) {
mode = mode && mode.foldingRules;
var foldRules = Folding.commonFoldingRules
if (typeof mode == "string")
mode = foldRules[mode];
if (mode) {
this.foldWidgets = [];
this.removeListener('change', this.$updateFoldWidgets);
if (mode.getFoldWidget)
this.getFoldWidget = mode.getFoldWidget;
else if (mode.foldingStopMarker)
this.getFoldWidget = foldRules.$testBoth;
else
this.getFoldWidget = foldRules.$testStart;
this.foldingStopMarker = mode.foldingStopMarker;
this.foldingStartMarker = mode.foldingStartMarker;
if (typeof mode.getFoldWidgetRange == "string")
this.getFoldWidgetRange = foldRules[mode.getFoldWidgetRange];
else
this.getFoldWidgetRange = mode.getFoldWidgetRange;
this.$updateFoldWidgets = (mode.onChange || foldRules.onChange).bind(this);
this.on('change', this.$updateFoldWidgets);
} else {
this.foldWidgets = null;
this.removeListener('change', this.$updateFoldWidgets);
}
};
this.onFoldWidgetClick = function(row, htmlEvent) {
var type = this.getFoldWidget(row);
var line = this.getLine(row);
if (type == "end")
var fold = this.getFoldAt(row, 0, -1);
else
var fold = this.getFoldAt(row, line.length, 1);
if (fold) {
this.expandFold(fold);
return;
}
range = this.getFoldWidgetRange(row);
if (range)
this.addFold("...", range);
}
}
Folding.commonFoldingRules = {
$testStart: function(row) {
if(this.foldingStartMarker.test(this.getLine(row)))
return "start";
return "";
},
$testBoth: function(row) {
var line = this.getLine(row);
if(this.foldingStartMarker.test(line))
return "start";
if(this.foldingStopMarker.test(line))
return "end";
return "";
},
onChange: function(e) {
var delta = e.data;
var range = delta.range;
var firstRow = range.start.row;
var len = range.end.row - firstRow;
if (len == 0) {
this.foldWidgets[firstRow] = null;
} else if (delta.action == "removeText" || delta.action == "removeLines") {
this.foldWidgets.splice(firstRow, len + 1, null);
} else {
var args = Array(len + 1);
args.unshift(firstRow, 1)
this.foldWidgets.splice.apply(this.foldWidgets, args);
}
},
indentationBlock: function(row) {
var re = /^\s*/;
var startRow = row, endRow = row;
var line = this.getLine(row);
var startColumn = line.length - 1;
var startLevel = line.match(re)[0].length;
while (line = this.getLine(++row)) {
var level = line.match(re)[0].length;
if (level == line.length)
continue;
if (level <= startLevel)
break;
endRow = row;
}
if (endRow > startRow) {
endColumn = this.getLine(endRow).length;
return new Range(startRow, startColumn, endRow, endColumn);
}
},
"cStyle": {
foldingStartMarker : /(\{|\[)[^\}\]]*$|^\s*(\/\*)/,
foldingStopMarker : /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,
getFoldWidgetRange: function(row) {
var line = this.getLine(row);
var match = line.match(this.foldingStartMarker);
if (match) {
var i = match.index;
if (match[2])
return this.getCommentFoldRange(row, i + match[0].length);
var start = {row: row, column: i+1};
var end = this.$findClosingBracket(match[1], start);
if (end) {
var fw = this.foldWidgets[end.row];
if (fw == null)
fw = this.getFoldWidget(end.row);
if (fw == "start"){
end.row --;
end.column = this.getLine(end.row).length;
}
} else {
end = {row: this.getLength(), column: 0};
}
return Range.fromPoints(start, end);
}
var match = line.match(this.foldingStopMarker);
if (match) {
var i = match.index + match[0].length;
if (match[2])
return this.getCommentFoldRange(row, i);
var end = {row: row, column: i};
var start = this.$findOpeningBracket(match[1], end)
if (start){
start.column++;
end.column--;
} else {
start = {row: 0, column: this.getLine(0).length}
}
return Range.fromPoints(start, end);
}
}
},
// TODO: folding based only on indentation
"indentation": null
}
exports.Folding = Folding;