Regex-Based Syntax Highlighting Had to Go
A parser that knows exactly where a function ends, not a regex that's guessing — and everything downstream quietly depending on the difference.
For a long time I thought treesitter was a highlighting upgrade: nicer colors, a keyword that's the right shade of purple instead of whatever regex pattern happened to match it. That's true, but it's not the reason it's load-bearing in my config now. The reason is that everything downstream of it needs a real parse tree, not colors.
Here's the setup, which is smaller than I expected the first time I read it:
require("nvim-treesitter").setup()
require("nvim-treesitter").install({ "lua", "vim", "python", "java", "c", "cpp", ... })
vim.api.nvim_create_autocmd("FileType", {
callback = function(ev)
if pcall(vim.treesitter.start) then
vim.bo[ev.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end
end,
})
vim.treesitter.start() builds an actual syntax tree for the buffer: not "these characters look like a keyword," but "this node is a function_definition, this one's its body, this one's a parameter." The indentexpr line hands indentation decisions to that tree too, instead of Vim's regex-based indent heuristics guessing from the previous line.
That tree is what everything else queries. My comment in the textobjects plugin spells out the dependency more bluntly than I would've expected myself to write it:
nvim-treesitter's "main" rewrite moved the textobjects queries out of the core plugin, and nothing else on the runtimepath provides them — so without this, no plugin can ask "where does this function start and end." That includes mini.ai's treesitter spec, which is what wires up
af/ic. Those mappings are dead without this plugin.
So af (a function) only works because treesitter-textobjects can answer a structural query, @function.outer, and hand back exact start/end coordinates. Same story for ]f / [f jumping between function starts, and ]k / [k for classes, both bound straight to that query system. A regex highlighter has no equivalent answer. It can guess that a line looks like the start of a function; it can't tell you, precisely, where that function's body actually closes.
The sticky-scope plugin makes the same point in scrolling form: it shows the enclosing function or class as you scroll past its opening line, because it's reading the same tree, not re-deriving scope from indentation.

