refactor(treesitter): use native neovim APIs

This commit is contained in:
Bryan Ramos 2026-05-01 08:59:38 -04:00
parent 6176457340
commit 34c52305af
5 changed files with 57 additions and 185 deletions

View file

@ -1,6 +1,6 @@
# Neovim Configuration # Neovim Configuration
Portable Neovim configuration using lazy.nvim, Mason-managed tooling, native LSP, Treesitter, Telescope, and DAP (Neovim 0.11+, tested on 0.12.1). Portable Neovim configuration using lazy.nvim, Mason-managed tooling, native LSP, native Treesitter, Telescope, and DAP (Neovim 0.11+, tested on 0.12.1).
## Installation ## Installation
@ -19,8 +19,8 @@ git clone --recurse-submodules git@github.com:itme-brain/nixos.git
- **Native LSP** (`vim.lsp.config` / `vim.lsp.enable`) - no manual server list needed - **Native LSP** (`vim.lsp.config` / `vim.lsp.enable`) - no manual server list needed
- **Smart LSP picker** (`<leader>css`) - auto-detects installed servers for current filetype - **Smart LSP picker** (`<leader>css`) - auto-detects installed servers for current filetype
- **Neovim 0.12 compatible** - uses built-in `:lsp` commands and keeps legacy `:Lsp*` aliases working - **Neovim 0.12 compatible** - uses built-in `:lsp` commands and keeps legacy `:Lsp*` aliases working
- **Portable** - Mason is the source of truth for LSP servers, debug adapters, and tree-sitter-cli - **Portable** - Mason is the source of truth for LSP servers and debug adapters
- **Treesitter** - starts via Neovim's native `vim.treesitter.start` - **Treesitter** - uses Neovim's native `vim.treesitter.*` APIs without `nvim-treesitter`
- **Debugging** - lazy-loaded `nvim-dap` stack with Mason-managed adapters - **Debugging** - lazy-loaded `nvim-dap` stack with Mason-managed adapters
## LSP Setup ## LSP Setup
@ -43,10 +43,14 @@ On Neovim 0.12+, start/stop/restart uses the built-in `:lsp` commands under the
## Treesitter ## Treesitter
Treesitter uses the current `nvim-treesitter` main branch API: Treesitter uses Neovim's native API:
- Parsers are installed with `nvim-treesitter`
- Highlighting starts through `vim.treesitter.start` - Highlighting starts through `vim.treesitter.start`
- `tree-sitter-cli` is bootstrapped through Mason when needed for parser installs/updates - Parser/filetype mappings use `vim.treesitter.language.register`
- Parser and query installation is intentionally outside lazy.nvim and Mason
Neovim loads compiled parser libraries from `parser/` directories on `runtimepath` and query files from `queries/<language>/`.
`tree-sitter-cli` is only needed by tools that generate or compile parsers from grammar sources; it is not required at runtime for highlighting.
Prefer providing parsers and queries through Neovim's runtime or a reproducible system/development environment.
## Debugging ## Debugging
@ -94,7 +98,7 @@ Mason installs:
- **nvim-lspconfig** - LSP configurations - **nvim-lspconfig** - LSP configurations
- **nvim-cmp** - completion - **nvim-cmp** - completion
- **telescope.nvim** - fuzzy finder - **telescope.nvim** - fuzzy finder
- **nvim-treesitter** - syntax highlighting - **Native Treesitter** - syntax highlighting
- **nvim-dap** - debug adapter client - **nvim-dap** - debug adapter client
- **nvim-dap-ui** - debugging UI panes - **nvim-dap-ui** - debugging UI panes
- **mason-nvim-dap.nvim** - Mason debug adapter integration - **mason-nvim-dap.nvim** - Mason debug adapter integration

View file

@ -12,13 +12,11 @@
"mason.nvim": { "branch": "main", "commit": "cb8445f8ce85d957416c106b780efd51c6298f89" }, "mason.nvim": { "branch": "main", "commit": "cb8445f8ce85d957416c106b780efd51c6298f89" },
"nvim-dap": { "branch": "master", "commit": "45a69eba683a2c448dd9ecfc4de89511f0646b5f" }, "nvim-dap": { "branch": "master", "commit": "45a69eba683a2c448dd9ecfc4de89511f0646b5f" },
"nvim-lspconfig": { "branch": "master", "commit": "31026a13eefb20681124706a79fc1df6bf11ab27" }, "nvim-lspconfig": { "branch": "master", "commit": "31026a13eefb20681124706a79fc1df6bf11ab27" },
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
"nvim-web-devicons": { "branch": "master", "commit": "4fc505ac7bd7692824a142e96e5f529c133862f8" }, "nvim-web-devicons": { "branch": "master", "commit": "4fc505ac7bd7692824a142e96e5f529c133862f8" },
"oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" }, "oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" },
"pi.nvim": { "branch": "main", "commit": "6e86a704ed6ff488fda78b64f4e564d6ee620785" }, "pi.nvim": { "branch": "main", "commit": "6e86a704ed6ff488fda78b64f4e564d6ee620785" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"render-markdown.nvim": { "branch": "main", "commit": "3f3eea97b80839f629c951ca660ffd125bfa5b34" }, "render-markdown.nvim": { "branch": "main", "commit": "3f3eea97b80839f629c951ca660ffd125bfa5b34" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"treesitter-parser-registry": { "branch": "main", "commit": "6eb15358bb9fc88f0d3401d8538d56652e9bdf3c" },
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
} }

