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++;
|
range.start.column++;
|
||||||
} else {
|
} else {
|
||||||
var iterator = new TokenIterator(this, cursor.row, cursor.column);
|
range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var folds = this.getFoldsInRange(range);
|
var folds = this.getFoldsInRange(range);
|
||||||
|
|
@ -574,7 +554,6 @@ function Folding() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var placeholder = "...";
|
var placeholder = "...";
|
||||||
if (!range.isMultiLine()) {
|
if (!range.isMultiLine()) {
|
||||||
placeholder = this.getTextRange(range);
|
placeholder = this.getTextRange(range);
|
||||||
|
|
@ -586,12 +565,212 @@ function Folding() {
|
||||||
this.addFold(placeholder, range);
|
this.addFold(placeholder, range);
|
||||||
};
|
};
|
||||||
|
|
||||||
// structured folding
|
this.getCommentFoldRange = function(row, column) {
|
||||||
this.$setFolding = function(mode) {
|
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;
|
exports.Folding = Folding;
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = "cStyle";
|
||||||
|
|
||||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||||
var outdent = true;
|
var outdent = true;
|
||||||
var outentedRows = [];
|
var outentedRows = [];
|
||||||
|
|
|
||||||
|
|
@ -16,34 +16,36 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
this.getNextLineIndent = function(state, line, tab) {
|
this.foldingRules = "cStyle";
|
||||||
var indent = this.$getIndent(line);
|
|
||||||
|
|
||||||
var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
|
this.getNextLineIndent = function(state, line, tab) {
|
||||||
var tokens = tokenizedLine.tokens;
|
var indent = this.$getIndent(line);
|
||||||
var endState = tokenizedLine.state;
|
|
||||||
|
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") {
|
this.checkOutdent = function(state, line, input) {
|
||||||
return indent;
|
return this.$outdent.checkOutdent(line, input);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (state == "start") {
|
this.autoOutdent = function(state, doc, row) {
|
||||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
this.$outdent.autoOutdent(doc, row);
|
||||||
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.createWorker = function(session) {
|
this.createWorker = function(session) {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = "cStyle";
|
||||||
|
|
||||||
this.getNextLineIndent = function(state, line, tab) {
|
this.getNextLineIndent = function(state, line, tab) {
|
||||||
var indent = this.$getIndent(line);
|
var indent = this.$getIndent(line);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ oop.inherits(Mode, JavaScriptMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = "cStyle";
|
||||||
|
|
||||||
this.createWorker = function(session) {
|
this.createWorker = function(session) {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = "cStyle";
|
||||||
|
|
||||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||||
var outdent = true;
|
var outdent = true;
|
||||||
var outentedRows = [];
|
var outentedRows = [];
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = "cStyle";
|
||||||
|
|
||||||
this.getNextLineIndent = function(state, line, tab) {
|
this.getNextLineIndent = function(state, line, tab) {
|
||||||
var indent = this.$getIndent(line);
|
var indent = this.$getIndent(line);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,11 @@ oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.foldingRules = {
|
||||||
|
foldingStartMarker: /\:(:?\s*)?(:?#.*)?$/,
|
||||||
|
getFoldWidgetRange: "indentationBlock"
|
||||||
|
};
|
||||||
|
|
||||||
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
this.toggleCommentLines = function(state, doc, startRow, endRow) {
|
||||||
var outdent = true;
|
var outdent = true;
|
||||||
var outentedRows = [];
|
var outentedRows = [];
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,9 @@ var VirtualRenderer = function(container, theme) {
|
||||||
var pageY = event.getDocumentY(e);
|
var pageY = event.getDocumentY(e);
|
||||||
var row = this.screenToTextCoordinates(0, pageY).row;
|
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, {
|
this._dispatchEvent("gutter" + e.type, {
|
||||||
row: row,
|
row: row,
|
||||||
htmlEvent: e
|
htmlEvent: e
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue