visual-studio-codevscode-extensionsfoldingblank-line

VSCode: Extension: folding section based on first blank line found or to the start of the next similar section


How can I make a VSCode extension folding strategy based on the first blank line following a starting folding marker?

## Some section   --|
Any text...         |  (this should fold)
...more text.     --|
                       (blank line)
## Another section     (next fold...)

I've tried lots of regex in the language-configuration.json.

    "folding": {
        "markers": {
            "start": "^##",
            "end": "^\\s*$"
    } },

If I change things to test with something other than a blank (or whitespace) line as the end delimiter it works. Can't use the next start marker to mark the end of the last or it includes it in the fold (I tried look ahead regex, but I think the regex are applied line by line and the matches can't span lines?)

It's similar to the folding needed for Markdown which VSCode handles well (don't know if that's using a more complex method like https://code.visualstudio.com/api/references/vscode-api#FoldingRangeProvider).

Maybe something in the fixes for [folding] should not fold white space after function has something to do with it.


Solution

  • What I learned: 1. the begin and end regex are applied line by line. 2. tmLanguage start/end regex will work on blank lines, but currently language-configuration folding doesn't seem to work on blank lines.

    And since blank lines are in this case a hack for ending at the next begin section:

    To solve the problem of folding a section to the next similar section I used the FoldingRangeProvider.

        disposable = vscode.languages.registerFoldingRangeProvider('myExt', {
            provideFoldingRanges(document, context, token) {
                //console.log('folding range invoked'); // comes here on every character edit
                let sectionStart = 0, FR = [], re = /^## /;  // regex to detect start of region
    
                for (let i = 0; i < document.lineCount; i++) {
    
                    if (re.test(document.lineAt(i).text)) {
                        if (sectionStart > 0) {
                            FR.push(new vscode.FoldingRange(sectionStart, i - 1, vscode.FoldingRangeKind.Region));
                        }
                        sectionStart = i;
                    }
                }
                if (sectionStart > 0) { FR.push(new vscode.FoldingRange(sectionStart, document.lineCount - 1, vscode.FoldingRangeKind.Region)); }
    
                return FR;
            }
        });
    

    Set "editor.foldingStrategy": "auto". You can make it more sophisticated to preserve white space between sections.