fix: load compiled parser.so via vim.treesitter.language.add

nvim-treesitter's :TSInstall reloads the parsers module from source
(package.loaded['nvim-treesitter.parsers'] = nil), which wipes runtime
config modifications. The old get_parser_configs() approach no longer
works for registering custom parsers with :TSInstall.

New approach:
- The mason build script now compiles parser.c into parser.so during
  :MasonInstall tia-lsp (requires cc/gcc)
- The plugin's setup_syntax finds parser.so via:
  1. opts.ts_parser_path (explicit override)
  2. Mason package dir (resolved from exepath('tia-lsp'))
  3. ~/dev/tia-lsp/parser.so (local dev fallback)
- Loads it with vim.treesitter.language.add('scl', { path = parser.so })
- Starts highlighting via vim.treesitter.start(bufnr, 'scl') in the
  FileType autocmd
- Falls back to notifying the user if no parser.so is found
- Still registers with nvim-treesitter's parsers table as best-effort
  for :TSInstall support (won't survive reload, but works in-session)
This commit is contained in:
2026-07-18 18:01:32 +02:00
parent bd50f7b459
commit aebffc34e7
+76 -5
View File
@@ -53,6 +53,9 @@ function M.setup(opts)
pattern = "scl",
callback = function(args)
start_lsp(args.buf)
M.notify_parser_install_if_needed(args.buf)
-- Start tree-sitter highlighting if the parser is registered
pcall(vim.treesitter.start, args.buf, "scl")
end,
})
@@ -65,6 +68,8 @@ function M.setup(opts)
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.bo[bufnr].filetype == "scl" and vim.api.nvim_buf_is_loaded(bufnr) then
start_lsp(bufnr)
M.notify_parser_install_if_needed(bufnr)
pcall(vim.treesitter.start, bufnr, "scl")
end
end
@@ -78,14 +83,80 @@ function M.setup(opts)
end
end
-- Find a compiled tree-sitter parser (.so) for SCL.
-- Looks in: opts.ts_parser_path, mason package dir, ~/dev/tia-lsp.
-- Returns the path to parser.so, or nil if not found.
function M.find_parser_so(opts)
-- 1. Explicit path from opts
if opts.ts_parser_path and vim.fn.filereadable(opts.ts_parser_path) == 1 then
return opts.ts_parser_path
end
-- 2. Mason install: resolve exepath("tia-lsp") -> real bin -> package dir
local tia_bin = vim.fn.exepath("tia-lsp")
if tia_bin ~= "" then
local real_bin = vim.fn.resolve(vim.fn.fnamemodify(tia_bin, ":p"))
local pkg_dir = vim.fn.fnamemodify(real_bin, ":h:h")
local so = pkg_dir .. "/parser.so"
if vim.fn.filereadable(so) == 1 then
return so
end
end
-- 3. Local dev path
local dev_so = vim.fn.expand("~/dev/tia-lsp/parser.so")
if vim.fn.filereadable(dev_so) == 1 then
return dev_so
end
return nil
end
-- Notify the user once per session if the tree-sitter parser isn't available.
local parser_notified = false
function M.notify_parser_install_if_needed(bufnr)
if parser_notified then return end
if vim.bo[bufnr].filetype ~= "scl" then return end
local ok = pcall(vim.treesitter.get_parser, bufnr, "scl")
if ok then return end
parser_notified = true
vim.schedule(function()
local msg = "SCL: Tree-sitter parser not found. "
if vim.fn.exepath("tia-lsp") ~= "" then
msg = msg .. "Run :MasonInstall tia-lsp to install it."
else
msg = msg .. "Install tia-lsp via mason or compile parser.so manually."
end
vim.notify(msg, vim.log.levels.INFO)
end)
end
function M.setup_syntax(opts)
local has_ts, ts = pcall(require, "nvim-treesitter.parsers")
if has_ts and ts.get_parser_configs then
local ok, parser_config = pcall(ts.get_parser_configs)
if ok and parser_config then
-- Load the compiled tree-sitter parser (.so) via Neovim's built-in API.
-- This bypasses nvim-treesitter's install system, which reloads its
-- parsers module from source on :TSInstall and wipes runtime config.
local parser_so = M.find_parser_so(opts)
if parser_so then
local ok, err = pcall(vim.treesitter.language.add, "scl", { path = parser_so })
if not ok then
vim.notify(
"SCL: Failed to load tree-sitter parser from " .. parser_so .. ": " .. tostring(err),
vim.log.levels.WARN
)
end
end
-- Also register with nvim-treesitter (best-effort, for :TSInstall support
-- in sessions where the user wants to install from source).
local has_ts, parsers = pcall(require, "nvim-treesitter.parsers")
if has_ts and type(parsers) == "table" then
local parser_config
if type(parsers.get_parser_configs) == "function" then
parser_config = parsers.get_parser_configs()
else
parser_config = parsers
end
if type(parser_config) == "table" then
parser_config.scl = {
install_info = {
-- Override via setup({ ts_parser_url = "https://your-gitea/tia-lsp.git" }).
url = opts.ts_parser_url
or "https://gitea.l-tech.rs/lazar/tia-lsp.git",
files = { "src/parser.c" },