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;

View file

@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
(function() {
this.foldingRules = "cStyle";
this.toggleCommentLines = function(state, doc, startRow, endRow) {
var outdent = true;
var outentedRows = [];

View file

@ -16,34 +16,36 @@ oop.inherits(Mode, TextMode);
(function() {
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);
this.foldingRules = "cStyle";
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
var tokens = tokenizedLine.tokens;
var endState = tokenizedLine.state;
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
var tokens = tokenizedLine.tokens;
var endState = tokenizedLine.state;
if (tokens.length && tokens[tokens.length-1].type == "comment") {
return indent;
}
if (state == "start") {
var match = line.match(/^.*[\{\(\[]\s*$/);
if (match) {
indent += tab;
}
}
return indent;
};
if (tokens.length && tokens[tokens.length-1].type == "comment") {
return indent;
}
if (state == "start") {
var match = line.match(/^.*[\{\(\[]\s*$/);
if (match) {
indent += tab;
}
}
return indent;
};
this.checkOutdent = function(state, line, input) {
return this.$outdent.checkOutdent(line, input);
};
this.autoOutdent = function(state, doc, row) {
this.$outdent.autoOutdent(doc, row);
};
this.checkOutdent = function(state, line, input) {
return this.$outdent.checkOutdent(line, input);
};
this.autoOutdent = function(state, doc, row) {
this.$outdent.autoOutdent(doc, row);
};
this.createWorker = function(session) {

View file

@ -52,6 +52,8 @@ oop.inherits(Mode, TextMode);
(function() {
this.foldingRules = "cStyle";
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);

View file

@ -16,6 +16,8 @@ oop.inherits(Mode, JavaScriptMode);
(function() {
this.foldingRules = "cStyle";
this.createWorker = function(session) {
return null;
};

View file

@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
(function() {
this.foldingRules = "cStyle";
this.toggleCommentLines = function(state, doc, startRow, endRow) {
var outdent = true;
var outentedRows = [];

View file

@ -54,6 +54,8 @@ oop.inherits(Mode, TextMode);
(function() {
this.foldingRules = "cStyle";
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);

View file

@ -52,6 +52,11 @@ oop.inherits(Mode, TextMode);
(function() {
this.foldingRules = {
foldingStartMarker: /\:(:?\s*)?(:?#.*)?$/,
getFoldWidgetRange: "indentationBlock"
};
this.toggleCommentLines = function(state, doc, startRow, endRow) {
var outdent = true;
var outentedRows = [];

View file

@ -267,6 +267,9 @@ var VirtualRenderer = function(container, theme) {
var pageY = event.getDocumentY(e);
var row = this.screenToTextCoordinates(0, pageY).row;
if (e.target.className.indexOf('ace_fold-widget') != -1)
return this.session.onFoldWidgetClick(row, e);
this._dispatchEvent("gutter" + e.type, {
row: row,
htmlEvent: e