diff options
| author | William Boman <william@redwill.se> | 2021-09-29 13:48:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-09-29 13:48:39 +0200 |
| commit | e267fe517feaaf7a48323349e3775944db49c158 (patch) | |
| tree | 1c9d869d71c32b0d3b2f9304d9433dbb4ced9903 /lua | |
| parent | fix stylua (#104) (diff) | |
| download | mason-e267fe517feaaf7a48323349e3775944db49c158.tar mason-e267fe517feaaf7a48323349e3775944db49c158.tar.gz mason-e267fe517feaaf7a48323349e3775944db49c158.tar.bz2 mason-e267fe517feaaf7a48323349e3775944db49c158.tar.lz mason-e267fe517feaaf7a48323349e3775944db49c158.tar.xz mason-e267fe517feaaf7a48323349e3775944db49c158.tar.zst mason-e267fe517feaaf7a48323349e3775944db49c158.zip | |
support installing specific version of language servers, defaults to latest (#106)
Diffstat (limited to 'lua')
35 files changed, 430 insertions, 172 deletions
diff --git a/lua/nvim-lsp-installer.lua b/lua/nvim-lsp-installer.lua index d5eb66b2..58b909dd 100644 --- a/lua/nvim-lsp-installer.lua +++ b/lua/nvim-lsp-installer.lua @@ -10,12 +10,13 @@ function M.display() status_win().open() end -function M.install(server_name) +function M.install(server_tuple) + local server_name, version = unpack(servers.parse_server_tuple(server_tuple)) local ok, server = servers.get_server(server_name) if not ok then return notify(("Unable to find LSP server %s.\n\n%s"):format(server_name, server), vim.log.levels.ERROR) end - status_win().install_server(server) + status_win().install_server(server, version) status_win().open() end diff --git a/lua/nvim-lsp-installer/data.lua b/lua/nvim-lsp-installer/data.lua index 53bca81e..da5694ce 100644 --- a/lua/nvim-lsp-installer/data.lua +++ b/lua/nvim-lsp-installer/data.lua @@ -51,4 +51,16 @@ function Data.coalesce(...) end end +function Data.list_copy(list) + local result = {} + for i = 1, #list do + result[#result + 1] = list[i] + end + return result +end + +function Data.json_decode(data) + return vim.fn.json_decode(data) +end + return Data diff --git a/lua/nvim-lsp-installer/installers/context.lua b/lua/nvim-lsp-installer/installers/context.lua new file mode 100644 index 00000000..057c3620 --- /dev/null +++ b/lua/nvim-lsp-installer/installers/context.lua @@ -0,0 +1,89 @@ +local Data = require "nvim-lsp-installer.data" +local Log = require "nvim-lsp-installer.log" +local process = require "nvim-lsp-installer.process" +local platform = require "nvim-lsp-installer.platform" + +local M = {} + +local function fetch(url, callback) + local stdio = process.in_memory_sink() + if platform.is_unix then + process.spawn("wget", { + args = { "-nv", "-O", "-", url }, + stdio_sink = stdio.sink, + }, function(success) + if success then + callback(nil, table.concat(stdio.buffers.stdout, "")) + else + callback(("Failed to fetch url=%s"):format(url), nil) + end + end) + elseif platform.is_win then + local script = { + "$ProgressPreference = 'SilentlyContinue'", + ("Write-Output (iwr -Uri %q).Content"):format(url), + } + process.spawn("powershell.exe", { + args = { "-Command", table.concat(script, ";") }, + stdio_sink = stdio.sink, + }, function(success) + if success then + callback(nil, table.concat(stdio.buffers.stdout, "")) + else + callback(("Failed to fetch url=%s"):format(url), nil) + end + end) + else + error "Unexpected error: Unsupported OS." + end +end + +function M.github_release_file(repo, file) + local function get_download_url(version) + return ("https://github.com/%s/releases/download/%s/%s"):format( + repo, + version, + type(file) == "function" and file(version) or file + ) + end + + return function(server, callback, context) + if context.requested_server_version then + context.github_release_file = get_download_url(context.requested_server_version) + callback(true) + else + context.stdio_sink.stdout "Fetching latest release version from GitHub API..." + fetch( + ("https://api.github.com/repos/%s/releases/latest"):format(repo), + vim.schedule_wrap(function(err, response) + if err then + context.stdio_sink.stderr "Failed to fetch latest release version from GitHub API." + return callback(false) + else + local version = Data.json_decode(response).tag_name + Log.debug("Resolved latest version", server.name, version) + context.requested_server_version = version + context.github_release_file = get_download_url(version) + callback(true) + end + end) + ) + end + end +end + +function M.capture(fn) + return function(server, callback, context, ...) + local installer = fn(context) + installer(server, callback, context, ...) + end +end + +function M.set(fn) + return function(_, callback, context) + fn(context) + callback(true) + end +end + +return M diff --git a/lua/nvim-lsp-installer/installers/gem.lua b/lua/nvim-lsp-installer/installers/gem.lua index 17f53620..091cda27 100644 --- a/lua/nvim-lsp-installer/installers/gem.lua +++ b/lua/nvim-lsp-installer/installers/gem.lua @@ -1,4 +1,5 @@ local path = require "nvim-lsp-installer.path" +local Data = require "nvim-lsp-installer.data" local process = require "nvim-lsp-installer.process" local installers = require "nvim-lsp-installer.installers" local std = require "nvim-lsp-installer.installers.std" @@ -15,6 +16,12 @@ function M.packages(packages) { "gem", "gem was not found in path, refer to https://wiki.openstack.org/wiki/RubyGems." }, }, function(server, callback, context) + local pkgs = Data.list_copy(packages or {}) + if context.requested_server_version then + -- The "head" package is the recipient for the requested version. It's.. by design... don't ask. + pkgs[1] = ("%s:%s"):format(pkgs[1], context.requested_server_version) + end + process.spawn(gem, { args = { "install", @@ -22,7 +29,7 @@ function M.packages(packages) "--install-dir=.", "--bindir=bin", "--no-document", - table.concat(packages, " "), + table.concat(pkgs, " "), }, cwd = server.root_dir, stdio_sink = context.stdio_sink, diff --git a/lua/nvim-lsp-installer/installers/go.lua b/lua/nvim-lsp-installer/installers/go.lua index aa2eeaba..005ce842 100644 --- a/lua/nvim-lsp-installer/installers/go.lua +++ b/lua/nvim-lsp-installer/installers/go.lua @@ -1,6 +1,7 @@ local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" local installers = require "nvim-lsp-installer.installers" +local Data = require "nvim-lsp-installer.data" local process = require "nvim-lsp-installer.process" local M = {} @@ -9,6 +10,7 @@ function M.packages(packages) return installers.pipe { std.ensure_executables { { "go", "go was not found in path, refer to https://golang.org/doc/install." } }, function(server, callback, context) + local pkgs = Data.list_copy(packages or {}) local c = process.chain { env = process.graft_env { GO111MODULE = "on", @@ -19,7 +21,12 @@ function M.packages(packages) stdio_sink = context.stdio_sink, } - c.run("go", vim.list_extend({ "get", "-v" }, packages)) + if context.requested_server_version then + -- The "head" package is the recipient for the requested version. It's.. by design... don't ask. + pkgs[1] = ("%s@%s"):format(pkgs[1], context.requested_server_version) + end + + c.run("go", vim.list_extend({ "get", "-v" }, pkgs)) c.run("go", { "clean", "-modcache" }) c.spawn(callback) diff --git a/lua/nvim-lsp-installer/installers/npm.lua b/lua/nvim-lsp-installer/installers/npm.lua index e6923520..88e8fafc 100644 --- a/lua/nvim-lsp-installer/installers/npm.lua +++ b/lua/nvim-lsp-installer/installers/npm.lua @@ -1,5 +1,6 @@ local path = require "nvim-lsp-installer.path" local fs = require "nvim-lsp-installer.fs" +local Data = require "nvim-lsp-installer.data" local installers = require "nvim-lsp-installer.installers" local std = require "nvim-lsp-installer.installers.std" local platform = require "nvim-lsp-installer.platform" @@ -24,6 +25,7 @@ end function M.packages(packages) return ensure_npm(function(server, callback, context) + local pkgs = Data.list_copy(packages or {}) local c = process.chain { cwd = server.root_dir, stdio_sink = context.stdio_sink, @@ -34,8 +36,14 @@ function M.packages(packages) then c.run(npm, { "init", "--yes", "--scope=lsp-installer" }) end + + if context.requested_server_version and #pkgs > 0 then + -- The "head" package is the recipient for the requested version. It's.. by design... don't ask. + pkgs[1] = ("%s@%s"):format(pkgs[1], context.requested_server_version) + end + -- stylua: ignore end - c.run(npm, vim.list_extend({ "install" }, packages)) + c.run(npm, vim.list_extend({ "install" }, pkgs)) c.spawn(callback) end) end diff --git a/lua/nvim-lsp-installer/installers/pip3.lua b/lua/nvim-lsp-installer/installers/pip3.lua index cb0af84b..084f102f 100644 --- a/lua/nvim-lsp-installer/installers/pip3.lua +++ b/lua/nvim-lsp-installer/installers/pip3.lua @@ -1,4 +1,5 @@ local path = require "nvim-lsp-installer.path" +local Data = require "nvim-lsp-installer.data" local installers = require "nvim-lsp-installer.installers" local std = require "nvim-lsp-installer.installers.std" local platform = require "nvim-lsp-installer.platform" @@ -15,13 +16,18 @@ function M.packages(packages) { "pip3", "pip3 was not found in path." }, }, function(server, callback, context) + local pkgs = Data.list_copy(packages or {}) local c = process.chain { cwd = server.root_dir, stdio_sink = context.stdio_sink, } c.run("python3", { "-m", "venv", REL_INSTALL_DIR }) - c.run(M.executable(server.root_dir, "pip3"), vim.list_extend({ "install", "-U" }, packages)) + if context.requested_server_version then + -- The "head" package is the recipient for the requested version. It's.. by design... don't ask. + pkgs[1] = ("%s==%s"):format(pkgs[1], context.requested_server_version) + end + c.run(M.executable(server.root_dir, "pip3"), vim.list_extend({ "install", "-U" }, pkgs)) c.spawn(callback) end, diff --git a/lua/nvim-lsp-installer/installers/std.lua b/lua/nvim-lsp-installer/installers/std.lua index f65992df..08bed2f2 100644 --- a/lua/nvim-lsp-installer/installers/std.lua +++ b/lua/nvim-lsp-installer/installers/std.lua @@ -97,11 +97,19 @@ end function M.git_clone(repo_url) return function(server, callback, context) - process.spawn("git", { - args = { "clone", "--depth", "1", repo_url, "." }, + local c = process.chain { cwd = server.root_dir, stdio_sink = context.stdio_sink, - }, callback) + } + + c.run("git", { "clone", "--depth", "1", repo_url, "." }) + + if context.requested_server_version then + c.run("git", { "fetch", "--depth", "1", "origin", context.requested_server_version }) + c.run("git", { "checkout", "FETCH_HEAD" }) + end + + c.spawn(callback) end end diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua index 5b4bc22a..31523a05 100644 --- a/lua/nvim-lsp-installer/process.lua +++ b/lua/nvim-lsp-installer/process.lua @@ -1,4 +1,4 @@ -local log = require "nvim-lsp-installer.log" +local Log = require "nvim-lsp-installer.log" local platform = require "nvim-lsp-installer.platform" local uv = vim.loop @@ -7,13 +7,10 @@ local M = {} local function connect_sink(pipe, sink) return function(err, data) if err then - -- log.error { "Unexpected error when reading pipe.", err } + Log.error("Unexpected error when reading pipe.", err) end if data ~= nil then - local lines = vim.split(data, "\n") - for i = 1, #lines do - sink(lines[i]) - end + sink(data) else pipe:read_stop() pipe:close() @@ -51,7 +48,7 @@ function M.spawn(cmd, opts, callback) local stdio = { stdin, stdout, stderr } - -- log.debug { "Spawning", cmd, opts } + Log.debug("Spawning", cmd, opts) local spawn_opts = { env = opts.env, @@ -85,12 +82,13 @@ function M.spawn(cmd, opts, callback) end) if handle == nil then + Log.error("Failed to spawn process", cmd, pid) opts.stdio_sink.stderr(("Failed to spawn process cmd=%s pid=%s"):format(cmd, pid)) callback(false) return nil, nil end - -- log.debug { "Spawned with pid", pid } + Log.debug("Spawned with pid", pid) stdout:read_start(connect_sink(stdout, opts.stdio_sink.stdout)) stderr:read_start(connect_sink(stderr, opts.stdio_sink.stderr)) @@ -144,6 +142,21 @@ function M.simple_sink() } end +function M.in_memory_sink() + local buffers = { stdout = {}, stderr = {} } + return { + buffers = buffers, + sink = { + stdout = function(chunk) + buffers.stdout[#buffers.stdout + 1] = chunk + end, + stderr = function(chunk) + buffers.stderr[#buffers.stderr + 1] = chunk + end, + }, + } +end + -- this prob belongs elsewhere ¯\_(ツ)_/¯ function M.debounced(debounced_fn) local queued = false @@ -157,6 +170,7 @@ function M.debounced(debounced_fn) vim.schedule(function() debounced_fn(last_arg) queued = false + last_arg = nil end) end end diff --git a/lua/nvim-lsp-installer/server.lua b/lua/nvim-lsp-installer/server.lua index 93102054..a6299136 100644 --- a/lua/nvim-lsp-installer/server.lua +++ b/lua/nvim-lsp-installer/server.lua @@ -78,7 +78,7 @@ function M.Server:install() status_win().install_server(self) end -function M.Server:install_attached(opts, callback) +function M.Server:install_attached(context, callback) self:uninstall() self:create_root_dir() local install_ok, install_err = pcall(self._installer, self, function(success) @@ -92,9 +92,9 @@ function M.Server:install_attached(opts, callback) end) end callback(success) - end, opts) + end, context) if not install_ok then - opts.stdio_sink.stderr(tostring(install_err)) + context.stdio_sink.stderr(tostring(install_err)) callback(false) end end diff --git a/lua/nvim-lsp-installer/servers/bashls/init.lua b/lua/nvim-lsp-installer/servers/bashls/init.lua index 59a7819e..7839131e 100644 --- a/lua/nvim-lsp-installer/servers/bashls/init.lua +++ b/lua/nvim-lsp-installer/servers/bashls/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "bash-language-server@latest" }, + installer = npm.packages { "bash-language-server" }, default_options = { cmd = { npm.executable(root_dir, "bash-language-server"), "start" }, }, diff --git a/lua/nvim-lsp-installer/servers/clangd/init.lua b/lua/nvim-lsp-installer/servers/clangd/init.lua index 72327e00..3fc9d9c6 100644 --- a/lua/nvim-lsp-installer/servers/clangd/init.lua +++ b/lua/nvim-lsp-installer/servers/clangd/init.lua @@ -3,24 +3,45 @@ local path = require "nvim-lsp-installer.path" local platform = require "nvim-lsp-installer.platform" local Data = require "nvim-lsp-installer.data" local std = require "nvim-lsp-installer.installers.std" - -local VERSION = "12.0.1" - -local target = Data.coalesce( - Data.when(platform.is_mac, "clangd-mac-%s.zip"), - Data.when(platform.is_linux, "clangd-linux-%s.zip"), - Data.when(platform.is_win, "clangd-windows-%s.zip") -):format(VERSION) +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = std.unzip_remote( - ("https://github.com/clangd/clangd/releases/download/%s/%s"):format(VERSION, target) - ), + installer = { + context.github_release_file("clangd/clangd", function(version) + return Data.coalesce( + Data.when(platform.is_mac, "clangd-mac-%s.zip"), + Data.when(platform.is_linux, "clangd-linux-%s.zip"), + Data.when(platform.is_win, "clangd-windows-%s.zip") + ):format(version) + end), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), + function(server, callback, context) + vim.loop.fs_symlink( + path.concat { + server.root_dir, + ("clangd_%s"):format(context.requested_server_version), + "bin", + "clangd", + }, + path.concat { server.root_dir, "clangd" }, + function(err, success) + if not success then + context.stdio_sink.stderr(tostring(err)) + callback(false) + else + callback(true) + end + end + ) + end, + }, default_options = { - cmd = { path.concat { root_dir, ("clangd_%s"):format(VERSION), "bin", "clangd" } }, + cmd = { path.concat { root_dir, "clangd" } }, }, } end diff --git a/lua/nvim-lsp-installer/servers/clojure_lsp/init.lua b/lua/nvim-lsp-installer/servers/clojure_lsp/init.lua index 8798474e..bbdde873 100644 --- a/lua/nvim-lsp-installer/servers/clojure_lsp/init.lua +++ b/lua/nvim-lsp-installer/servers/clojure_lsp/init.lua @@ -1,25 +1,26 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local Data = require "nvim-lsp-installer.data" local platform = require "nvim-lsp-installer.platform" -local VERSION = "2021.07.01-19.49.02" - -local target = Data.coalesce( - Data.when(platform.is_mac, "clojure-lsp-native-macos-amd64.zip"), - Data.when(platform.is_linux, "clojure-lsp-native-linux-amd64.zip"), - Data.when(platform.is_win, "clojure-lsp-native-windows-amd64.zip") -) - return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, installer = { - std.unzip_remote( - ("https://github.com/clojure-lsp/clojure-lsp/releases/download/%s/%s"):format(VERSION, target) + context.github_release_file( + "clojure-lsp/clojure-lsp", + Data.coalesce( + Data.when(platform.is_mac, "clojure-lsp-native-macos-amd64.zip"), + Data.when(platform.is_linux, "clojure-lsp-native-linux-amd64.zip"), + Data.when(platform.is_win, "clojure-lsp-native-windows-amd64.zip") + ) ), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), std.chmod("+x", { "clojure-lsp" }), }, default_options = { diff --git a/lua/nvim-lsp-installer/servers/denols/init.lua b/lua/nvim-lsp-installer/servers/denols/init.lua index edaf4f21..f2131ff1 100644 --- a/lua/nvim-lsp-installer/servers/denols/init.lua +++ b/lua/nvim-lsp-installer/servers/denols/init.lua @@ -1,23 +1,32 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" -local installers = require "nvim-lsp-installer.installers" -local shell = require "nvim-lsp-installer.installers.shell" +local platform = require "nvim-lsp-installer.platform" +local Data = require "nvim-lsp-installer.data" +local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = installers.when { - unix = shell.remote_bash("https://deno.land/x/install/install.sh", { - env = { - DENO_INSTALL = root_dir, - }, - }), - win = shell.remote_powershell("https://deno.land/x/install/install.ps1", { - env = { - DENO_INSTALL = root_dir, - }, - }), + installer = { + context.github_release_file( + "denoland/deno", + Data.coalesce( + Data.when( + platform.is_mac, + Data.coalesce( + Data.when(platform.arch == "arm64", "deno-aarch64-apple-darwin.zip"), + Data.when(platform.arch == "x64", "deno-x86_64-apple-darwin.zip") + ) + ), + Data.when(platform.is_linux, "deno-x86_64-unknown-linux-gnu.zip"), + Data.when(platform.is_win, "deno-x86_64-pc-windows-msvc.zip") + ) + ), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), }, default_options = { cmd = { path.concat { root_dir, "bin", "deno" }, "lsp" }, diff --git a/lua/nvim-lsp-installer/servers/dockerls/init.lua b/lua/nvim-lsp-installer/servers/dockerls/init.lua index b493ba72..7ea76d2e 100644 --- a/lua/nvim-lsp-installer/servers/dockerls/init.lua +++ b/lua/nvim-lsp-installer/servers/dockerls/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "dockerfile-language-server-nodejs@latest" }, + installer = npm.packages { "dockerfile-language-server-nodejs" }, default_options = { cmd = { npm.executable(root_dir, "docker-langserver"), "--stdio" }, }, diff --git a/lua/nvim-lsp-installer/servers/elixirls/init.lua b/lua/nvim-lsp-installer/servers/elixirls/init.lua index 98dc7a7a..ecb0cb00 100644 --- a/lua/nvim-lsp-installer/servers/elixirls/init.lua +++ b/lua/nvim-lsp-installer/servers/elixirls/init.lua @@ -1,16 +1,17 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, installer = { - std.unzip_remote( - "https://github.com/elixir-lsp/elixir-ls/releases/download/v0.8.1/elixir-ls.zip", - "elixir-ls" - ), + context.github_release_file("elixir-lsp/elixir-ls", "elixir-ls.zip"), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file, "elixir-ls") + end), std.chmod("+x", { "elixir-ls/language_server.sh" }), }, default_options = { diff --git a/lua/nvim-lsp-installer/servers/elmls/init.lua b/lua/nvim-lsp-installer/servers/elmls/init.lua index aa776a88..30e69055 100644 --- a/lua/nvim-lsp-installer/servers/elmls/init.lua +++ b/lua/nvim-lsp-installer/servers/elmls/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "elm", "elm-test", "elm-format", "@elm-tooling/elm-language-server" }, + installer = npm.packages { "@elm-tooling/elm-language-server", "elm", "elm-test", "elm-format" }, default_options = { cmd = { npm.executable(root_dir, "elm-language-server") }, init_options = { diff --git a/lua/nvim-lsp-installer/servers/eslintls/init.lua b/lua/nvim-lsp-installer/servers/eslintls/init.lua index 89c2af5c..3e9d3cc3 100644 --- a/lua/nvim-lsp-installer/servers/eslintls/init.lua +++ b/lua/nvim-lsp-installer/servers/eslintls/init.lua @@ -1,7 +1,8 @@ local notify = require "nvim-lsp-installer.notify" local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" -local shell = require "nvim-lsp-installer.installers.shell" +local std = require "nvim-lsp-installer.installers.std" +local npm = require "nvim-lsp-installer.installers.npm" local ConfirmExecutionResult = { deny = 1, @@ -14,7 +15,11 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = shell.polyshell [[ git clone --depth 1 https://github.com/microsoft/vscode-eslint . && npm install && npm run compile:server ]], + installer = { + std.git_clone "https://github.com/microsoft/vscode-eslint", + npm.install(), + npm.run "compile:server", + }, pre_setup = function() local lspconfig = require "lspconfig" local configs = require "lspconfig/configs" diff --git a/lua/nvim-lsp-installer/servers/gopls/init.lua b/lua/nvim-lsp-installer/servers/gopls/init.lua index 3bf336d3..9534673b 100644 --- a/lua/nvim-lsp-installer/servers/gopls/init.lua +++ b/lua/nvim-lsp-installer/servers/gopls/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = go.packages { "golang.org/x/tools/gopls@latest" }, + installer = go.packages { "golang.org/x/tools/gopls" }, default_options = { cmd = { go.executable(root_dir, "gopls") }, }, diff --git a/lua/nvim-lsp-installer/servers/graphql/init.lua b/lua/nvim-lsp-installer/servers/graphql/init.lua index 54b5cef3..d11f77ef 100644 --- a/lua/nvim-lsp-installer/servers/graphql/init.lua +++ b/lua/nvim-lsp-installer/servers/graphql/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "graphql-language-service-cli@latest", "graphql" }, + installer = npm.packages { "graphql-language-service-cli", "graphql" }, default_options = { cmd = { npm.executable(root_dir, "graphql-lsp"), "server", "-m", "stream" }, filetypes = { "typescriptreact", "javascriptreact", "graphql" }, diff --git a/lua/nvim-lsp-installer/servers/hls/init.lua b/lua/nvim-lsp-installer/servers/hls/init.lua index d030c673..940deb1a 100644 --- a/lua/nvim-lsp-installer/servers/hls/init.lua +++ b/lua/nvim-lsp-installer/servers/hls/init.lua @@ -3,25 +3,25 @@ local platform = require "nvim-lsp-installer.platform" local path = require "nvim-lsp-installer.path" local installers = require "nvim-lsp-installer.installers" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local shell = require "nvim-lsp-installer.installers.shell" local Data = require "nvim-lsp-installer.data" -local VERSION = "1.4.0" - -local target = Data.coalesce( - Data.when(platform.is_mac, "haskell-language-server-macOS-%s.tar.gz"), - Data.when(platform.is_linux, "haskell-language-server-Linux-%s.tar.gz"), - Data.when(platform.is_win, "haskell-language-server-Windows-%s.tar.gz") -):format(VERSION) - return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, installer = { - std.untargz_remote( - ("https://github.com/haskell/haskell-language-server/releases/download/%s/%s"):format(VERSION, target) - ), + context.github_release_file("haskell/haskell-language-server", function(version) + return Data.coalesce( + Data.when(platform.is_mac, "haskell-language-server-macOS-%s.tar.gz"), + Data.when(platform.is_linux, "haskell-language-server-Linux-%s.tar.gz"), + Data.when(platform.is_win, "haskell-language-server-Windows-%s.tar.gz") + ):format(version) + end), + context.capture(function(ctx) + return std.untargz_remote(ctx.github_release_file) + end), installers.on { -- we can't use std.chmod because of shell wildcard expansion unix = shell.bash [[ chmod +x haskell*]], diff --git a/lua/nvim-lsp-installer/servers/init.lua b/lua/nvim-lsp-installer/servers/init.lua index bbeed678..497d5375 100644 --- a/lua/nvim-lsp-installer/servers/init.lua +++ b/lua/nvim-lsp-installer/servers/init.lua @@ -131,6 +131,11 @@ function M.is_server_installed(server_name) return scanned_server_dirs[dirname] or false end +-- returns a tuple of [server_name, requested_version], where requested_version may be nil +function M.parse_server_tuple(server_name) + return vim.split(server_name, "@") +end + function M.get_server(server_name) if INITIALIZED_SERVERS[server_name] then return true, INITIALIZED_SERVERS[server_name] diff --git a/lua/nvim-lsp-installer/servers/jdtls/init.lua b/lua/nvim-lsp-installer/servers/jdtls/init.lua index 3f250387..a7dba6c6 100644 --- a/lua/nvim-lsp-installer/servers/jdtls/init.lua +++ b/lua/nvim-lsp-installer/servers/jdtls/init.lua @@ -1,6 +1,7 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local platform = require "nvim-lsp-installer.platform" local Data = require "nvim-lsp-installer.data" @@ -41,7 +42,12 @@ return function(name, root_dir) name = name, root_dir = root_dir, installer = { - std.untargz_remote "https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz", + context.capture(function(ctx) + local version = ctx.requested_server_version or "latest" + return std.untargz_remote( + ("https://download.eclipse.org/jdtls/snapshots/jdt-language-server-%s.tar.gz"):format(version) + ) + end), std.download_file("https://projectlombok.org/downloads/lombok.jar", "lombok.jar"), }, default_options = { diff --git a/lua/nvim-lsp-installer/servers/kotlin_language_server/init.lua b/lua/nvim-lsp-installer/servers/kotlin_language_server/init.lua index 2a7ec34f..baff307f 100644 --- a/lua/nvim-lsp-installer/servers/kotlin_language_server/init.lua +++ b/lua/nvim-lsp-installer/servers/kotlin_language_server/init.lua @@ -2,12 +2,18 @@ local server = require "nvim-lsp-installer.server" local platform = require "nvim-lsp-installer.platform" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = std.unzip_remote "https://github.com/fwcd/kotlin-language-server/releases/latest/download/server.zip", + installer = { + context.github_release_file("fwcd/kotlin-language-server", "server.zip"), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), + }, default_options = { cmd = { path.concat { diff --git a/lua/nvim-lsp-installer/servers/omnisharp/init.lua b/lua/nvim-lsp-installer/servers/omnisharp/init.lua index f6260a01..fb7f99bf 100644 --- a/lua/nvim-lsp-installer/servers/omnisharp/init.lua +++ b/lua/nvim-lsp-installer/servers/omnisharp/init.lua @@ -3,30 +3,30 @@ local platform = require "nvim-lsp-installer.platform" local path = require "nvim-lsp-installer.path" local Data = require "nvim-lsp-installer.data" local std = require "nvim-lsp-installer.installers.std" - -local VERSION = "v1.37.15" - -local target = Data.coalesce( - Data.when(platform.is_mac, "omnisharp-osx.zip"), - Data.when(platform.is_linux and platform.arch == "x64", "omnisharp-linux-x64.zip"), - Data.when( - platform.is_win, - Data.coalesce( - Data.when(platform.arch == "x64", "omnisharp-win-x64.zip"), - Data.when(platform.arch == "arm64", "omnisharp-win-arm64.zip") - ) - ) -) +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, installer = { - std.unzip_remote( - ("https://github.com/OmniSharp/omnisharp-roslyn/releases/download/%s/%s"):format(VERSION, target), - "omnisharp" + context.github_release_file( + "OmniSharp/omnisharp-roslyn", + Data.coalesce( + Data.when(platform.is_mac, "omnisharp-osx.zip"), + Data.when(platform.is_linux and platform.arch == "x64", "omnisharp-linux-x64.zip"), + Data.when( + platform.is_win, + Data.coalesce( + Data.when(platform.arch == "x64", "omnisharp-win-x64.zip"), + Data.when(platform.arch == "arm64", "omnisharp-win-arm64.zip") + ) + ) + ) ), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file, "omnisharp") + end), std.chmod("+x", { "omnisharp/run" }), }, default_options = { diff --git a/lua/nvim-lsp-installer/servers/rescriptls/init.lua b/lua/nvim-lsp-installer/servers/rescriptls/init.lua index 76baba6a..caec9d53 100644 --- a/lua/nvim-lsp-installer/servers/rescriptls/init.lua +++ b/lua/nvim-lsp-installer/servers/rescriptls/init.lua @@ -1,12 +1,20 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = std.unzip_remote "https://github.com/rescript-lang/rescript-vscode/releases/download/1.1.3/rescript-vscode-1.1.3.vsix", + installer = { + context.github_release_file("rescript-lang/rescript-vscode", function(version) + return ("rescript-vscode-%s.vsix"):format(version) + end), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), + }, default_options = { cmd = { "node", path.concat { root_dir, "extension", "server", "out", "server.js" }, "--stdio" }, }, diff --git a/lua/nvim-lsp-installer/servers/rome/init.lua b/lua/nvim-lsp-installer/servers/rome/init.lua index 00e7d4b4..e4e61ab7 100644 --- a/lua/nvim-lsp-installer/servers/rome/init.lua +++ b/lua/nvim-lsp-installer/servers/rome/init.lua @@ -1,11 +1,21 @@ local server = require "nvim-lsp-installer.server" local npm = require "nvim-lsp-installer.installers.npm" +local Data = require "nvim-lsp-installer.data" +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "rome@10.0.7-nightly.2021.7.2" }, -- https://github.com/rome/tools/pull/1409 + installer = { + context.set(function(ctx) + ctx.requested_server_version = Data.coalesce( + ctx.requested_server_version, + "10.0.7-nightly.2021.7.2" -- https://github.com/rome/tools/pull/1409 + ) + end), + npm.packages { "rome" }, + }, default_options = { cmd = { npm.executable(root_dir, "rome"), "lsp" }, }, diff --git a/lua/nvim-lsp-installer/servers/rust_analyzer/init.lua b/lua/nvim-lsp-installer/servers/rust_analyzer/init.lua index 8fe0c740..c81e37b1 100644 --- a/lua/nvim-lsp-installer/servers/rust_analyzer/init.lua +++ b/lua/nvim-lsp-installer/servers/rust_analyzer/init.lua @@ -2,10 +2,9 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local platform = require "nvim-lsp-installer.platform" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local Data = require "nvim-lsp-installer.data" -local VERSION = "2021-06-28" - local target = Data.coalesce( Data.when( platform.is_mac, @@ -35,10 +34,13 @@ return function(name, root_dir) name = name, root_dir = root_dir, installer = { - std.gunzip_remote( - ("https://github.com/rust-analyzer/rust-analyzer/releases/download/%s/%s"):format(VERSION, target), - platform.is_win and "rust-analyzer.exe" or "rust-analyzer" - ), + context.github_release_file("rust-analyzer/rust-analyzer", target), + context.capture(function(ctx) + return std.gunzip_remote( + ctx.github_release_file, + platform.is_win and "rust-analyzer.exe" or "rust-analyzer" + ) + end), std.chmod("+x", { "rust-analyzer" }), }, default_options = { diff --git a/lua/nvim-lsp-installer/servers/sumneko_lua/init.lua b/lua/nvim-lsp-installer/servers/sumneko_lua/init.lua index 8332c0e6..008a2e4f 100644 --- a/lua/nvim-lsp-installer/servers/sumneko_lua/init.lua +++ b/lua/nvim-lsp-installer/servers/sumneko_lua/init.lua @@ -3,19 +3,25 @@ local path = require "nvim-lsp-installer.path" local platform = require "nvim-lsp-installer.platform" local Data = require "nvim-lsp-installer.data" local std = require "nvim-lsp-installer.installers.std" - -local bin_dir = Data.coalesce( - Data.when(platform.is_mac, "macOS"), - Data.when(platform.is_linux, "Linux"), - Data.when(platform.is_win, "Windows") -) +local context = require "nvim-lsp-installer.installers.context" return function(name, root_dir) + local bin_dir = Data.coalesce( + Data.when(platform.is_mac, "macOS"), + Data.when(platform.is_linux, "Linux"), + Data.when(platform.is_win, "Windows") + ) + return server.Server:new { name = name, root_dir = root_dir, installer = { - std.unzip_remote "https://github.com/sumneko/vscode-lua/releases/download/v2.3.6/lua-2.3.6.vsix", + context.github_release_file("sumneko/vscode-lua", function(version) + return ("lua-%s.vsix"):format(version:gsub("^v", "")) + end), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), -- see https://github.com/sumneko/vscode-lua/pull/43 std.chmod( "+x", diff --git a/lua/nvim-lsp-installer/servers/terraformls/init.lua b/lua/nvim-lsp-installer/servers/terraformls/init.lua index 350051d2..fac9a3ef 100644 --- a/lua/nvim-lsp-installer/servers/terraformls/init.lua +++ b/lua/nvim-lsp-installer/servers/terraformls/init.lua @@ -2,37 +2,41 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local platform = require "nvim-lsp-installer.platform" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local Data = require "nvim-lsp-installer.data" -local VERSION = "0.21.0" - -local target = Data.coalesce( - Data.when( - platform.is_mac, - Data.coalesce( - Data.when(platform.arch == "arm64", "terraform-ls_%s_darwin_arm64.zip"), - Data.when(platform.arch == "x64", "terraform-ls_%s_darwin_amd64.zip") - ) - ), - Data.when( - platform.is_linux, - Data.coalesce( - Data.when(platform.arch == "arm64", "terraform-ls_%s_linux_arm64.zip"), - Data.when(platform.arch == "arm", "terraform-ls_%s_linux_arm.zip"), - Data.when(platform.arch == "x64", "terraform-ls_%s_linux_amd64.zip") - ) - ), - Data.when(platform.is_win, Data.coalesce(Data.when(platform.arch == "x64", "terraform-ls_%s_windows_amd64.zip"))) -):format(VERSION) - return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = std.unzip_remote( - ("https://github.com/hashicorp/terraform-ls/releases/download/v%s/%s"):format(VERSION, target), - "terraform-ls" - ), + installer = { + context.github_release_file("hashicorp/terraform-ls", function(version) + return Data.coalesce( + Data.when( + platform.is_mac, + Data.coalesce( + Data.when(platform.arch == "arm64", "terraform-ls_%s_darwin_arm64.zip"), + Data.when(platform.arch == "x64", "terraform-ls_%s_darwin_amd64.zip") + ) + ), + Data.when( + platform.is_linux, + Data.coalesce( + Data.when(platform.arch == "arm64", "terraform-ls_%s_linux_arm64.zip"), + Data.when(platform.arch == "arm", "terraform-ls_%s_linux_arm.zip"), + Data.when(platform.arch == "x64", "terraform-ls_%s_linux_amd64.zip") + ) + ), + Data.when( + platform.is_win, + Data.coalesce(Data.when(platform.arch == "x64", "terraform-ls_%s_windows_amd64.zip")) + ) + ):format(version:gsub("^v", "")) + end), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file, "terraform-ls") + end), + }, default_options = { cmd = { path.concat { root_dir, "terraform-ls", "terraform-ls" }, "serve" }, }, diff --git a/lua/nvim-lsp-installer/servers/texlab/init.lua b/lua/nvim-lsp-installer/servers/texlab/init.lua index 47dfb09d..cbb17ea3 100644 --- a/lua/nvim-lsp-installer/servers/texlab/init.lua +++ b/lua/nvim-lsp-installer/servers/texlab/init.lua @@ -1,17 +1,10 @@ local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local Data = require "nvim-lsp-installer.data" local platform = require "nvim-lsp-installer.platform" -local VERSION = "v3.2.0" - -local target = Data.coalesce( - Data.when(platform.is_mac, "texlab-x86_64-macos.tar.gz"), - Data.when(platform.is_linux, "texlab-x86_64-linux.tar.gz"), - Data.when(platform.is_win, "texlab-x86_64-windows.tar.gz") -) - return function(name, root_dir) return server.Server:new { name = name, @@ -20,7 +13,17 @@ return function(name, root_dir) std.ensure_executables { { "pdflatex", "A TeX distribution is not installed. Refer to https://www.latex-project.org/get/." }, }, - std.untargz_remote(("https://github.com/latex-lsp/texlab/releases/download/%s/%s"):format(VERSION, target)), + context.github_release_file( + "latex-lsp/texlab", + Data.coalesce( + Data.when(platform.is_mac, "texlab-x86_64-macos.tar.gz"), + Data.when(platform.is_linux, "texlab-x86_64-linux.tar.gz"), + Data.when(platform.is_win, "texlab-x86_64-windows.tar.gz") + ) + ), + context.capture(function(ctx) + return std.untargz_remote(ctx.github_release_file) + end), }, default_options = { cmd = { path.concat { root_dir, "texlab" } }, diff --git a/lua/nvim-lsp-installer/servers/tflint/init.lua b/lua/nvim-lsp-installer/servers/tflint/init.lua index d4cb74c3..35f00918 100644 --- a/lua/nvim-lsp-installer/servers/tflint/init.lua +++ b/lua/nvim-lsp-installer/servers/tflint/init.lua @@ -1,26 +1,33 @@ local server = require "nvim-lsp-installer.server" local notify = require "nvim-lsp-installer.notify" local path = require "nvim-lsp-installer.path" -local installers = require "nvim-lsp-installer.installers" -local shell = require "nvim-lsp-installer.installers.shell" +local Data = require "nvim-lsp-installer.data" +local platform = require "nvim-lsp-installer.platform" +local std = require "nvim-lsp-installer.installers.std" +local context = require "nvim-lsp-installer.installers.context" local process = require "nvim-lsp-installer.process" +local os = Data.coalesce( + Data.when(platform.is_mac, "darwin"), + Data.when(platform.is_linux, "linux"), + Data.when(platform.is_win, "windows") +) + +local arch = Data.coalesce(Data.when(platform.arch == "x64", "amd64"), platform.arch) + +local target = ("tflint_%s_%s.zip"):format(os, arch) + return function(name, root_dir) local bin_path = path.concat { root_dir, "tflint" } return server.Server:new { name = name, root_dir = root_dir, - installer = installers.when { - unix = shell.remote_bash( - "https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh", - { - env = { - TFLINT_INSTALL_PATH = root_dir, - TFLINT_INSTALL_NO_ROOT = 1, - }, - } - ), + installer = { + context.github_release_file("terraform-linters/tflint", target), + context.capture(function(ctx) + return std.unzip_remote(ctx.github_release_file) + end), }, default_options = { cmd = { bin_path, "--langserver" }, diff --git a/lua/nvim-lsp-installer/servers/tsserver/init.lua b/lua/nvim-lsp-installer/servers/tsserver/init.lua index c1501c62..ec66e1c1 100644 --- a/lua/nvim-lsp-installer/servers/tsserver/init.lua +++ b/lua/nvim-lsp-installer/servers/tsserver/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "typescript", "typescript-language-server" }, + installer = npm.packages { "typescript-language-server", "typescript" }, default_options = { cmd = { npm.executable(root_dir, "typescript-language-server"), "--stdio" }, }, diff --git a/lua/nvim-lsp-installer/servers/vimls/init.lua b/lua/nvim-lsp-installer/servers/vimls/init.lua index 7ae8b370..756e32aa 100644 --- a/lua/nvim-lsp-installer/servers/vimls/init.lua +++ b/lua/nvim-lsp-installer/servers/vimls/init.lua @@ -5,7 +5,7 @@ return function(name, root_dir) return server.Server:new { name = name, root_dir = root_dir, - installer = npm.packages { "vim-language-server@latest" }, + installer = npm.packages { "vim-language-server" }, default_options = { cmd = { npm.executable(root_dir, "vim-language-server"), "--stdio" }, }, diff --git a/lua/nvim-lsp-installer/ui/status-win/init.lua b/lua/nvim-lsp-installer/ui/status-win/init.lua index 10fd5559..a8bad050 100644 --- a/lua/nvim-lsp-installer/ui/status-win/init.lua +++ b/lua/nvim-lsp-installer/ui/status-win/init.lua @@ -1,6 +1,6 @@ local Ui = require "nvim-lsp-installer.ui" local fs = require "nvim-lsp-installer.fs" -local log = require "nvim-lsp-installer.log" +local Log = require "nvim-lsp-installer.log" local Data = require "nvim-lsp-installer.data" local display = require "nvim-lsp-installer.ui.display" @@ -267,29 +267,41 @@ local function init(all_servers) } end - local function start_install(server, on_complete) + local function start_install(server_tuple, on_complete) + local server, requested_version = unpack(server_tuple) mutate_state(function(state) state.servers[server.name].installer.is_queued = false state.servers[server.name].installer.is_running = true end) + Log.debug("Starting install", server.name, requested_version) + server:install_attached({ + requested_server_version = requested_version, stdio_sink = { - stdout = function(line) + stdout = function(chunk) mutate_state(function(state) local tailed_output = state.servers[server.name].installer.tailed_output - tailed_output[#tailed_output + 1] = line + local lines = vim.split(chunk, "\n") + for i = 1, #lines do + tailed_output[#tailed_output + 1] = lines[i] + end end) end, - stderr = function(line) + stderr = function(chunk) mutate_state(function(state) local tailed_output = state.servers[server.name].installer.tailed_output - tailed_output[#tailed_output + 1] = line + local lines = vim.split(chunk, "\n") + for i = 1, #lines do + tailed_output[#tailed_output + 1] = lines[i] + end end) end, }, }, function(success) mutate_state(function(state) + -- can we log each line separately? + Log.debug("Installer output", server.name, state.servers[server.name].installer.tailed_output) if success then -- release stdout/err output table.. hopefully ¯\_(ツ)_/¯ state.servers[server.name].installer.tailed_output = {} @@ -321,19 +333,19 @@ local function init(all_servers) end end) - return function(server) - q[#q + 1] = server + return function(server, version) + q[#q + 1] = { server, version } check_queue() end end)() return { open = open, - install_server = function(server) - -- log.debug { "installing server", server } + install_server = function(server, version) + Log.debug("Installing server", server, version) local server_state = get_state().servers[server.name] if server_state and (server_state.installer.is_running or server_state.installer.is_queued) then - -- log.debug { "Installer is already queued/running", server.name } + Log.debug("Installer is already queued/running", server.name) return end mutate_state(function(state) @@ -341,12 +353,12 @@ local function init(all_servers) state.servers[server.name] = create_server_state(server) state.servers[server.name].installer.is_queued = true end) - queue(server) + queue(server, version) end, uninstall_server = function(server) local server_state = get_state().servers[server.name] if server_state and (server_state.installer.is_running or server_state.installer.is_queued) then - -- log.debug { "Installer is already queued/running", server.name } + Log.debug("Installer is already queued/running", server.name) return end |
