diff options
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/nvim-lsp-installer/installers/context.lua | 76 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/installers/init.lua | 4 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/servers/ccls/init.lua | 89 |
3 files changed, 137 insertions, 32 deletions
diff --git a/lua/nvim-lsp-installer/installers/context.lua b/lua/nvim-lsp-installer/installers/context.lua index 85d3f2a2..919e3957 100644 --- a/lua/nvim-lsp-installer/installers/context.lua +++ b/lua/nvim-lsp-installer/installers/context.lua @@ -169,7 +169,7 @@ end ---Creates an installer that moves the current installation directory to the server's root directory. function M.promote_install_dir() ---@type ServerInstallerFunction - return function(server, callback, context) + return vim.schedule_wrap(function(server, callback, context) if server:promote_install_dir(context.install_dir) then context.install_dir = server.root_dir callback(true) @@ -179,7 +179,7 @@ function M.promote_install_dir() ) callback(false) end - end + end) end ---Access the context ojbect to create a new installer. @@ -225,4 +225,76 @@ function M.set_working_dir(rel_path) end) end +function M.use_os_distribution() + ---Parses the provided contents of an /etc/\*-release file and identifies the Linux distribution. + ---@param contents string @The contents of a /etc/\*-release file. + ---@return table<string, any> + local function parse_linux_dist(contents) + local lines = vim.split(contents, "\n") + + local entries = {} + + for i = 1, #lines do + local line = lines[i] + local index = line:find "=" + if index then + local key = line:sub(1, index - 1) + local value = line:sub(index + 1) + entries[key] = value + end + end + + if entries.ID == "ubuntu" then + -- Parses the Ubuntu OS VERSION_ID into their version components, e.g. "18.04" -> {major=18, minor=04} + local version_id = entries.VERSION_ID:gsub([["]], "") + local version_parts = vim.split(version_id, "%.") + local major = tonumber(version_parts[1]) + local minor = tonumber(version_parts[2]) + + return { + id = "ubuntu", + version_id = version_id, + version = { major = major, minor = minor }, + } + else + return { + id = "linux-generic", + } + end + end + + return installers.when { + ---@type ServerInstallerFunction + linux = function(_, callback, ctx) + local stdio = process.in_memory_sink() + process.spawn("bash", { + args = { "-c", "cat /etc/*-release" }, + stdio_sink = stdio.sink, + }, function(success) + if success then + ctx.os_distribution = parse_linux_dist(table.concat(stdio.buffers.stdout, "")) + callback(true) + else + ctx.os_distribution = { + id = "linux-generic", + } + callback(true) + end + end) + end, + mac = function(_, callback, ctx) + ctx.os_distribution = { + id = "macOS", + } + callback(true) + end, + win = function(_, callback, ctx) + ctx.os_distribution = { + id = "windows", + } + callback(true) + end, + } +end + return M diff --git a/lua/nvim-lsp-installer/installers/init.lua b/lua/nvim-lsp-installer/installers/init.lua index 25d97658..c4ac2747 100644 --- a/lua/nvim-lsp-installer/installers/init.lua +++ b/lua/nvim-lsp-installer/installers/init.lua @@ -1,9 +1,6 @@ local platform = require "nvim-lsp-installer.platform" local log = require "nvim-lsp-installer.log" local Data = require "nvim-lsp-installer.data" -local process = require "nvim-lsp-installer.process" -local fs = require "nvim-lsp-installer.fs" -local path = require "nvim-lsp-installer.path" local M = {} @@ -23,6 +20,7 @@ end ---@field requested_server_version string|nil @The version requested by the user. ---@field stdio_sink StdioSink ---@field github_release_file string|nil @Only available if context.use_github_release_file has been called. +---@field os_distribution table<string, any> @Only available if context.use_os_distribution has been called. ---@field install_dir string ---@alias ServerInstallerFunction fun(server: Server, callback: ServerInstallCallback, context: ServerInstallContext) diff --git a/lua/nvim-lsp-installer/servers/ccls/init.lua b/lua/nvim-lsp-installer/servers/ccls/init.lua index f8545c38..079c9cd2 100644 --- a/lua/nvim-lsp-installer/servers/ccls/init.lua +++ b/lua/nvim-lsp-installer/servers/ccls/init.lua @@ -14,15 +14,32 @@ return function(name, root_dir) do ---@param version string + ---@param os_distribution table<string, string>|nil ---@return string|nil - local function get_archive_name(version) + local function get_archive_name(version, os_distribution) local name_template = coalesce( when(platform.is_mac, "clang+llvm-%s-x86_64-apple-darwin"), when( platform.is_linux, coalesce( - when(platform.arch == "x64", "clang+llvm-%s-amd64-unknown-freebsd13"), - when(platform.arch == "arm64", "clang+llvm-%s-aarch64-linux-gnu") + when( + platform.arch == "x64", + coalesce( + when( + os_distribution.id == "ubuntu" and os_distribution.version.major >= 20, + "clang+llvm-%s-x86_64-linux-gnu-ubuntu-20.04" + ), + when( + os_distribution.id == "ubuntu" and os_distribution.version.major >= 16, + "clang+llvm-%s-x86_64-linux-gnu-ubuntu-16.04" + ), + -- the Ubuntu dist is allegedly the most suitable cross-platform one, so we default to it + "clang+llvm-%s-x86_64-linux-gnu-ubuntu-16.04" + ) + ), + when(platform.arch == "arm64", "clang+llvm-%s-aarch64-linux-gnu"), + when(platform.arch == "armv7", "clang+llvm-%s-armv7a-linux-gnueabihf"), + when(platform.arch == "x86", "clang+llvm-%s-i386-unknown-freebsd13") ) ) ) @@ -31,7 +48,8 @@ return function(name, root_dir) ---@param version string local function normalize_version(version) - return version:gsub("^llvmorg%-", "") + local s = version:gsub("^llvmorg%-", "") + return s end llvm_installer = installers.branch_context { @@ -39,15 +57,24 @@ return function(name, root_dir) -- We unset the requested version for llvm because it's not the primary target - the user's requested version should only apply to ccls. ctx.requested_server_version = nil end), - context.use_github_release_file("llvm/llvm-project", function(version) - -- Strip the "llvmorg-" prefix from tags (llvm releases tags like llvmorg-13.0.0) - local archive_name = get_archive_name(normalize_version(version)) - return archive_name and ("%s.tar.xz"):format(archive_name) + context.capture(function(ctx) + return context.use_github_release_file("llvm/llvm-project", function(version) + -- Strip the "llvmorg-" prefix from tags (llvm releases tags like llvmorg-13.0.0) + local archive_name = get_archive_name(normalize_version(version), ctx.os_distribution) + return archive_name and ("%s.tar.xz"):format(archive_name) + end) end), context.capture(function(ctx) return installers.pipe { std.untarxz_remote(ctx.github_release_file), - std.rename(get_archive_name(normalize_version(ctx.requested_server_version)), "llvm"), + std.rename( + get_archive_name(normalize_version(ctx.requested_server_version), ctx.os_distribution), + "llvm" + ), + std.rename( + path.concat { "llvm", "lib", "clang", normalize_version(ctx.requested_server_version) }, + "clang-resource" + ), } end), } @@ -56,25 +83,30 @@ return function(name, root_dir) local ccls_installer = installers.branch_context { context.set(function(ctx) ctx.llvm_install_dir = path.concat { ctx.install_dir, "llvm" } + ctx.clang_resource_dir = path.concat { ctx.install_dir, "clang-resource" } end), - context.set_working_dir "ccls", - std.git_clone "https://github.com/MaskRay/ccls", - std.git_submodule_update(), - function(_, callback, ctx) - local c = process.chain { - cwd = ctx.install_dir, - stdio_sink = ctx.stdio_sink, - } + installers.branch_context { + context.set_working_dir "ccls-git", + std.git_clone "https://github.com/MaskRay/ccls", + std.git_submodule_update(), + function(_, callback, ctx) + local c = process.chain { + cwd = ctx.install_dir, + stdio_sink = ctx.stdio_sink, + } - c.run("cmake", { - "-H.", - "-BRelease", - "-DCMAKE_BUILD_TYPE=Release", - ("-DCMAKE_PREFIX_PATH=%s"):format(path.concat { ctx.llvm_install_dir, "lib", "cmake" }), - }) - c.run("cmake", { "--build", "Release" }) - c.spawn(callback) - end, + c.run("cmake", { + "-H.", + "-BRelease", + "-DCMAKE_BUILD_TYPE=Release", + ("-DCMAKE_PREFIX_PATH=%s"):format(ctx.llvm_install_dir), + ("-DCLANG_RESOURCE_DIR=%s"):format(ctx.clang_resource_dir), + }) + c.run("cmake", { "--build", "Release" }) + c.spawn(callback) + end, + }, + std.rename(path.concat { "ccls-git", "Release", "ccls" }, "ccls"), } return server.Server:new { @@ -84,13 +116,16 @@ return function(name, root_dir) languages = { "c", "c++", "objective-c" }, installer = installers.when { unix = { + context.use_os_distribution(), context.promote_install_dir(), -- ccls hardcodes the path to llvm at compile time, so we need to compile everything in the final directory llvm_installer, ccls_installer, + std.rmrf "llvm", + std.rmrf "ccls-git", }, }, default_options = { - cmd = { path.concat { root_dir, "ccls", "Release", "ccls" } }, + cmd = { path.concat { root_dir, "ccls" } }, }, } end |
