mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 19:17:02 -04:00
180 lines
4.5 KiB
Lua
180 lines
4.5 KiB
Lua
local M = {}
|
|
|
|
M.tiers = { 'stable', 'unstable', 'unmaintained', 'unsupported' }
|
|
|
|
---@class TSConfig
|
|
---@field install_dir string
|
|
|
|
---@type TSConfig
|
|
local config = {
|
|
install_dir = vim.fs.joinpath(vim.fn.stdpath('data') --[[@as string]], 'site'),
|
|
}
|
|
|
|
---Setup call for users to override configuration configurations.
|
|
---@param user_data TSConfig? user configuration table
|
|
function M.setup(user_data)
|
|
if user_data then
|
|
if user_data.install_dir then
|
|
user_data.install_dir = vim.fs.normalize(user_data.install_dir)
|
|
vim.o.rtp = user_data.install_dir .. ',' .. vim.o.rtp
|
|
end
|
|
config = vim.tbl_deep_extend('force', config, user_data)
|
|
end
|
|
end
|
|
|
|
-- Returns the install path for parsers, parser info, and queries.
|
|
-- If the specified directory does not exist, it is created.
|
|
---@param dir_name string
|
|
---@return string
|
|
function M.get_install_dir(dir_name)
|
|
local dir = vim.fs.joinpath(config.install_dir, dir_name)
|
|
|
|
if not vim.uv.fs_stat(dir) then
|
|
local ok, err = pcall(vim.fn.mkdir, dir, 'p', '0755')
|
|
if not ok then
|
|
local log = require('nvim-treesitter.log')
|
|
log.error(err --[[@as string]])
|
|
end
|
|
end
|
|
return dir
|
|
end
|
|
|
|
---@param type 'queries'|'parsers'?
|
|
---@return string[]
|
|
function M.get_installed(type)
|
|
local installed = {} --- @type table<string, boolean>
|
|
if not (type and type == 'parsers') then
|
|
for f in vim.fs.dir(M.get_install_dir('queries')) do
|
|
installed[f] = true
|
|
end
|
|
end
|
|
if not (type and type == 'queries') then
|
|
for f in vim.fs.dir(M.get_install_dir('parser')) do
|
|
installed[vim.fn.fnamemodify(f, ':r')] = true
|
|
end
|
|
end
|
|
return vim.tbl_keys(installed)
|
|
end
|
|
|
|
-- Get a list of all available parsers
|
|
---@param tier integer? only get parsers of specified tier
|
|
---@return string[]
|
|
function M.get_available(tier)
|
|
vim.api.nvim_exec_autocmds('User', { pattern = 'TSUpdate' })
|
|
local parsers = require('nvim-treesitter.parsers')
|
|
--- @type string[]
|
|
local languages = vim.tbl_keys(parsers)
|
|
table.sort(languages)
|
|
if tier then
|
|
languages = vim.tbl_filter(
|
|
--- @param p string
|
|
function(p)
|
|
return parsers[p] ~= nil and parsers[p].tier == tier
|
|
end,
|
|
languages
|
|
)
|
|
end
|
|
return languages
|
|
end
|
|
|
|
local function expand_tiers(list)
|
|
for i, tier in ipairs(M.tiers) do
|
|
if vim.list_contains(list, tier) then
|
|
list = vim.tbl_filter(
|
|
--- @param l string
|
|
function(l)
|
|
return l ~= tier
|
|
end,
|
|
list
|
|
)
|
|
vim.list_extend(list, M.get_available(i))
|
|
end
|
|
end
|
|
|
|
return list
|
|
end
|
|
|
|
---Normalize languages
|
|
---@param languages? string[]|string
|
|
---@param skip? { missing: boolean?, unsupported: boolean?, installed: boolean?, dependencies: boolean? }
|
|
---@return string[]
|
|
function M.norm_languages(languages, skip)
|
|
if not languages then
|
|
return {}
|
|
elseif type(languages) == 'string' then
|
|
languages = { languages }
|
|
end
|
|
|
|
if vim.list_contains(languages, 'all') then
|
|
if skip and skip.missing then
|
|
return M.get_installed()
|
|
end
|
|
languages = M.get_available()
|
|
end
|
|
|
|
languages = expand_tiers(languages)
|
|
|
|
if skip and skip.installed then
|
|
local installed = M.get_installed()
|
|
languages = vim.tbl_filter(
|
|
--- @param v string
|
|
function(v)
|
|
return not vim.list_contains(installed, v)
|
|
end,
|
|
languages
|
|
)
|
|
end
|
|
|
|
if skip and skip.missing then
|
|
local installed = M.get_installed()
|
|
languages = vim.tbl_filter(
|
|
--- @param v string
|
|
function(v)
|
|
return vim.list_contains(installed, v)
|
|
end,
|
|
languages
|
|
)
|
|
end
|
|
|
|
local parsers = require('nvim-treesitter.parsers')
|
|
languages = vim.tbl_filter(
|
|
--- @param v string
|
|
function(v)
|
|
if parsers[v] ~= nil then
|
|
return true
|
|
else
|
|
require('nvim-treesitter.log').warn('skipping unsupported language: ' .. v)
|
|
return false
|
|
end
|
|
end,
|
|
languages
|
|
)
|
|
|
|
if skip and skip.unsupported then
|
|
languages = vim.tbl_filter(
|
|
--- @param v string
|
|
function(v)
|
|
return not (parsers[v] and parsers[v].tier and parsers[v].tier == 4)
|
|
end,
|
|
languages
|
|
)
|
|
end
|
|
|
|
if not (skip and skip.dependencies) then
|
|
for _, lang in pairs(languages) do
|
|
if parsers[lang] and parsers[lang].requires then
|
|
vim.list_extend(languages, parsers[lang].requires)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- TODO(clason): remove Nvim 0.11 compat
|
|
if vim.list then
|
|
return vim.list.unique(languages)
|
|
else
|
|
table.sort(languages)
|
|
return vim.fn.uniq(languages) --[=[@as string[] ]=]
|
|
end
|
|
end
|
|
|
|
return M
|