mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-06 13:30:01 -04:00
feat/refacto: improve installer
This commit is contained in:
parent
2967ca5203
commit
ec9daa1f8a
1 changed files with 103 additions and 39 deletions
|
|
@ -1,74 +1,138 @@
|
||||||
local api = vim.api
|
local api = vim.api
|
||||||
local fn = vim.fn
|
local fn = vim.fn
|
||||||
|
local luv = vim.loop
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
local package_path = nil
|
|
||||||
local repositories = {
|
local repositories = {
|
||||||
javascript = {
|
javascript = {
|
||||||
url = "https://github.com/tree-sitter/tree-sitter-javascript",
|
url = "https://github.com/tree-sitter/tree-sitter-javascript",
|
||||||
files = "src/parser.c src/scanner.c",
|
files = { "src/parser.c", "src/scanner.c" },
|
||||||
},
|
},
|
||||||
c = {
|
c = {
|
||||||
url = "https://github.com/tree-sitter/tree-sitter-c",
|
url = "https://github.com/tree-sitter/tree-sitter-c",
|
||||||
files = "src/parser.c"
|
files = { "src/parser.c" }
|
||||||
|
},
|
||||||
|
rust = {
|
||||||
|
url = "https://github.com/tree-sitter/tree-sitter-rust",
|
||||||
|
files = { "src/parser.c", "src/scanner.c" },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- TODO(kyazdani): there might be a better way to get the plugin path
|
local function get_package_path()
|
||||||
for _, path in pairs(api.nvim_list_runtime_paths()) do
|
for _, path in pairs(api.nvim_list_runtime_paths()) do
|
||||||
if string.match(path, '.*/nvim%-treesitter') then
|
if string.match(path, '.*/nvim%-treesitter') then
|
||||||
package_path = path
|
return path
|
||||||
break
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return nil, 'Plugin runtime path not found.'
|
||||||
end
|
end
|
||||||
|
|
||||||
local function create_compile_command(ft, path, files)
|
local function get_cache_dir()
|
||||||
-- TODO(kyazdani): should download the parser in $XDG_CACHE_HOME instead of /tmp
|
local home = fn.get(fn.environ(), 'HOME')
|
||||||
return "cd /tmp/tree-sitter-"..ft..[[ && \
|
local xdg_cache = fn.get(fn.environ(), 'XDG_CACHE_HOME')
|
||||||
gcc -o parser.so -shared ]]..files..[[ -Os -I./src && \
|
|
||||||
mv parser.so ]]..path.."/parsers/"..ft..[[.so && \
|
if xdg_cache == 0 then
|
||||||
rm -rf /tmp/tree-sitter-]]..ft
|
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
|
end
|
||||||
|
|
||||||
local function create_download_command(url)
|
local function iter_cmd(cmd_list, i, ft)
|
||||||
return "cd /tmp && git clone "..url
|
if i == #cmd_list then return print('Treesitter parser for '..ft..' has been installed') end
|
||||||
|
local attr = cmd_list[i + 1]
|
||||||
|
print(attr.info)
|
||||||
|
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
|
end
|
||||||
|
|
||||||
function M.install_parser(lang)
|
local function run_install(cache_folder, package_path, ft, files, url)
|
||||||
|
local project_repo = cache_folder..'/tree-sitter-'..ft
|
||||||
|
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', url },
|
||||||
|
cwd = cache_folder,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd = 'cc',
|
||||||
|
info = 'Compiling...',
|
||||||
|
err = 'Error during compilation',
|
||||||
|
opts = {
|
||||||
|
args = { '-o', 'parser.so', '-shared', '-lstdc++', unpack(files), '-Os', '-I./src' },
|
||||||
|
cwd = project_repo
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd = 'mv',
|
||||||
|
opts = {
|
||||||
|
args = { project_repo..'/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
|
if fn.has('win32') == 1 then
|
||||||
-- TODO(kyazdani): this should work on windows too
|
return api.nvim_err_writeln('This command is not available on windows at the moment.')
|
||||||
api.nvim_err_writeln('This command is not available on windows at the moment.')
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not lang then
|
if not ft then
|
||||||
api.nvim_err_writeln("usage: install_parser('language')")
|
return api.nvim_err_writeln("Usage: install_parser('language')")
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local repository = repositories[lang]
|
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 = repositories[ft]
|
||||||
if not repository then
|
if not repository then
|
||||||
api.nvim_err_writeln('Parser not available for language '..lang)
|
return api.nvim_err_writeln('Parser not available for language '..ft)
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not package_path then
|
if fn.executable('git') == 0 then
|
||||||
api.nvim_err_writeln('Plugin runtime path not found.')
|
return api.nvim_err_writeln('Git is required on your system to run this command')
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not fn.executable('git') == 1 then
|
local package_path, err = get_package_path()
|
||||||
api.nvim_err_writeln('Please install `git` to download parsers.')
|
if err then return api.nvim_err_writeln(err) end
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Downloading parser...")
|
local cache_folder, err = get_cache_dir()
|
||||||
fn.system(create_download_command(repository.url))
|
if err then return api.nvim_err_writeln(err) end
|
||||||
|
|
||||||
print("Compiling parser...")
|
run_install(cache_folder, package_path, ft, repository.files, repository.url)
|
||||||
fn.system(create_compile_command(lang, package_path, repository.files))
|
|
||||||
|
|
||||||
print("Install for the " ..lang.." parser was successfull")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue