add fold detection rules for python and c style languages
This commit is contained in:
parent
aa9ff0d763
commit
4677db58d8
9 changed files with 250 additions and 51 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
|
|||
|
||||
(function() {
|
||||
|
||||
this.foldingRules = "cStyle";
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ oop.inherits(Mode, TextMode);
|
|||
|
||||
(function() {
|
||||
|
||||
this.foldingRules = "cStyle";
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ oop.inherits(Mode, JavaScriptMode);
|
|||
|
||||
(function() {
|
||||
|
||||
this.foldingRules = "cStyle";
|
||||
|
||||
this.createWorker = function(session) {
|
||||
return null;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
|
|||
|
||||
(function() {
|
||||
|
||||
this.foldingRules = "cStyle";
|
||||
|
||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||
var outdent = true;
|
||||
var outentedRows = [];
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ oop.inherits(Mode, TextMode);
|
|||
|
||||
(function() {
|
||||
|
||||
this.foldingRules = "cStyle";
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = [];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue