@@ -12,11 +12,13 @@ export class IndentRange {
1212 startLineNumber : number ;
1313 endLineNumber : number ;
1414 indent : number ;
15+ marker : boolean ;
1516
16- constructor ( startLineNumber : number , endLineNumber : number , indent : number ) {
17+ constructor ( startLineNumber : number , endLineNumber : number , indent : number , marker ?: boolean ) {
1718 this . startLineNumber = startLineNumber ;
1819 this . endLineNumber = endLineNumber ;
1920 this . indent = indent ;
21+ this . marker = marker ;
2022 }
2123
2224 public static deepCloneArr ( indentRanges : IndentRange [ ] ) : IndentRange [ ] {
@@ -29,12 +31,27 @@ export class IndentRange {
2931 }
3032}
3133
32- export function computeRanges ( model : ITextModel , offSide : boolean , minimumRangeSize : number = 1 ) : IndentRange [ ] {
34+ export interface FoldMarkers {
35+ start : string ;
36+ end : string ;
37+ indent ?: number ;
38+ }
39+
40+ interface PreviousRegion { indent : number ; line : number ; marker : RegExp ; } ;
41+
42+ export function computeRanges ( model : ITextModel , offSide : boolean , markers ?: FoldMarkers , minimumRangeSize : number = 1 ) : IndentRange [ ] {
3343
3444 let result : IndentRange [ ] = [ ] ;
3545
36- let previousRegions : { indent : number , line : number } [ ] = [ ] ;
37- previousRegions . push ( { indent : - 1 , line : model . getLineCount ( ) + 1 } ) ; // sentinel, to make sure there's at least one entry
46+ let pattern = void 0 ;
47+ let patternIndent = - 1 ;
48+ if ( markers ) {
49+ pattern = new RegExp ( `(${ markers . start } )|(?:${ markers . end } )` ) ;
50+ patternIndent = typeof markers . indent === 'number' ? markers . indent : - 1 ;
51+ }
52+
53+ let previousRegions : PreviousRegion [ ] = [ ] ;
54+ previousRegions . push ( { indent : - 1 , line : model . getLineCount ( ) + 1 , marker : null } ) ; // sentinel, to make sure there's at least one entry
3855
3956 for ( let line = model . getLineCount ( ) ; line > 0 ; line -- ) {
4057 let indent = model . getIndentLevel ( line ) ;
@@ -46,26 +63,48 @@ export function computeRanges(model: ITextModel, offSide: boolean, minimumRangeS
4663 }
4764 continue ; // only whitespace
4865 }
66+ let m ;
67+ if ( pattern && ( patternIndent === - 1 || patternIndent === indent ) && ( m = model . getLineContent ( line ) . match ( pattern ) ) ) {
68+ // folding pattern match
69+ if ( m [ 1 ] ) { // start pattern match
70+ if ( previous . indent >= 0 && ! previous . marker ) {
4971
72+ // discard all regions until the folding pattern
73+ do {
74+ previousRegions . pop ( ) ;
75+ previous = previousRegions [ previousRegions . length - 1 ] ;
76+ } while ( previous . indent >= 0 && ! previous . marker ) ;
77+ }
78+ if ( previous . marker ) {
79+ // new folding range from pattern, includes the end line
80+ result . push ( new IndentRange ( line , previous . line , indent , true ) ) ;
81+ previous . marker = null ;
82+ previous . indent = indent ;
83+ previous . line = line ;
84+ }
85+ } else { // end pattern match
86+ previousRegions . push ( { indent : - 2 , line, marker : pattern } ) ;
87+ }
88+ } else {
89+ if ( previous . indent > indent ) {
90+ // discard all regions with larger indent
91+ do {
92+ previousRegions . pop ( ) ;
93+ previous = previousRegions [ previousRegions . length - 1 ] ;
94+ } while ( previous . indent > indent ) ;
5095
51- if ( previous . indent > indent ) {
52- // discard all regions with larger indent
53- do {
54- previousRegions . pop ( ) ;
55- previous = previousRegions [ previousRegions . length - 1 ] ;
56- } while ( previous . indent > indent ) ;
57-
58- // new folding range
59- let endLineNumber = previous . line - 1 ;
60- if ( endLineNumber - line >= minimumRangeSize ) {
61- result . push ( new IndentRange ( line , endLineNumber , indent ) ) ;
96+ // new folding range
97+ let endLineNumber = previous . line - 1 ;
98+ if ( endLineNumber - line >= minimumRangeSize ) {
99+ result . push ( new IndentRange ( line , endLineNumber , indent ) ) ;
100+ }
101+ }
102+ if ( previous . indent === indent ) {
103+ previous . line = line ;
104+ } else { // previous.indent < indent
105+ // new region with a bigger indent
106+ previousRegions . push ( { indent , line , marker : null } ) ;
62107 }
63- }
64- if ( previous . indent === indent ) {
65- previous . line = line ;
66- } else { // previous.indent < indent
67- // new region with a bigger indent
68- previousRegions . push ( { indent, line } ) ;
69108 }
70109 }
71110
0 commit comments