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

14

3

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)?

Andrew Ferrier

Posted 2013-03-03T11:04:24.813

Reputation: 1 604

I'm also trying to get both fold methods of marker and indent working at the same time. I also believe that to use the fold expression is the best option. Did you find an expression to match both indent and marker? – Jp_ – 2017-03-03T17:51:30.107

1@Jp_ nope, 'fraid not. – Andrew Ferrier – 2017-03-03T22:01:37.900

Answers

10

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')

Ingo Karkat

Posted 2013-03-03T11:04:24.813

Reputation: 19 513

1Thanks. So this tells me I can set foldmethod to marker inside that buffer. But what I'm looking for is something that still allows me to use the indent foldmethod, whilst have some sections (which are delimited by an indent) pre-folded. If I do (4) above, zc, zo, and so on will no longer work as intended in that buffer. I've clarified my question. – Andrew Ferrier – 2013-03-03T11:50:55.263

Your question wasn't clear in that aspect, thanks for the clarification. I've amended my answer. – Ingo Karkat – 2013-03-03T12:34:49.327

Yes, apologies if I wasn't clear. The foldexpr sounds like the best approach but also complicated. I'll give it a try though. +1 for the pointer. – Andrew Ferrier – 2013-03-03T12:38:52.133

Thanks again. I have been trying to write the foldexpr and opened a related Q here which may be of interest: http://superuser.com/questions/560167/how-can-i-write-a-vim-foldexpr-which-is-equivalent-to-foldmethod-indent

– Andrew Ferrier – 2013-03-03T12:55:25.807

@IngoKarkat: In the first paragraph below the line you wrote that there can be only one fold method per buffer. I believe that should be per window. – garyjohn – 2013-03-03T19:07:19.770

@garyjohn: Okay, I've reworded it. The question actually starts with that it's window-local; I meant single buffer here. – Ingo Karkat – 2013-03-03T19:24:40.270

@IngoKarkat: But you can have more than one foldmethod in a single buffer. You just can't have more than one foldmethod at a time in a single window. E.g., edit some file; execute :split; in one window execute :set foldmethod=manual; in the other window execute :set foldmethod=marker. Now execute :windo set foldmethod=?. You'll see that those two windows into the same buffer have different foldmethods. – garyjohn – 2013-03-03T19:37:56.513

@garyjohn: I know, I even mentioned this in my answer. – Ingo Karkat – 2013-03-03T19:51:55.937