-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
folding for php alternative syntax (#5491)
- Loading branch information
Showing
3 changed files
with
187 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
"use strict"; | ||
|
||
var oop = require("../../lib/oop"); | ||
var MixedFoldMode = require("./mixed").FoldMode; | ||
var CstyleFoldMode = require("./cstyle").FoldMode; | ||
var Range = require("../../range").Range; | ||
var TokenIterator = require("../../token_iterator").TokenIterator; | ||
|
||
|
||
var FoldMode = exports.FoldMode = function () { | ||
this.cstyleFoldMode = new CstyleFoldMode(); | ||
MixedFoldMode.call(this, this, { | ||
"js-": new CstyleFoldMode(), | ||
"css-": new CstyleFoldMode(), | ||
"php-": this | ||
}); | ||
}; | ||
|
||
oop.inherits(FoldMode, MixedFoldMode); | ||
|
||
(function () { | ||
this.indentKeywords = { | ||
"if": 1, | ||
"while": 1, | ||
"for": 1, | ||
"foreach": 1, | ||
"switch": 1, | ||
"else": 0, | ||
"elseif": 0, | ||
"endif": -1, | ||
"endwhile": -1, | ||
"endfor": -1, | ||
"endforeach": -1, | ||
"endswitch": -1 | ||
}; | ||
|
||
this.foldingStartMarker = /(?:\s|^)(if|else|elseif|while|for|foreach|switch).*\:/i; | ||
this.foldingStopMarker = /(?:\s|^)(endif|endwhile|endfor|endforeach|endswitch)\;/i; | ||
|
||
this.getFoldWidgetRange = function (session, foldStyle, row) { | ||
var line = session.doc.getLine(row); | ||
var match = this.foldingStartMarker.exec(line); | ||
if (match) { | ||
return this.phpBlock(session, row, match.index + 2); | ||
} | ||
|
||
var match = this.foldingStopMarker.exec(line); | ||
if (match) { | ||
return this.phpBlock(session, row, match.index + 2); | ||
} | ||
return this.cstyleFoldMode.getFoldWidgetRange(session, foldStyle, row); | ||
}; | ||
|
||
|
||
// must return "" if there's no fold, to enable caching | ||
this.getFoldWidget = function (session, foldStyle, row) { | ||
var line = session.getLine(row); | ||
var isStart = this.foldingStartMarker.test(line); | ||
var isEnd = this.foldingStopMarker.test(line); | ||
if (isStart && !isEnd) { | ||
var match = this.foldingStartMarker.exec(line); | ||
var keyword = match && match[1].toLowerCase(); | ||
if (keyword) { | ||
var type = session.getTokenAt(row, match.index + 2).type; | ||
if (type == "keyword") { | ||
return "start"; | ||
} | ||
} | ||
} | ||
if (isEnd && foldStyle === "markbeginend") { | ||
var match = this.foldingStopMarker.exec(line); | ||
var keyword = match && match[1].toLowerCase(); | ||
if (keyword) { | ||
var type = session.getTokenAt(row, match.index + 2).type; | ||
if (type == "keyword") { | ||
return "end"; | ||
} | ||
} | ||
} | ||
return this.cstyleFoldMode.getFoldWidget(session, foldStyle, row); | ||
}; | ||
|
||
this.phpBlock = function (session, row, column, tokenRange) { | ||
var stream = new TokenIterator(session, row, column); | ||
|
||
var token = stream.getCurrentToken(); | ||
if (!token || token.type != "keyword") return; | ||
|
||
var val = token.value; | ||
var stack = [val]; | ||
var dir = this.indentKeywords[val]; | ||
|
||
if (val === "else" || val === "elseif") { | ||
dir = 1; | ||
} | ||
|
||
if (!dir) return; | ||
|
||
var startColumn = dir === -1 ? stream.getCurrentTokenColumn() : session.getLine(row).length; | ||
var startRow = row; | ||
|
||
stream.step = dir === -1 ? stream.stepBackward : stream.stepForward; | ||
while (token = stream.step()) { | ||
if (token.type !== "keyword") continue; | ||
var level = dir * this.indentKeywords[token.value]; | ||
|
||
if (level > 0) { | ||
stack.unshift(token.value); | ||
} | ||
else if (level <= 0) { | ||
stack.shift(); | ||
if (!stack.length) break; | ||
if (level === 0) stack.unshift(token.value); | ||
} | ||
} | ||
|
||
if (!token) return null; | ||
|
||
if (tokenRange) return stream.getCurrentTokenRange(); | ||
|
||
var row = stream.getCurrentTokenRow(); | ||
if (dir === -1) return new Range( | ||
row, session.getLine(row).length, startRow, startColumn); else return new Range( | ||
startRow, startColumn, row, stream.getCurrentTokenColumn()); | ||
}; | ||
|
||
}).call(FoldMode.prototype); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
if (typeof process !== "undefined") require("amd-loader"); | ||
|
||
"use strict"; | ||
|
||
var PHPMode = require("../php").Mode; | ||
var EditSession = require("../../edit_session").EditSession; | ||
var assert = require("../../test/assertions"); | ||
|
||
module.exports = { | ||
setUp: function () { | ||
this.mode = new PHPMode(); | ||
}, | ||
|
||
"test: php folding with alternative syntax": function () { | ||
var session = new EditSession([ | ||
'<?php', 'function checkNumber($number)', '{', ' switch ($number) {', ' case 0:', | ||
' echo "Number is zero again";', ' if ($number == 0):', | ||
' echo "Number is zero";', ' elseif ($number > 0):', | ||
' echo "Number is positive";', ' else:', | ||
' echo "Number is negative";', 'endif;', ' break;', ' default:', | ||
' echo "Number is not zero";', ' }', 'foreach (array(1, 2, 3) as $num):', | ||
' echo "Num: $num";', ' endforeach;', '}', '?>' | ||
]); | ||
|
||
session.setFoldStyle("markbeginend"); | ||
session.setMode(this.mode); | ||
session.bgTokenizer.$worker(); | ||
|
||
assert.equal(session.getFoldWidget(0), ""); | ||
assert.equal(session.getFoldWidget(1), ""); | ||
assert.equal(session.getFoldWidget(2), "start"); | ||
assert.equal(session.getFoldWidget(3), "start"); | ||
assert.equal(session.getFoldWidget(4), ""); | ||
assert.equal(session.getFoldWidget(5), ""); | ||
assert.equal(session.getFoldWidget(6), "start"); | ||
assert.equal(session.getFoldWidget(7), ""); | ||
assert.equal(session.getFoldWidget(8), "start"); | ||
assert.equal(session.getFoldWidget(10), "start"); | ||
assert.equal(session.getFoldWidget(12), "end"); | ||
assert.equal(session.getFoldWidget(16), "end"); | ||
assert.equal(session.getFoldWidget(17), "start"); | ||
assert.equal(session.getFoldWidget(19), "end"); | ||
assert.equal(session.getFoldWidget(20), "end"); | ||
|
||
assert.range(session.getFoldWidgetRange(2), 2, 1, 20, 0); // Range for the function's foldable section | ||
assert.range(session.getFoldWidgetRange(3), 3, 21, 16, 7); // Range for the 'switch' statement | ||
assert.range(session.getFoldWidgetRange(6), 6, 29, 8, 11); // Range for the 'if' block | ||
assert.range(session.getFoldWidgetRange(8), 8, 32, 10, 11); // Range for the 'elseif' block | ||
assert.range(session.getFoldWidgetRange(10), 10, 16, 12, 0); // Range for the 'else' block | ||
assert.range(session.getFoldWidgetRange(12), 10, 16, 12, 0); // Range for the 'endif' line | ||
assert.range(session.getFoldWidgetRange(17), 17, 33, 19, 3); | ||
assert.range(session.getFoldWidgetRange(19), 17, 33, 19, 3); | ||
} | ||
}; | ||
|
||
|
||
if (typeof module !== "undefined" && module === require.main) require("asyncjs").test.testcase(module.exports).exec(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2e40702
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HI @mkslanc I've opened an issue about this change: #5547
We can fold php alternative syntax now, it's cool but we can't fold html tags anymore
2e40702
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Syone , good catch! I will push the fix ASAP