Skip to content

Commit 38ea9ea

Browse files
committed
(todo) Add block region
1 parent 9085985 commit 38ea9ea

File tree

1 file changed

+119
-29
lines changed

1 file changed

+119
-29
lines changed

src/features/Folding.ts

Lines changed: 119 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,43 @@ import { IFeature } from "../feature";
1212

1313
const rangeLimit = 5000;
1414

15-
// https://github.com/Microsoft/vscode/issues/46281
1615
const tm = getCoreNodeModule("vscode-textmate");
17-
/**
18-
* Returns a node module installed with VSCode, or null if it fails.
19-
*/
16+
17+
// Returns a node module installed with VSCode, or null if it fails.
18+
// https://github.com/Microsoft/vscode/issues/46281
2019
function getCoreNodeModule(moduleName: string) {
2120
try {
2221
return require(`${vscode.env.appRoot}/node_modules.asar/${moduleName}`);
22+
// tslint:disable-next-line:no-empty
2323
} catch (err) { }
2424

2525
try {
2626
return require(`${vscode.env.appRoot}/node_modules/${moduleName}`);
27+
// tslint:disable-next-line:no-empty
2728
} catch (err) { }
2829

2930
return null;
3031
}
3132

3233
interface IExtensionGrammar {
33-
language?: string; scopeName?: string; path?: string; embeddedLanguages?: { [scopeName: string]: string }; injectTo?: string[];
34+
language?: string;
35+
scopeName?: string;
36+
path?: string;
37+
embeddedLanguages?: {
38+
[scopeName: string]: string,
39+
}; injectTo?: string[];
40+
}
41+
42+
interface IExtensionLanguage {
43+
id: string;
44+
configuration: string;
3445
}
3546

3647
interface IExtensionPackage {
3748
contributes?: {
38-
languages?: { id: string; configuration: string }[],
49+
languages?: IExtensionLanguage[],
3950
grammars?: IExtensionGrammar[],
40-
}
51+
};
4152
}
4253

4354
// Need to reproduce the IToken interface from vscode-textmate due to
@@ -141,7 +152,11 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
141152
return foldingRanges;
142153
}
143154

144-
private matchScopeElements(tokens, startScopeName: string, endScopeName: string, matchType: MatchType, document: vscode.TextDocument): IMatchedTokenList {
155+
private matchScopeElements(tokens,
156+
startScopeName: string,
157+
endScopeName: string,
158+
matchType: MatchType,
159+
document: vscode.TextDocument): IMatchedTokenList {
145160
const result = [];
146161
const tokenStack = [];
147162

@@ -157,7 +172,10 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
157172
return result.reverse();
158173
}
159174

160-
private matchContiguousScopeElements(tokens, scopeName: string, matchType: MatchType, document) {
175+
private matchContiguousScopeElements(tokens,
176+
scopeName: string,
177+
matchType: MatchType,
178+
document: vscode.TextDocument) {
161179
const result = [];
162180
let startToken;
163181

@@ -178,19 +196,22 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
178196
}
179197

180198
// Given a zero based offset, find the line text preceeding it
181-
private preceedingText(offset: number, document: vscode.TextDocument) {
199+
private preceedingText(offset: number,
200+
document: vscode.TextDocument): string {
182201
const endPos = document.positionAt(offset);
183202
const startPos = endPos.translate(0, -endPos.character);
184203

185204
return document.getText(new vscode.Range(startPos, endPos));
186205
}
187206

188207
// Given a zero based offset, return the line number
189-
private lineAtOffest(offset, document): number {
208+
private lineAtOffest(offset: number,
209+
document: vscode.TextDocument): number {
190210
return document.positionAt(offset).line;
191211
}
192212

193-
private matchBlockCommentScopeElements(tokens, document: vscode.TextDocument) {
213+
private matchBlockCommentScopeElements(tokens,
214+
document: vscode.TextDocument) {
194215
const result = [];
195216

196217
const emptyLine = new RegExp("^[\\s]+$");
@@ -214,7 +235,12 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
214235
if (lineNum === nextLine) {
215236
nextLine = lineNum + 1;
216237
} else {
217-
result.push(new MatchedToken(null, null, startLine, nextLine - 1, MatchType.Comment, document));
238+
result.push(new MatchedToken(null,
239+
null,
240+
startLine,
241+
nextLine - 1,
242+
MatchType.Comment,
243+
document));
218244
startLine = lineNum;
219245
nextLine = lineNum + 1;
220246
}
@@ -230,23 +256,90 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
230256
return result;
231257
}
232258

259+
// Given a zero based offset, find the line text after it
260+
private subsequentText(offset: number,
261+
document: vscode.TextDocument): string {
262+
const startPos = document.positionAt(offset);
263+
// We don't know how long the line is so just return a really long one.
264+
const endPos = startPos.translate(0, 1000);
265+
return document.getText(new vscode.Range(startPos, endPos));
266+
}
267+
268+
// Create a new token object with an appended scopeName
269+
private addTokenScope(token,
270+
scopeName: string) {
271+
// Only a shallow clone is required
272+
const tokenClone = Object.assign({}, token);
273+
tokenClone.scopes.push(scopeName);
274+
return tokenClone;
275+
}
276+
277+
private extractRegionScopeElements(tokens,
278+
document: vscode.TextDocument) {
279+
const result = [];
280+
281+
const emptyLine = new RegExp("^[\\s]+$");
282+
const startRegionText = new RegExp("^#\\s*region\\b");
283+
const endRegionText = new RegExp("^#\\s*endregion\\b");
284+
285+
tokens.forEach( (token, index) => {
286+
if (token.scopes.includes("punctuation.definition.comment.powershell")) {
287+
if (emptyLine.test(this.preceedingText(token.startIndex, document))) {
288+
const commentText = this.subsequentText(token.startIndex, document);
289+
290+
if (startRegionText.test(commentText)) { result.push(this.addTokenScope(token, "custom.start.region")); }
291+
if (endRegionText.test(commentText)) { result.push(this.addTokenScope(token, "custom.end.region")); }
292+
}
293+
}
294+
});
295+
return result;
296+
}
297+
233298
private matchGrammarTokens(tokens, document: vscode.TextDocument): IMatchedTokenList {
234299
const matchedTokens = [];
235300

236301
// Find matching Braces { -> }
237-
this.matchScopeElements(tokens, "punctuation.section.braces.begin.powershell", "punctuation.section.braces.end.powershell", MatchType.Region, document).forEach((x) => { matchedTokens.push(x); });
238-
// Find matching brackets ( -> )
239-
this.matchScopeElements(tokens, "punctuation.section.group.begin.powershell", "punctuation.section.group.end.powershell", MatchType.Region, document).forEach((x) => { matchedTokens.push(x); });
240-
241-
// Find contiguous here strings @' -> '@ and @" -> "@
242-
this.matchContiguousScopeElements(tokens, "string.quoted.single.heredoc.powershell", MatchType.Region, document).forEach((x) => { matchedTokens.push(x); });
243-
this.matchContiguousScopeElements(tokens, "string.quoted.double.heredoc.powershell", MatchType.Region, document).forEach((x) => { matchedTokens.push(x); });
302+
this.matchScopeElements(tokens,
303+
"punctuation.section.braces.begin.powershell",
304+
"punctuation.section.braces.end.powershell",
305+
MatchType.Region, document)
306+
.forEach((x) => { matchedTokens.push(x); });
244307

245-
// Find blocks of line comments # foo
308+
// Find matching brackets ( -> )
309+
this.matchScopeElements(tokens,
310+
"punctuation.section.group.begin.powershell",
311+
"punctuation.section.group.end.powershell",
312+
MatchType.Region, document)
313+
.forEach((x) => { matchedTokens.push(x); });
314+
315+
// Find contiguous here strings @' -> '@
316+
this.matchContiguousScopeElements(tokens,
317+
"string.quoted.single.heredoc.powershell",
318+
MatchType.Region, document)
319+
.forEach((x) => { matchedTokens.push(x); });
320+
321+
// Find contiguous here strings @" -> "@
322+
this.matchContiguousScopeElements(tokens,
323+
"string.quoted.double.heredoc.powershell",
324+
MatchType.Region, document)
325+
.forEach((x) => { matchedTokens.push(x); });
326+
327+
// Find matching Braces #region -> #endregion
328+
this.matchScopeElements(this.extractRegionScopeElements(tokens, document),
329+
"custom.start.region",
330+
"custom.end.region",
331+
MatchType.Region, document)
332+
.forEach( (x) => { matchedTokens.push(x); });
333+
334+
// Find blocks of line comments # comment1\n# comment2\n...
246335
this.matchBlockCommentScopeElements(tokens, document).forEach((x) => { matchedTokens.push(x); });
247336

248337
// Find matching function definitions <# -> #>
249-
this.matchScopeElements(tokens, "punctuation.definition.comment.block.begin.powershell", "punctuation.definition.comment.block.end.powershell", MatchType.Comment, document).forEach( (x) => { matchedTokens.push(x); });
338+
this.matchScopeElements(tokens,
339+
"punctuation.definition.comment.block.begin.powershell",
340+
"punctuation.definition.comment.block.end.powershell",
341+
MatchType.Comment, document)
342+
.forEach( (x) => { matchedTokens.push(x); });
250343

251344
return matchedTokens;
252345
}
@@ -286,12 +379,9 @@ export class FoldingFeature implements IFeature {
286379
this.foldingProvider);
287380
}
288381

289-
public dispose(): any {
290-
// Should be empty
291-
}
382+
// tslint:disable-next-line:no-empty
383+
public dispose(): any { }
292384

293-
public setLanguageClient(languageclient: LanguageClient): void {
294-
this.languageClient = languageclient;
295-
// this.foldingProvider.setLanguageClient(languageclient);
296-
}
385+
// tslint:disable-next-line:no-empty
386+
public setLanguageClient(languageclient: LanguageClient): void { }
297387
}

0 commit comments

Comments
 (0)