How do I use Treesitter for syntax-aware text selection in Neovim?
Answer
Treesitter incremental selection with grn/grc
Explanation
nvim-treesitter provides incremental selection that expands based on the syntax tree rather than simple text patterns. Starting from the cursor, it selects the smallest syntax node, then expands to the parent node with each press.
Setup
require('nvim-treesitter.configs').setup {
incremental_selection = {
enable = true,
keymaps = {
init_selection = 'grn', -- Start selection
node_incremental = 'grn', -- Expand to next node
node_decremental = 'grc', -- Shrink to previous node
scope_incremental = 'grs', -- Expand to scope
},
},
}
How it works
With cursor on a variable name in JavaScript:
const result = items.filter(item => item.active)
grn— selectsitem(identifier)grn— selectsitem.active(member expression)grn— selectsitem => item.active(arrow function)grn— selectsitems.filter(item => item.active)(call expression)grn— selects the entire assignmentgrc— shrinks back one level
Treesitter text objects
With nvim-treesitter-textobjects:
-- Select around/inside functions, classes, etc.
vim.keymap.set({'x', 'o'}, 'af', '@function.outer') -- around function
vim.keymap.set({'x', 'o'}, 'if', '@function.inner') -- inside function
vim.keymap.set({'x', 'o'}, 'ac', '@class.outer') -- around class
vim.keymap.set({'x', 'o'}, 'ic', '@class.inner') -- inside class
Now daf deletes an entire function, cif changes the function body.
Tips
- Treesitter understands the AST, so selections are always syntactically correct
- Works across all languages with Treesitter parsers installed
nvim-treesitter-textobjectsadds@parameter,@conditional,@looptext objects too:TSPlaygroundTogglelets you explore the syntax tree visually- Install parsers with
:TSInstall python javascript goetc.