aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua')
-rw-r--r--lua/nvim-lsp-installer/installers/context.lua76
-rw-r--r--lua/nvim-lsp-installer/installers/init.lua4
-rw-r--r--lua/nvim-lsp-installer/servers/ccls/init.lua89
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