export function computeRanges(model: ITextModel, foldEndPattern: RegExp = null, minimumRangeSize: number = 1): IndentRange[] { let result: IndentRange[] = []; let previousRegions: { indent: number, line: number }[] = []; previousRegions.push({ indent: -1, line: model.getLineCount() + 1 }); // sentinel, to make sure there's at least one entry for (let line = model.getLineCount(); line > 0; line--) { let indent = model.getIndentLevel(line); if (indent === -1) { continue; // only whitespace } let previous = previousRegions[previousRegions.length - 1]; if (previous.indent > indent) { // discard all regions with larger indent do { previousRegions.pop(); previous = previousRegions[previousRegions.length - 1]; } while (previous.indent > indent); // new folding range let endLineNumber = previous.line - 1; if (previous.line <= model.getLineCount() && foldEndPattern) { let foldEndLineContent = model.getLineContent(previous.line); if (previous.indent === indent && foldEndPattern.test(foldEndLineContent)) { endLineNumber = previous.line; } } if (endLineNumber - line >= minimumRangeSize) { result.push(new IndentRange(line, endLineNumber, indent)); } } if (previous.indent === indent) { previous.line = line; } else { // previous.indent < indent // new region with a bigger indent previousRegions.push({ indent, line }); } } return result.reverse(); }
public toIndentRanges(model: ITextModel) { if (this._length <= this._FoldingRangesLimit) { // reverse and create arrays of the exact length let startIndexes = new Uint32Array(this._length); let endIndexes = new Uint32Array(this._length); for (let i = this._length - 1, k = 0; i >= 0; i-- , k++) { startIndexes[k] = this._startIndexes[i]; endIndexes[k] = this._endIndexes[i]; } return new FoldingRanges(startIndexes, endIndexes); } else { let entries = 0; let maxIndent = this._indentOccurrences.length; for (let i = 0; i < this._indentOccurrences.length; i++) { let n = this._indentOccurrences[i]; if (n) { if (n + entries > this._FoldingRangesLimit) { maxIndent = i; break; } entries += n; } } const tabSize = model.getOptions().tabSize; // reverse and create arrays of the exact length let startIndexes = new Uint32Array(entries); let endIndexes = new Uint32Array(entries); for (let i = this._length - 1, k = 0; i >= 0; i--) { let startIndex = this._startIndexes[i]; let lineContent = model.getLineContent(startIndex); let indent = computeIndentLevel(lineContent, tabSize); if (indent < maxIndent) { startIndexes[k] = startIndex; endIndexes[k] = this._endIndexes[i]; k++; } } return new FoldingRanges(startIndexes, endIndexes); } }
export function computeRanges(model: ITextModel, offSide: boolean, markers?: FoldingMarkers, FoldingRangesLimit = MAX_FOLDING_REGIONS_FOR_INDENT_LIMIT): FoldingRanges { const tabSize = model.getOptions().tabSize; let result = new RangesCollector(FoldingRangesLimit); let pattern = void 0; if (markers) { pattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`); } let previousRegions: PreviousRegion[] = []; previousRegions.push({ indent: -1, line: model.getLineCount() + 1, marker: false }); // sentinel, to make sure there's at least one entry for (let line = model.getLineCount(); line > 0; line--) { let lineContent = model.getLineContent(line); let indent = computeIndentLevel(lineContent, tabSize); let previous = previousRegions[previousRegions.length - 1]; if (indent === -1) { if (offSide && !previous.marker) { // for offSide languages, empty lines are associated to the next block previous.line = line; } continue; // only whitespace } let m; if (pattern && (m = lineContent.match(pattern))) { // folding pattern match if (m[1]) { // start pattern match // discard all regions until the folding pattern let i = previousRegions.length - 1; while (i > 0 && !previousRegions[i].marker) { i--; } if (i > 0) { previousRegions.length = i + 1; previous = previousRegions[i]; // new folding range from pattern, includes the end line result.insertFirst(line, previous.line, indent); previous.marker = false; previous.indent = indent; previous.line = line; continue; } else { // no end marker found, treat line as a regular line } } else { // end pattern match previousRegions.push({ indent: -2, line, marker: true }); continue; } } if (previous.indent > indent) { // discard all regions with larger indent do { previousRegions.pop(); previous = previousRegions[previousRegions.length - 1]; } while (previous.indent > indent); // new folding range let endLineNumber = previous.line - 1; if (endLineNumber - line >= 1) { // needs at east size 1 result.insertFirst(line, endLineNumber, indent); } } if (previous.indent === indent) { previous.line = line; } else { // previous.indent < indent // new region with a bigger indent previousRegions.push({ indent, line, marker: false }); } } return result.toIndentRanges(model); }
export function computeRanges(model: ITextModel, offSide: boolean, markers?: FoldingMarkers, minimumRangeSize: number = 1): IndentRange[] { let result: IndentRange[] = []; let pattern = void 0; if (markers) { pattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`); } let previousRegions: PreviousRegion[] = []; previousRegions.push({ indent: -1, line: model.getLineCount() + 1, marker: null }); // sentinel, to make sure there's at least one entry for (let line = model.getLineCount(); line > 0; line--) { let indent = model.getIndentLevel(line); let previous = previousRegions[previousRegions.length - 1]; if (indent === -1) { if (offSide) { // for offSide languages, empty lines are associated to the next block previous.line = line; } continue; // only whitespace } let m; if (pattern && (m = model.getLineContent(line).match(pattern))) { // folding pattern match if (m[1]) { // start pattern match if (previous.indent >= 0 && !previous.marker) { // discard all regions until the folding pattern do { previousRegions.pop(); previous = previousRegions[previousRegions.length - 1]; } while (previous.indent >= 0 && !previous.marker); } if (previous.marker) { // new folding range from pattern, includes the end line result.push(new IndentRange(line, previous.line, indent, true)); previous.marker = null; previous.indent = indent; previous.line = line; } } else { // end pattern match previousRegions.push({ indent: -2, line, marker: pattern }); } } else { if (previous.indent > indent) { // discard all regions with larger indent do { previousRegions.pop(); previous = previousRegions[previousRegions.length - 1]; } while (previous.indent > indent); // new folding range let endLineNumber = previous.line - 1; if (endLineNumber - line >= minimumRangeSize) { result.push(new IndentRange(line, endLineNumber, indent)); } } if (previous.indent === indent) { previous.line = line; } else { // previous.indent < indent // new region with a bigger indent previousRegions.push({ indent, line, marker: null }); } } } return result.reverse(); }
public getIndent(index: number) { const lineNumber = this.getStartLineNumber(index); const tabSize = this._model.getOptions().tabSize; const lineContent = this._model.getLineContent(lineNumber); return computeIndentLevel(lineContent, tabSize); }