Treesitter Setup
Treesitter is a parser generator that understands your code's actual syntax tree (not just regex patterns). This enables accurate syntax highlighting, smart code folding, and language-aware selection.
Core Idea
Traditional syntax highlighting = regex patterns on text. Treesitter = proper parse tree. The result is accurate highlighting even in complex or multi-language files (like PHP with inline HTML).
Plugin Setup
lua/plugins/treesitter.lua
return {
{
"nvim-treesitter/nvim-treesitter",
version = false,
build = ":TSUpdate",
event = { "BufReadPost", "BufNewFile" },
dependencies = {
"nvim-treesitter/nvim-treesitter-textobjects", -- treesitter-based text objects
},
config = function()
require("nvim-treesitter.configs").setup({
-- Install parsers for these languages
ensure_installed = {
"lua", "python", "javascript", "typescript",
"php", "bash", "json", "yaml", "toml",
"html", "css", "markdown", "markdown_inline",
"regex", "vim", "vimdoc", "query",
"go", "rust", "c", "cpp",
"sql", "dockerfile", "terraform",
},
-- Install parsers synchronously (only first time)
sync_install = false,
-- Auto-install missing parsers
auto_install = true,
-- Highlighting
highlight = {
enable = true,
-- Disable for large files (performance)
disable = function(lang, buf)
local max_filesize = 100 * 1024 -- 100 KB
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
if ok and stats and stats.size > max_filesize then
return true
end
end,
additional_vim_regex_highlighting = false,
},
-- Incremental selection
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
-- Indentation based on treesitter
indent = {
enable = true,
},
-- Treesitter text objects
textobjects = {
select = {
enable = true,
lookahead = true, -- jump ahead to next text object
keymaps = {
["af"] = "@function.outer",
["if"] = "@function.inner",
["ac"] = "@class.outer",
["ic"] = "@class.inner",
["al"] = "@loop.outer",
["il"] = "@loop.inner",
["aa"] = "@parameter.outer",
["ia"] = "@parameter.inner",
["ai"] = "@conditional.outer",
["ii"] = "@conditional.inner",
},
},
move = {
enable = true,
goto_next_start = {
["]f"] = "@function.outer",
["]c"] = "@class.outer",
},
goto_previous_start = {
["[f"] = "@function.outer",
["[c"] = "@class.outer",
},
},
swap = {
enable = true,
swap_next = { ["<leader>a"] = "@parameter.inner" },
swap_previous = { ["<leader>A"] = "@parameter.inner" },
},
},
})
end,
},
}
Treesitter Text Objects
With nvim-treesitter-textobjects, you get semantic text objects:
| Key | Text Object |
|---|---|
af / if | Around/inner function |
ac / ic | Around/inner class |
al / il | Around/inner loop |
aa / ia | Around/inner function argument |
ai / ii | Around/inner conditional (if) |
Usage:
dif → delete function body (inner)
vaf → visually select entire function
yic → yank class body
cil → change loop body
Navigation with Treesitter
]f → next function start
[f → previous function start
]c → next class
[c → previous class
Managing Parsers
:TSInstall python → install Python parser
:TSUninstall python → remove parser
:TSUpdate → update all parsers
:TSInstallInfo → show all available parsers
:TSConfigInfo → show current config
:InspectTree → open parse tree view for current file
Incremental Selection
With incremental_selection configured:
<C-Space> → start selection at current node
<C-Space> → expand to parent node
<Backspace> → shrink selection back
This selects semantically meaningful regions: word → expression → statement → block → function → file.
Code Folding with Treesitter
lua/config/options.lua
vim.opt.foldmethod = "expr"
vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
vim.opt.foldenable = false -- don't fold on open
vim.opt.foldlevel = 99 -- open all folds by default
Fold commands:
zc → close fold
zo → open fold
za → toggle fold
zR → open all folds
zM → close all folds