46
lua/config/treesitter.lua Normal file
View file

@ -0,0 +1,46 @@
local treesitter_filetypes = {
"lua",
"c",
"cpp",
"python",
"nix",
"rust",
"bash",
"markdown",
"html",
"javascript",
"javascriptreact",
"css",
"vim",
"gitconfig",
"gitrebase",
"gitattributes",
"gitcommit",
"gitignore",
}
local language_by_filetype = {
gitconfig = "git_config",
gitrebase = "git_rebase",
javascriptreact = "javascript",
}
for filetype, language in pairs(language_by_filetype) do
vim.treesitter.language.register(language, filetype)
end
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("config_treesitter", { clear = true }),
pattern = treesitter_filetypes,
callback = function(event)
local language = vim.treesitter.language.get_lang(vim.bo[event.buf].filetype)
if not language then
return
end
local ok, has_parser = pcall(vim.treesitter.language.add, language)
if ok and has_parser then
pcall(vim.treesitter.start, event.buf, language)
end
end,
})

View file

@ -14,182 +14,7 @@ local mason_ensure_installed = {
"yamlls", -- YAML "yamlls", -- YAML
} }
local treesitter_parsers = {
"lua",
"c",
"cpp",
"python",
"nix",
"rust",
"bash",
"markdown",
"markdown_inline",
"html",
"javascript",
"css",
"vim",
"git_config",
"git_rebase",
"gitattributes",
"gitcommit",
"gitignore",
}
return { return {
{
"neovim-treesitter/nvim-treesitter",
name = "nvim-treesitter",
dependencies = {
"neovim-treesitter/treesitter-parser-registry",
"williamboman/mason.nvim",
},
lazy = false,
build = ":TSUpdate",
init = function()
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("config_treesitter", { clear = true }),
pattern = {
"lua",
"c",
"cpp",
"python",
"nix",
"rust",
"bash",
"markdown",
"html",
"javascript",
"javascriptreact",
"css",
"vim",
"gitconfig",
"gitrebase",
"gitattributes",
"gitcommit",
"gitignore",
},
callback = function(event)
if pcall(vim.treesitter.start, event.buf) then
vim.bo[event.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end
end,
})
end,
config = function()
local treesitter = require("nvim-treesitter")
treesitter.setup()
local function has_c_compiler()
return vim.fn.executable("cc") == 1
or vim.fn.executable("gcc") == 1
or vim.fn.executable("clang") == 1
end
local function install_missing_parsers(missing)
if not has_c_compiler() then
vim.notify_once(
"A C compiler is required to install or update Treesitter parsers",
vim.log.levels.WARN
)
return
end
treesitter.install(missing)
end
local function tree_sitter_cli_works()
if vim.fn.executable("tree-sitter") == 0 then
return false
end
local result = vim.system({ "tree-sitter", "--version" }, { text = true }):wait()
if result.code == 0 then
return true
end
vim.notify_once(
"tree-sitter CLI is installed but cannot run. On NixOS, enable nix-ld so Mason-installed binaries can execute.",
vim.log.levels.WARN
)
return false
end
local function ensure_treesitter_cli(callback)
if tree_sitter_cli_works() then
callback()
return
end
if #vim.api.nvim_list_uis() == 0 then
return
end
local mason_ok, mason = pcall(require, "mason")
local registry_ok, registry = pcall(require, "mason-registry")
if not mason_ok or not registry_ok then
vim.notify_once(
"tree-sitter CLI is required to install or update parsers; install tree-sitter-cli or enable mason.nvim",
vim.log.levels.WARN
)
return
end
mason.setup()
registry.refresh(function()
local package_ok, package = pcall(registry.get_package, "tree-sitter-cli")
if not package_ok then
vim.notify_once(
"Mason registry does not include tree-sitter-cli; install tree-sitter-cli before running :TSUpdate",
vim.log.levels.WARN
)
return
end
if package:is_installed() then
if tree_sitter_cli_works() then
callback()
end
return
end
if package:is_installing() then
vim.notify_once("tree-sitter-cli is already being installed by Mason", vim.log.levels.INFO)
return
end
vim.notify_once("Installing tree-sitter-cli with Mason for Treesitter parser updates", vim.log.levels.INFO)
package:install({}, function(success, error)
if success and tree_sitter_cli_works() then
callback()
else
vim.notify(
"Failed to install tree-sitter-cli with Mason: " .. tostring(error),
vim.log.levels.WARN
)
end
end)
end)
end
local installed = treesitter.get_installed("parsers")
local missing = vim.iter(treesitter_parsers)
:filter(function(parser)
return not vim.tbl_contains(installed, parser)
end)
:totable()
if #missing == 0 then
return
end
ensure_treesitter_cli(function()
if #missing > 0 then
install_missing_parsers(missing)
end
end)
end
},
{ {
"m4xshen/autoclose.nvim", "m4xshen/autoclose.nvim",
config = function() config = function()

View file

@ -3,7 +3,6 @@ return {
"MeanderingProgrammer/render-markdown.nvim", "MeanderingProgrammer/render-markdown.nvim",
ft = { "markdown" }, ft = { "markdown" },
dependencies = { dependencies = {
"nvim-treesitter/nvim-treesitter",
"nvim-tree/nvim-web-devicons", "nvim-tree/nvim-web-devicons",
}, },
opts = { opts = {