diff options
| author | William Boman <william@redwill.se> | 2022-03-05 22:42:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-05 22:42:25 +0100 |
| commit | f9299bb59c9e42d59fc57ed034fb84bdd23bbd77 (patch) | |
| tree | 0ac6e701d7fa206ce5e05b4daed2238ab1eaf6c0 /lua/nvim-lsp-installer | |
| parent | async: raise errors instead of returning pcall-style (#521) (diff) | |
| download | mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar.gz mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar.bz2 mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar.lz mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar.xz mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.tar.zst mason-f9299bb59c9e42d59fc57ed034fb84bdd23bbd77.zip | |
feat(ui): display installed server version (#520)
Diffstat (limited to 'lua/nvim-lsp-installer')
| -rw-r--r-- | lua/nvim-lsp-installer/core/async/spawn.lua | 36 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/core/result.lua | 49 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/jobs/outdated-servers/gem.lua | 14 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/jobs/version-check/init.lua | 131 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/process.lua | 2 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/ui/status-win/init.lua | 68 |
6 files changed, 277 insertions, 23 deletions
diff --git a/lua/nvim-lsp-installer/core/async/spawn.lua b/lua/nvim-lsp-installer/core/async/spawn.lua new file mode 100644 index 00000000..e643f098 --- /dev/null +++ b/lua/nvim-lsp-installer/core/async/spawn.lua @@ -0,0 +1,36 @@ +local a = require "nvim-lsp-installer.core.async" +local process = require "nvim-lsp-installer.process" +local platform = require "nvim-lsp-installer.platform" + +local async_spawn = a.promisify(process.spawn) + +local spawn = { + aliases = { + npm = platform.is_win and "npm.cmd" or "npm", + }, +} + +setmetatable(spawn, { + __index = function(self, k) + return function(args) + local stdio = process.in_memory_sink() + local cmd_args = {} + for i, arg in ipairs(args) do + cmd_args[i] = arg + end + ---@type JobSpawnOpts + local spawn_args = { + stdio_sink = stdio.sink, + cwd = args.cwd, + env = args.env, + args = cmd_args, + } + local cmd = self.aliases[k] or k + local _, exit_code = async_spawn(cmd, spawn_args) + assert(exit_code == 0, ("%q exited with an error code: %d."):format(cmd, exit_code)) + return table.concat(stdio.buffers.stdout, ""), table.concat(stdio.buffers.stderr, "") + end + end, +}) + +return spawn diff --git a/lua/nvim-lsp-installer/core/result.lua b/lua/nvim-lsp-installer/core/result.lua new file mode 100644 index 00000000..33623c66 --- /dev/null +++ b/lua/nvim-lsp-installer/core/result.lua @@ -0,0 +1,49 @@ +---@class Failure +---@field error any +local Failure = {} +Failure.__index = Failure + +function Failure.new(error) + return setmetatable({ error = error }, Failure) +end + +---@class Result +---@field value any +local Result = {} +Result.__index = Result + +function Result.new(value) + return setmetatable({ + value = value, + }, Result) +end + +function Result.success(value) + return Result.new(value) +end + +function Result.failure(error) + return Result.new(Failure.new(error)) +end + +function Result:get_or_nil() + if self:is_success() then + return self.value + end +end + +function Result:err_or_nil() + if self:is_failure() then + return self.value.error + end +end + +function Result:is_failure() + return getmetatable(self.value) == Failure +end + +function Result:is_success() + return getmetatable(self.value) ~= Failure +end + +return Result diff --git a/lua/nvim-lsp-installer/jobs/outdated-servers/gem.lua b/lua/nvim-lsp-installer/jobs/outdated-servers/gem.lua index 909bf7c3..cf880fd0 100644 --- a/lua/nvim-lsp-installer/jobs/outdated-servers/gem.lua +++ b/lua/nvim-lsp-installer/jobs/outdated-servers/gem.lua @@ -27,6 +27,19 @@ local function parse_outdated_gem(outdated_gem) return outdated_package end +---@param output string +local function parse_gem_list_output(output) + ---@type Record<string, string> + local gem_versions = {} + for _, line in ipairs(vim.split(output, "\n")) do + local gem_package, version = line:match "^(%S+) %((%S+)%)$" + if gem_package and version then + gem_versions[gem_package] = version + end + end + return gem_versions +end + ---@param server Server ---@param source InstallReceiptSource ---@param on_check_complete fun(result: VersionCheckResult) @@ -74,6 +87,7 @@ end -- to allow tests to access internals return setmetatable({ parse_outdated_gem = parse_outdated_gem, + parse_gem_list_output = parse_gem_list_output, }, { __call = function(_, ...) return gem_checker(...) diff --git a/lua/nvim-lsp-installer/jobs/version-check/init.lua b/lua/nvim-lsp-installer/jobs/version-check/init.lua new file mode 100644 index 00000000..11df3721 --- /dev/null +++ b/lua/nvim-lsp-installer/jobs/version-check/init.lua @@ -0,0 +1,131 @@ +local a = require "nvim-lsp-installer.core.async" +local Result = require "nvim-lsp-installer.core.result" +local process = require "nvim-lsp-installer.process" +local pip3 = require "nvim-lsp-installer.installers.pip3" +local gem = require "nvim-lsp-installer.installers.gem" +local cargo_check = require "nvim-lsp-installer.jobs.outdated-servers.cargo" +local gem_check = require "nvim-lsp-installer.jobs.outdated-servers.gem" +local spawn = require "nvim-lsp-installer.core.async.spawn" + +local M = {} + +local ServerVersion = {} +ServerVersion.__index = ServerVersion + +---@param field_name string +local function version_in_receipt(field_name) + ---@param receipt InstallReceipt + ---@return Result + return function(_, receipt) + return Result.success(receipt.primary_source[field_name]) + end +end + +---@param package string +---@return string +---@TODO DRY +local function normalize_pip3_package(package) + -- https://stackoverflow.com/a/60307740 + local s = package:gsub("%[.*%]", "") + return s +end + +local function noop() + return Result.failure "Unable to detect version." +end + +---@type Record<InstallReceiptSourceType, fun(server: Server, receipt: InstallReceipt): Result> +local version_checker = { + ["npm"] = function(server, receipt) + local stdout = spawn.npm { + "ls", + "--json", + cwd = server.root_dir, + } + local npm_packages = vim.json.decode(stdout) + return Result.success(npm_packages.dependencies[receipt.primary_source.package].version) + end, + ["pip3"] = function(server, receipt) + local stdout = spawn.python3 { + "-m", + "pip", + "list", + "--format", + "json", + cwd = server.root_dir, + env = process.graft_env(pip3.env(server.root_dir)), + } + local pip_packages = vim.json.decode(stdout) + local normalized_pip_package = normalize_pip3_package(receipt.primary_source.package) + for _, pip_package in ipairs(pip_packages) do + if pip_package.name == normalized_pip_package then + return Result.success(pip_package.version) + end + end + return Result.failure "Failed to find pip package version." + end, + ["gem"] = function(server, receipt) + local stdout = spawn.gem { + "list", + cwd = server.root_dir, + env = process.graft_env(gem.env(server.root_dir)), + } + local gems = gem_check.parse_gem_list_output(stdout) + if gems[receipt.primary_source.package] then + return Result.success(gems[receipt.primary_source.package]) + else + return Result.failure "Failed to find gem package version." + end + end, + ["cargo"] = function(server, receipt) + local stdout = spawn.cargo { + "install", + "--list", + "--root", + server.root_dir, + cwd = server.root_dir, + } + local crates = cargo_check.parse_installed_crates(stdout) + a.scheduler() -- needed because vim.fn.* call + local package = vim.fn.fnamemodify(receipt.primary_source.package, ":t") + if crates[package] then + return Result.success(crates[package]) + else + return Result.failure "Failed to find cargo package version." + end + end, + ["git"] = function(server) + local stdout = spawn.git { + "rev-parse", + "--short", + "HEAD", + cwd = server.root_dir, + } + return Result.success(vim.trim(stdout)) + end, + ["opam"] = noop, + ["dotnet"] = noop, + ["r_package"] = noop, + ["github_release_file"] = version_in_receipt "release", + ["github_tag"] = version_in_receipt "tag", + ["jdtls"] = version_in_receipt "version", +} + +--- Async function. +---@param server Server +---@return Result +function M.check_server_version(server) + local receipt = server:get_receipt() + if not receipt then + return Result.failure "Unable to retrieve installation receipt." + end + local version_check = version_checker[receipt.primary_source.type] or noop + local ok, result = pcall(version_check, server, receipt) + if ok then + return result + else + return Result.failure(result) + end +end + +return M diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua |
