VIM Better FoldText

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 Reddit Tip

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

Initially when I started using VIM, I had borrowed configs from my mentor Vagmi Mudumbai (1)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 (2)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 (3)~/.vimrc :

function! NeatFoldText()
  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
set foldtext=NeatFoldText()

And this is how the fold text look like :

Neat Fold Text.

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

comments powered by Disqus