Is there a way to use multiple vim folding methods at once?

I have foldmethod=indent set in my ~/.vimrc, and in general that works for me and I'd like to keep it.

However, there are a few files I have which I edit regularly (and which are under my exclusive control), where I'd like to add in a marker-based system, in particular so that when I open the file a large section I rarely look at (which is already 'delimited' by indent) is pre-folded. It looks like foldmethod=marker would allow me to do that (I don't mind the odd comment in the file to indicate these 'pre-folds' if necessary), but I still want foldmethod=indent set so that I can use zc, zo, and so on to then fold or unfold sections by indent. As far as I can tell I can't set foldmethod to multiple values.

Is there another way I can achieve this (ideally using something embedded in the file itself)?


Solution 1:

Each window can have its own local value of 'foldmethod'; what you set in ~/.vimrc is just the global default. There are multiple ways to set a different local value for a particular buffer:

  1. Manually with :setlocal foldmethod=marker
  2. For a particular filetype (e.g. Java files): :autocmd FileType java setlocal foldmethod=marker (or in ~/.vim/after/ftplugin/java.vim)
  3. For particular file(s): :autocmd BufRead /path/to/file setlocal foldmethod=marker
  4. Inside the file itself via a modeline (since you have to add the markers anyway, I would prefer this):

/* vim: set fdm=manual : */

There still can be only one fold method inside a single window. If you want to employ different strategies, you have to choose a more flexible method (e.g. expr), and re-implement the "other" method(s) in there (e.g. by making your 'foldexpr' consider the indent). Or you use two window splits for the same buffer, and set different foldmethods for each split.

Since that probably isn't what you want to hear, you could hack something together with an :autocmd CursorMoved that switches the foldmethod based on the current line:

" Use markers when in the first 100 lines, else use indent.
:autocmd CursorMoved,CursorMovedI <buffer> let &l:foldmethod = (line('.') <= 100 ? 'manual' : 'indent')