vimtricks.wiki Concise Vim tricks, one at a time.

How do I enable LSP and treesitter-powered code folding in Neovim with nvim-ufo?

Answer

:lua require('ufo').openAllFolds()

Explanation

nvim-ufo is a Neovim plugin that replaces the built-in fold system with one powered by LSP (textDocument/foldingRange) or treesitter. The result is accurate, language-aware folds that reflect real code structure — functions, classes, blocks — rather than just indentation levels.

How it works

nvim-ufo provides fold providers that query LSP or treesitter for fold ranges. A minimal setup:

vim.o.foldcolumn = '1'
vim.o.foldlevel = 99   -- start with all folds open
vim.o.foldlevelstart = 99
vim.o.foldenable = true

require('ufo').setup({
  provider_selector = function(bufnr, filetype, buftype)
    return { 'treesitter', 'indent' }  -- fallback chain
  end
})

The standard Vim fold keybindings (za, zo, zc, zR, zM) work unchanged. nvim-ufo also adds:

  • zR — open all folds (overridden by ufo to use its provider)
  • zM — close all folds
  • K / a custom keymap — peek into a closed fold without opening it:
    vim.keymap.set('n', 'K', function()
      local winid = require('ufo').peekFoldedLinesUnderCursor()
      if not winid then vim.lsp.buf.hover() end
    end)
    

Example

With LSP as the provider, a TypeScript file gets folds at function and class boundaries even if the indentation is inconsistent. A fold on a 200-line class shows a summary line with the number of folded lines, making large files far easier to navigate.

With treesitter fallback, languages without an LSP (shell scripts, config files) still get structural folds based on the grammar.

Tips

  • Use { 'lsp', 'treesitter', 'indent' } as the provider chain to maximize coverage across file types
  • peekFoldedLinesUnderCursor() opens a floating preview window — useful for reading function bodies without disrupting the current fold layout
  • Set foldlevel = 99 and foldlevelstart = 99 so files open fully expanded by default; close folds manually with zM or zm
  • nvim-ufo works alongside plugins like statuscol.nvim for a cleaner fold column display
  • The plugin respects foldenable — disable per-buffer with :set nofoldenable when you want a flat view

Next

How do I jump anywhere on screen with labeled targets using flash.nvim?