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:
+76
-5
@@ -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" },
|
||||
|
||||
Reference in New Issue
Block a user