summaryrefslogtreecommitdiff
path: root/lua/lvim/core/treesitter.lua
diff options
context:
space:
mode:
authorkylo252 <[email protected]>2022-11-16 11:13:41 +0100
committerGitHub <[email protected]>2022-11-16 11:13:41 +0100
commit358ebdfe715ef10b77d2e5eb94ae5b2425bd8907 (patch)
treee40df667af8e23a914f0255f17f772d508e6114b /lua/lvim/core/treesitter.lua
parentae89f073773f8de42ebeb408aaf97038a79060e1 (diff)
fix(tree-sitter): force update bundled parsers (#3475)
Diffstat (limited to 'lua/lvim/core/treesitter.lua')
-rw-r--r--lua/lvim/core/treesitter.lua90
1 files changed, 87 insertions, 3 deletions
diff --git a/lua/lvim/core/treesitter.lua b/lua/lvim/core/treesitter.lua
index 9b50986e..a1bcb121 100644
--- a/lua/lvim/core/treesitter.lua
+++ b/lua/lvim/core/treesitter.lua
@@ -1,11 +1,27 @@
local M = {}
local Log = require "lvim.core.log"
-M.config = function()
+function M.config()
lvim.builtin.treesitter = {
on_config_done = nil,
- ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages
+
+ -- A list of parser names, or "all"
+ ensure_installed = {},
+
+ -- List of parsers to ignore installing (for "all")
ignore_install = {},
+
+ -- A directory to install the parsers into.
+ -- By default parsers are installed to either the package dir, or the "site" dir.
+ -- If a custom path is used (not nil) it must be added to the runtimepath.
+ parser_install_dir = nil,
+
+ -- Install parsers synchronously (only applied to `ensure_installed`)
+ sync_install = false,
+
+ -- Automatically install missing parsers when entering buffer
+ auto_install = false,
+
matchup = {
enable = false, -- mandatory, false will disable the whole extension
-- disable = { "c", "ruby" }, -- optional, list of language that will be disabled
@@ -109,7 +125,70 @@ M.config = function()
}
end
-M.setup = function()
+---@class bundledParsersOpts
+---@field name_only boolean
+---@field filter function
+
+---Retrives a list of bundled parsers paths (any parser not found in default `install_dir`)
+---@param opts bundledParsersOpts
+---@return string[]
+local function get_parsers(opts)
+ opts = opts or {}
+ opts.filter = opts.filter or function()
+ return true
+ end
+
+ local bundled_parsers = vim.tbl_filter(opts.filter, vim.api.nvim_get_runtime_file("parser/*.so", true))
+
+ if opts.name_only then
+ bundled_parsers = vim.tbl_map(function(parser)
+ return vim.fn.fnamemodify(parser, ":t:r")
+ end, bundled_parsers)
+ end
+
+ return bundled_parsers
+end
+
+---Checks if parser is installed with nvim-treesitter
+---@param lang string
+---@return boolean
+local function is_installed(lang)
+ local configs = require "nvim-treesitter.configs"
+ local result = get_parsers {
+ filter = function(parser)
+ local install_dir = configs.get_parser_install_dir()
+ return vim.startswith(parser, install_dir) and (vim.fn.fnamemodify(parser, ":t:r") == lang)
+ end,
+ }
+ local parser_file = result and result[1] or ""
+ local stat = vim.loop.fs_stat(parser_file)
+ return stat and stat.type == "file"
+end
+
+local function ensure_updated_bundled()
+ local configs = require "nvim-treesitter.configs"
+ local bundled_parsers = get_parsers {
+ name_only = true,
+ filter = function(parser)
+ local install_dir = configs.get_parser_install_dir()
+ return not vim.startswith(parser, install_dir)
+ end,
+ }
+
+ vim.api.nvim_create_autocmd("VimEnter", {
+ callback = function()
+ local missing = vim.tbl_filter(function(parser)
+ return not is_installed(parser)
+ end, bundled_parsers)
+
+ if #missing > 0 then
+ vim.cmd { cmd = "TSInstall", args = missing, bang = true }
+ end
+ end,
+ })
+end
+
+function M.setup()
-- avoid running in headless mode since it's harder to detect failures
if #vim.api.nvim_list_uis() == 0 then
Log:debug "headless mode detected, skipping running setup for treesitter"
@@ -126,9 +205,14 @@ M.setup = function()
treesitter_configs.setup(opts)
+ ensure_updated_bundled()
+
if lvim.builtin.treesitter.on_config_done then
lvim.builtin.treesitter.on_config_done(treesitter_configs)
end
end
+M.get_parsers = get_parsers
+M.is_installed = is_installed
+
return M