Noxbru
Noxbru

Reputation: 472

Adding a marker for vim syntax folding

I usually code in C, and I have in my .vimrc set foldmethod=syntax, which works very well as it folds braces and comments and everything.

But sometimes I need to fold big chunks of code so that they don't get in my way (for example a group of related functions), and I usually do this with set foldmethod=marker and the markers >>> and <<<.

I have been trying to add a new sync region and the nearest thing I have come with is:

syn region cFoldMarkers start='>>>' end='<<<' containedin=cComment transparent fold

but this creates a mess as it somehow it matches with comments.

Is there a way of achieving both objectives? or should I give up of doing this with syntax and just set markers for braces, comments and my custom one?

Thanks in advance

Upvotes: 5

Views: 1024

Answers (2)

Jorenar
Jorenar

Reputation: 2884

Plugin syntaxMarkerFold adds this functionality.


containedin=cComment means that whole region (whole fold) is contained in single comment; we want only markers to be in comments (two separate comments).
Surprisingly enough, it matches markers not belonging to any syntax group too; it's also undesired behaviour for us.

By leaving only

syn region cFoldMarkers start='>>>' end='<<<' transparent fold

it finds start of region and folds it. But it doesn't have so much luck with the end, so Vim just folds to the end of file.

So we need to add matching comments to the RegExp of region (\s*//.\{-}) and for some pecultiar reason, define matchgroup=Comment

syn region cFoldMarkers matchgroup=Comment start='\s*//.\{-}>>>' end='\s*//.\{-}<<<' transparent fold

Now it should fold just where we want.


Of course, there are more edge cases, which require more handling.
We would also like to be able to use any marker and different valid comments than just //.
Not to mention leveled marker folding (e.g. {{{1).

Have a look at the code of my syntaxMarkerFold plugin to check how I've resolved those issues.

Upvotes: 1

Noxbru
Noxbru

Reputation: 472

Okay, after... like 5 hours trying to do it with syntax folding, I have given up and changed to expression folding.

Following this question: LLVM-IR syntax folding for vim I have created a folding function that more or less does what I want:

function! CFold()
    let this_line = getline(v:lnum)

    " Matching of braces
    if match(this_line, '}') >= 0
        return 's1'
    elseif match(this_line, '{$') >= 0
        return 'a1'
    " Matching of comments
    elseif match(this_line, '/\*') >= 0
        if match(this_line, '\*/$') == -1
            return 'a1'
        " Matching custom folding
        elseif match(this_line, '>>>') >= 0
            return 'a1'
        elseif match(this_line, '<<<') >= 0
            return 's1'
        endif
    elseif match(this_line, '\*/$') >= 0
        return 's1'
    endif
    return '='
endfunction

setlocal foldmethod=expr
setlocal foldexpr=CFold()

Upvotes: 1

Related Questions