Automatically fold function bodies so you can actually see your code structure.
- Neovim 0.10+
- nvim-treesitter with parsers installed for your languages:
:TSInstall ruby python lua javascript rustInspired by this article from matklad - the idea is simple: function signatures are way more useful than function bodies when you're reading code. So let's fold the bodies by default.
- Folds top-level function/method bodies on file open
- Unfolds at cursor when you move your cursor to a fold or use LSP navigation (go to definition, references, etc.)
- Uses Tree-sitter, so it actually understands your code
- Lua
- Ruby
- Python
- JavaScript
- Rust
- PHP
PRs welcome for more languages - the queries are pretty simple.
lazy.nvim:
{
'nuvic/tuck.nvim',
config = function()
require('tuck').setup()
end,
}packer:
use {
'nuvic/tuck.nvim',
config = function()
require('tuck').setup()
end,
}require('tuck').setup({
enabled = true,
auto_unfold = true, -- set to false if you want to disable auto unfold on cursor movement
exclude_filetypes = { 'markdown', 'text' },
exclude_paths = { 'vendor/*', 'node_modules/*' },
integrations = {
fzf_lua = false,
},
})| Command | What it does |
|---|---|
:Tuck enable |
Turn it on |
:Tuck disable |
Turn it off |
:Tuck toggle |
Toggle |
:Tuck fold |
Re-fold everything in current buffer |
tuck uses Tree-sitter queries to find function bodies, then sets up foldexpr to fold them. The queries live in queries/tuck/ if you want to poke around or add new languages.
When you navigate via LSP (go to definition, references, etc.), tuck automatically unfolds the function body at the cursor position. This works with:
- Native LSP navigation (
vim.lsp.buf.definition(), etc.) - fzf-lua LSP pickers (with the integration enabled)
If you use fzf-lua, enable the integration to automatically unfold when jumping via fzf-lua pickers:
require('tuck').setup({
integrations = {
fzf_lua = true,
},
})This patches fzf-lua's file actions (file_edit, file_split, file_vsplit, etc.) and LSP jump functions to unfold at cursor after jumping. Works with all fzf-lua pickers - files, grep, lsp_definitions, you name it.
Your existing fzf-lua keybinds and config are preserved.
If it doesn't seem to work, run :Tuck debug to see what's happening.
MIT