mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 19:17:02 -04:00
264 lines
7.4 KiB
Lua
264 lines
7.4 KiB
Lua
local api = vim.api
|
|
local fn = vim.fn
|
|
local luv = vim.loop
|
|
|
|
local M = {}
|
|
M.repositories = {
|
|
javascript = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-javascript",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
},
|
|
c = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-c",
|
|
files = { "src/parser.c" }
|
|
},
|
|
cpp = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-cpp",
|
|
files = { "src/parser.c", "src/scanner.cc" }
|
|
},
|
|
rust = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-rust",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
},
|
|
lua = {
|
|
url = "https://github.com/nvim-treesitter/tree-sitter-lua",
|
|
files = { "src/parser.c", "src/scanner.cc" }
|
|
},
|
|
python = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-python",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
go = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-go",
|
|
files = { "src/parser.c" },
|
|
},
|
|
ruby = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-ruby",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
bash = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-bash",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
php = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-php",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
java = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-java",
|
|
files = { "src/parser.c" },
|
|
},
|
|
html = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-html",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
julia = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-julia",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
},
|
|
json = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-json",
|
|
files = { "src/parser.c" },
|
|
},
|
|
css = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-css",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
},
|
|
ocaml = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-ocaml",
|
|
files = { "src/parser.c", "src/scanner.cc" },
|
|
},
|
|
swift = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-swift",
|
|
files = { "src/parser.c" },
|
|
},
|
|
csharp = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-c-sharp",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
},
|
|
typescript = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-typescript",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
location = "tree-sitter-typescript/typescript"
|
|
},
|
|
tsx = {
|
|
url = "https://github.com/tree-sitter/tree-sitter-typescript",
|
|
files = { "src/parser.c", "src/scanner.c" },
|
|
location = "tree-sitter-tsx/tsx"
|
|
}
|
|
}
|
|
|
|
local function get_package_path()
|
|
for _, path in pairs(api.nvim_list_runtime_paths()) do
|
|
if string.match(path, '.*/nvim%-treesitter') then
|
|
return path
|
|
end
|
|
end
|
|
|
|
return nil, 'Plugin runtime path not found.'
|
|
end
|
|
|
|
local function get_cache_dir()
|
|
local home = fn.get(fn.environ(), 'HOME')
|
|
local xdg_cache = fn.get(fn.environ(), 'XDG_CACHE_HOME')
|
|
|
|
if xdg_cache == 0 then
|
|
xdg_cache = home .. '/.cache'
|
|
end
|
|
|
|
if luv.fs_access(xdg_cache, 'RW') then
|
|
return xdg_cache
|
|
elseif luv.fs_access('/tmp', 'RW') then
|
|
return '/tmp'
|
|
end
|
|
|
|
return nil, 'Invalid cache rights, $XDG_CACHE_HOME or /tmp should be read/write'
|
|
end
|
|
|
|
local function iter_cmd(cmd_list, i, ft)
|
|
if i == #cmd_list then return print('Treesitter parser for '..ft..' has been installed') end
|
|
|
|
local attr = cmd_list[i + 1]
|
|
if attr.info then print(attr.info) end
|
|
|
|
handle = luv.spawn(attr.cmd, attr.opts, vim.schedule_wrap(function(code)
|
|
handle:close()
|
|
if code ~= 0 then return api.nvim_err_writeln(attr.err) end
|
|
iter_cmd(cmd_list, i + 1, ft)
|
|
end))
|
|
end
|
|
|
|
local function run_install(cache_folder, package_path, ft, repo)
|
|
local project_name = 'tree-sitter-'..ft
|
|
local project_repo = cache_folder..'/'..project_name
|
|
-- compile_location only needed for typescript installs.
|
|
local compile_location = cache_folder..'/'..(repo.location or project_name)
|
|
local parser_lib_name = package_path.."/parser/"..ft..".so"
|
|
local command_list = {
|
|
{
|
|
cmd = 'rm',
|
|
opts = {
|
|
args = { '-rf', project_repo },
|
|
}
|
|
},
|
|
{
|
|
cmd = 'git',
|
|
info = 'Downloading...',
|
|
err = 'Error during download, please verify your internet connection',
|
|
opts = {
|
|
args = { 'clone', '--single-branch', '--branch', 'master', '--depth', '1', repo.url, project_name },
|
|
cwd = cache_folder,
|
|
},
|
|
},
|
|
{
|
|
cmd = 'cc',
|
|
info = 'Compiling...',
|
|
err = 'Error during compilation',
|
|
opts = {
|
|
args = vim.tbl_flatten({
|
|
'-o',
|
|
'parser.so',
|
|
'-shared',
|
|
'-lstdc++',
|
|
'-Os',
|
|
'-I./src',
|
|
repo.files
|
|
}),
|
|
cwd = compile_location
|
|
}
|
|
},
|
|
{
|
|
cmd = 'mv',
|
|
opts = {
|
|
args = { compile_location..'/parser.so', parser_lib_name }
|
|
}
|
|
},
|
|
{
|
|
cmd = 'rm',
|
|
opts = {
|
|
args = { '-rf', project_repo }
|
|
}
|
|
}
|
|
}
|
|
|
|
iter_cmd(command_list, 0, ft)
|
|
end
|
|
|
|
-- TODO(kyazdani): this should work on windows too
|
|
function M.install_parser(ft)
|
|
if fn.has('win32') == 1 then
|
|
return api.nvim_err_writeln('This command is not available on windows at the moment.')
|
|
end
|
|
|
|
if not ft then
|
|
return api.nvim_err_writeln("Usage: install_parser('language')")
|
|
end
|
|
|
|
if #api.nvim_get_runtime_file('parser/'..ft..'.so', false) > 0 then
|
|
local yesno = fn.input('Parser already available: would you like to reinstall ? y/n: ')
|
|
print('\n ') -- mandatory to avoid messing up command line
|
|
if not string.match(yesno, '^y.*') then return end
|
|
end
|
|
|
|
local repository = M.repositories[ft]
|
|
if not repository then
|
|
return api.nvim_err_writeln('Parser not available for language '..ft)
|
|
end
|
|
|
|
if fn.executable('git') == 0 then
|
|
return api.nvim_err_writeln('Git is required on your system to run this command')
|
|
end
|
|
|
|
local package_path, err = get_package_path()
|
|
if err then return api.nvim_err_writeln(err) end
|
|
|
|
local cache_folder, err = get_cache_dir()
|
|
if err then return api.nvim_err_writeln(err) end
|
|
|
|
run_install(cache_folder, package_path, ft, repository)
|
|
end
|
|
|
|
function M.checkhealth()
|
|
local health_ok = vim.fn['health#report_ok']
|
|
local health_info = vim.fn['health#report_info']
|
|
local health_warn = vim.fn['health#report_warn']
|
|
local health_error = vim.fn['health#report_error']
|
|
|
|
if fn.executable('git') == 0 then
|
|
health_error('`git` executable not found.', {
|
|
'Install it with your package manager.',
|
|
'Check that your `$PATH` is set correctly.'
|
|
})
|
|
else
|
|
health_ok('`git` executable found.')
|
|
end
|
|
|
|
if fn.executable('cc') == 0 then
|
|
health_error('`cc` executable not found.', {
|
|
'Install `gcc` with your package manager.',
|
|
'Install `clang` with your package manager.',
|
|
'Check that your `$PATH` is set correctly.'
|
|
})
|
|
else
|
|
health_ok('`cc` executable found.')
|
|
end
|
|
end
|
|
|
|
function M.list_parsers()
|
|
local max_len = 0
|
|
for parser_name, _ in pairs(repositories) do
|
|
if #parser_name > max_len then max_len = #parser_name end
|
|
end
|
|
|
|
for parser_name, _ in pairs(repositories) do
|
|
local is_installed = #api.nvim_get_runtime_file('parser/'..parser_name..'.so', false) > 0
|
|
api.nvim_out_write(parser_name..string.rep(' ', max_len - #parser_name + 1))
|
|
if is_installed then
|
|
api.nvim_out_write("[✓] installed\n")
|
|
else
|
|
api.nvim_out_write("[✗] not installed\n")
|
|
end
|
|
end
|
|
end
|
|
|
|
return M
|