March 29, 2010

vim folding makes me happy

When I'm not working with NetBeans and Java, I'm working with vim and python. Vim is unquestionably the best text editor of all time, but this post is not meant as an evangelism. This is aimed at those of you who are already using it.

Maybe you know that vim can do folding. That means that you type "zc" and the piece of code under your cursor neatly folds itself into one line (very much like in NetBeans/Visual Studio/Eclipse etc.), then type "zo" to unfold this line to the whole code. Alternately, use "za" to toggle.
This usually works either manually (you create folds with "zc" and "zf" and whatnot) or via a specialized filetype plugin that will create folds from, for example, sections delimited by curly braces.

It can also work based on indentation. Which happens to work very well for sanely formatted code, and especially for python, where sane formatting is part of syntax. Simplest way to get to this is to simply set foldmethod=indent in your .vimrc.

But this has its own share of drawbacks, namely, the autofolds do not contain a leading line.

For example, in this code:
if something():

the autofolder will collapse the three do_stuff()s into one line labeled "+--- 3 lines:do_stuff(1)". I would like to collapse all four lines into one saying "if something()"

To accomplish this, you have to use a different method. This is what I added to my .vimrc (update: escaped the '<' sign that disappeared when rendering html):
setlocal foldmethod=expr
setlocal foldexpr=(getline(v:lnum)=~'^$')?-1:((indent(v:lnum)<indent(v:lnum+1))?('>'.indent(v:lnum+1)):indent(v:lnum))
set foldtext=getline(v:foldstart)
set fillchars=fold:\ "(there's a space after that \)

You also probably want to have all folds open by default:
set foldlevelstart=999

And to make things ultimately convenient, remap <SPACE> key to open/close a fold in normal mode
nnoremap <space> za

and create a new fold from selection
vnoremap <space> zf

There! Happy faces all around.

(note that this will mess up your foldlevel math, because there will be many foldlevels without corresponding folds. so don't expect serious use of zm/zr. me, i don't care.)