diff options
| author | Florian Beeres <yuuki@protonmail.com> | 2020-09-18 09:44:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-18 09:44:07 +0200 |
| commit | 18adc9e17661c6ff690598e3f6e0f34708353dd3 (patch) | |
| tree | 30a376555f4e324aafc9072f81f4803af889beab /lua | |
| parent | Update CONTRIBUTING.md (diff) | |
| download | nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar.gz nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar.bz2 nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar.lz nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar.xz nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.tar.zst nvim-treesitter-18adc9e17661c6ff690598e3f6e0f34708353dd3.zip | |
Make :TSInstall work in Nix by adding a second module installation target (#473)
* Ignore tags file in project root
* Make :TSInstall work with Nix
This commit adds logic to determine where to install parsers, meaning
the *.so files. Until now the package path of the nvim-treesitter plugin
was used. But when installed with Nix, the plugin lands in "/nix/store",
which is read-only.
With this commit $XDG_DATA_HOME/nvim/site/parser/*.go will be used as
the parser installation path. The directory will be created if it
doesn't exist.
* Add generate_join function
The generate_join function is used to create two other functions, one
to join path segments, the other to join strings with a space for error
messages.
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/nvim-treesitter/install.lua | 25 | ||||
| -rw-r--r-- | lua/nvim-treesitter/utils.lua | 66 |
2 files changed, 78 insertions, 13 deletions
diff --git a/lua/nvim-treesitter/install.lua b/lua/nvim-treesitter/install.lua index 0d2d74817..4c52fd412 100644 --- a/lua/nvim-treesitter/install.lua +++ b/lua/nvim-treesitter/install.lua @@ -117,18 +117,15 @@ local function select_mv_cmd(compile_location, parser_lib_name) end end -local function run_install(cache_folder, package_path, lang, repo, with_sync) +local function run_install(cache_folder, install_folder, lang, repo, with_sync) parsers.reset_cache() - local path_sep = '/' - if fn.has('win32') == 1 then - path_sep = '\\' - end + local path_sep = utils.get_path_sep() local project_name = 'tree-sitter-'..lang -- compile_location only needed for typescript installs. local compile_location = cache_folder..path_sep..(repo.location or project_name) - local parser_lib_name = package_path..path_sep.."parser"..path_sep..lang..".so" + local parser_lib_name = install_folder..path_sep..lang..".so" local compilers = { "cc", "gcc", "clang" } local cc = select_executable(compilers) @@ -170,7 +167,7 @@ local function run_install(cache_folder, package_path, lang, repo, with_sync) end end -local function install_lang(lang, ask_reinstall, cache_folder, package_path, with_sync) +local function install_lang(lang, ask_reinstall, cache_folder, install_folder, with_sync) if #api.nvim_get_runtime_file('parser/'..lang..'.so', false) > 0 then if ask_reinstall ~= 'force' then if not ask_reinstall then return end @@ -192,7 +189,7 @@ local function install_lang(lang, ask_reinstall, cache_folder, package_path, wit files={ install_info.files, 'table' } } - run_install(cache_folder, package_path, lang, install_info, with_sync) + run_install(cache_folder, install_folder, lang, install_info, with_sync) end local function install(with_sync, ask_reinstall) @@ -202,10 +199,12 @@ local function install(with_sync, ask_reinstall) return api.nvim_err_writeln('Git is required on your system to run this command') end - local package_path = utils.get_package_path() local cache_folder, err = utils.get_cache_dir() if err then return api.nvim_err_writeln(err) end + local install_folder, err = utils.get_parser_install_dir() + if err then return api.nvim_err_writeln(err) end + local languages local ask if ... == 'all' then @@ -217,7 +216,7 @@ local function install(with_sync, ask_reinstall) end for _, lang in ipairs(languages) do - install_lang(lang, ask, cache_folder, package_path, with_sync) + install_lang(lang, ask, cache_folder, install_folder, with_sync) end end end @@ -267,8 +266,10 @@ function M.uninstall(lang) M.uninstall(lang) end elseif lang then - local package_path = utils.get_package_path() - local parser_lib = package_path..path_sep.."parser"..path_sep..lang..".so" + local install_dir, err = utils.get_parser_install_dir() + if err then return api.nvim_err_writeln(err) end + + local parser_lib = install_dir..path_sep..lang..".so" local command_list = { select_uninstall_rm_cmd(lang, parser_lib) diff --git a/lua/nvim-treesitter/utils.lua b/lua/nvim-treesitter/utils.lua index 7a5fbe5e9..24813bc96 100644 --- a/lua/nvim-treesitter/utils.lua +++ b/lua/nvim-treesitter/utils.lua @@ -17,6 +17,26 @@ function M.setup_commands(mod, commands) end end +function M.get_path_sep() + return fn.has('win32') == 1 and '\\' or '/' +end + +-- Returns a function that joins the given arguments with separator. Arguments +-- can't be nil. Example: +--[[ +print(M.generate_join(" ")("foo", "bar")) +--]] +-- prints "foo bar" +function M.generate_join(separator) + return function (...) + return table.concat({...}, separator) + end +end + +local join_path = M.generate_join(M.get_path_sep()) + +local join_space = M.generate_join(" ") + function M.get_package_path() -- Path to this source file, removing the leading '@' local source = string.sub(debug.getinfo(1, 'S').source, 2) @@ -34,7 +54,51 @@ function M.get_cache_dir() return '/tmp' end - return nil, 'Invalid cache rights, '..fn.stdpath('data')..' or /tmp should be read/write' + return nil, join_space('Invalid cache rights,', fn.stdpath('data'), 'or /tmp should be read/write') +end + +-- Returns $XDG_DATA_HOME/nvim/site, but could use any directory that is in +-- runtimepath +function M.get_site_dir() + local path_sep = M.get_path_sep() + return join_path(fn.stdpath('data'), path_sep, 'site') +end + +-- Try the package dir of the nvim-treesitter plugin first, followed by the +-- "site" dir from "runtimepath". "site" dir will be created if it doesn't +-- exist. Using only the package dir won't work when the plugin is installed +-- with Nix, since the "/nix/store" is read-only. +function M.get_parser_install_dir() + local package_path = M.get_package_path() + local package_path_parser_dir = join_path(package_path, "parser") + + -- If package_path is read/write, use that + if luv.fs_access(package_path_parser_dir, 'RW') then + return package_path_parser_dir + end + + local site_dir = M.get_site_dir() + local path_sep = M.get_path_sep() + local parser_dir = join_path(site_dir, path_sep, 'parser') + + -- Try creating and using parser_dir if it doesn't exist + if not luv.fs_stat(parser_dir) then + local ok, error = pcall(vim.fn.mkdir, parser_dir, "p", "0755") + if not ok then + return nil, join_space('Couldn\'t create parser dir', parser_dir, ':', error) + end + + return parser_dir + end + + -- parser_dir exists, use it if it's read/write + if luv.fs_access(parser_dir, 'RW') then + return parser_dir + end + + -- package_path isn't read/write, parser_dir exists but isn't read/write + -- either, give up + return nil, join_space('Invalid cache rights,', package_path, 'or', parser_dir, 'should be read/write') end -- Gets a property at path |
