Update 3: Improved the code for extraction of fillchar from ‘fillchars’ option and taking ‘foldcolumn’ into account.

Update 2: Fixed the regex for removing the fold marker from the displayed text by splitting the ‘{{{‘ in the regex to ‘{{‘. ‘{‘ so that it is not treated as a fold marker by vim. Thanks to Amadan on reddit here.

Update: Fixed ‘NeatFoldText()’ to get foldchar from ‘fillchars’ settings.

Initially when I started using VIM, I had borrowed configs from my mentor Vagmi Mudumbai (to whom I am eternally thankful!!!).

He used folding in VIM actively. I on the other hand though, barely got around using VIM itself, found folding to be quite confusing and hard to work with. The first folding mapping I learnt was ‘zR’, which is for recursively opening all folds in the current documents, so I don’t have to deal / worry about them. I became so habitual to using ‘zR’ that one day I decided I was better off without folding altogether, after all I was clearly not using folding anyways. That day I removed folding related configs from my ~/.vimrc. Much later as I became more comfortable using VIM, I came back to folding and have not looked back ever since!

I have always thought though that the vim’s default folding look and feel could use some beautification, and although I have been aware about ‘foldtext’, I never really got around to understanding how to take advantage of it to customize things like I wanted.

After quite a bit of effort and quite a few iterations, I now present to you my ‘NeatFoldText()’, a vim function that makes the fold line look really impressive, meaningful and neat at the same time! It puts focus on what’s most important (the text in the start of the fold). And right aligns the number of lines in the fold. Also formats it to fixed size which makes it look neat and consistent.

Put this in your $VIMRC (~/.vimrc) :

function! NeatFoldText() "{{{2 let line = ' ' . substitute(getline(v:foldstart), '^\s*"\?\s*\|\s*"\?\s*{{' . '{\d*\s*', '', 'g') . ' ' let lines_count = v:foldend - v:foldstart + 1 let lines_count_text = '| ' . printf("%10s", lines_count . ' lines') . ' |' let foldchar = matchstr(&fillchars, 'fold:\zs.') let foldtextstart = strpart('+' . repeat(foldchar, v:foldlevel*2) . line, 0, (winwidth(0)*2)/3) let foldtextend = lines_count_text . repeat(foldchar, 8) let foldtextlength = strlen(substitute(foldtextstart . foldtextend, '.', 'x', 'g')) + &foldcolumn return foldtextstart . repeat(foldchar, winwidth(0)-foldtextlength) . foldtextend endfunction set foldtext=NeatFoldText() " }}}2 1 2 3 4 5 6 7 8 9 10 11 12 function ! NeatFoldText ( ) "{{{2 let line = ' ' . substitute ( getline ( v:foldstart ) , '^\s*"\?\s*\|\s*"\?\s*{{' . '{\d*\s*' , '' , 'g' ) . ' ' let lines_count = v:foldend - v:foldstart + 1 let lines_count_text = '| ' . printf ( "%10s" , lines_count . ' lines' ) . ' |' let foldchar = matchstr ( &fillchars , 'fold:\zs.' ) let foldtextstart = strpart ( '+' . repeat ( foldchar , v:foldlevel * 2 ) . line , 0 , ( winwidth ( 0 ) * 2 ) / 3 ) let foldtextend = lines_count_text . repeat ( foldchar , 8 ) let foldtextlength = strlen ( substitute ( foldtextstart . foldtextend , '.' , 'x' , 'g' ) ) + &foldcolumn return foldtextstart . repeat ( foldchar , winwidth ( 0 ) - foldtextlength ) . foldtextend endfunction set foldtext = NeatFoldText ( ) " }}}2

And this is how the fold text look like :

This example should also prove to be a great starting point / example for those who wish to tweak the folding text further.