For editing XML files I have the following in my init.vim

" Automatically enable folding of XML-files
augroup XML
  autocmd FileType xml let g:xml_syntax_folding=1
  autocmd FileType xml setlocal foldmethod=syntax
  autocmd FileType xml :syntax on
  autocmd FileType xml :%foldopen!
augroup END

This is fine for small files. From times to times I will edit large (huge) XML-files which open much faster without folding.

My way of doing is to open an new buffer,

set ft=xml  # Which yields an error message because the buffer is empty and no folds can be found
setlocal foldmethod=manual
:r <file>

Is there a better way of disabling folding for a buffer before the file is loaded?

  • When starting a new vim instance I believe you can do vim -c ':set nofoldenable' filename . While in vim the Normal mode command zi toggles 'foldenable'. That might be useful.
    – B Layer
    Dec 3 '19 at 10:44

Automatic detections

The LargeFile plugin automatically disables many options to increase performance, but its exact actions cannot be influenced, so it'll do more than what you have in mind (like completely turning off syntax highlighting for that buffer). You could re-use its mechanism (of hooking into BufReadPre) for your purpose, though.

If this is just for a particular set of XML files together with your config, I would probably just add a simple conditional:

autocmd FileType xml if line('$') > 9999 | setlocal nofoldenable | endif

Instead of checking the number of lines, you could also check file size (getfsize()) or other file attributes.

Manual control

Your current approach with :read is ugly and has many downsides. Unfortunately, the filetype detection flow is not designed to be influenced; built-in features like :help +cmd will run too late, so you cannot avoid the penalty of the very first parsing of folds. You'd have to somehow delay the application of setlocal foldmethod=syntax, e.g. via a fire-once autocmd, in the worst case only on CursorHold,CursorMoved. With that, you could load the xml via :edit +let\ b:nofold=1 large.xml or as a compound filetype: :edit +setf\ xml.large large.xml.

However, I'd strongly favor the automatic detection, as you don't have to think about it.


I would do it like this:

" global variable only needs to be set once
let g:xml_syntax_folding=1

augroup XML | au!
    " start with all folds open for the current window
    " or you can setglobal foldlevelstart=99
    " if you like open folds for all file types
    autocmd FileType xml setlocal foldmethod=syntax foldlevel=99

    " what is huge exactly?
    " btw. it should be line2byte(line('$')+1)-1 but we don't need to be precise
    autocmd FileType xml let &foldenable = (line2byte('$') < 1*1024*1024*1024)

    " do you really need this one?
    autocmd FileType xml syntax on
augroup end

First I applogize for answering my own question, I know this is bad style. However my preferred solution is a mixture of the answers given by @Matt and @Ingo.

The point is that for large files you really want to avoid foldmethod=syntax from the beginning. foldenable just hides the folds, they still get "computed". And it's the computation of the folds which costs a lot of time, not so much the display.

My solution which works well is the following:

augroup XML | au!
  autocmd FileType xml let g:xml_syntax_folding=1
  autocmd FileType xml if (line2byte('$') < 1*32*1024*1024) | setlocal foldmethod=syntax | endif
  autocmd FileType xml silent! :%foldopen!
augroup END
  • Self-answering isn’t bad style! No need to apologize.
    – D. Ben Knoble
    Dec 5 '19 at 16:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.