aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2021-10-26 09:47:20 +0200
committerGitHub <noreply@github.com>2021-10-26 09:47:20 +0200
commitc7ef12d8f99490c984ec171c7341577513b435a8 (patch)
treeaea6fa17846dbc45c832fa28da1025ef03861d31 /lua
parentmac's not fun (diff)
downloadmason-c7ef12d8f99490c984ec171c7341577513b435a8.tar
mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.gz
mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.bz2
mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.lz
mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.xz
mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.zst
mason-c7ef12d8f99490c984ec171c7341577513b435a8.zip
add synchronous variants of commands for better headless interop (#189)
Diffstat (limited to 'lua')
-rw-r--r--lua/nvim-lsp-installer.lua140
-rw-r--r--lua/nvim-lsp-installer/log.lua3
-rw-r--r--lua/nvim-lsp-installer/platform.lua2
-rw-r--r--lua/nvim-lsp-installer/process.lua4
-rw-r--r--lua/nvim-lsp-installer/server.lua6
-rw-r--r--lua/nvim-lsp-installer/servers/init.lua8
6 files changed, 129 insertions, 34 deletions
diff --git a/lua/nvim-lsp-installer.lua b/lua/nvim-lsp-installer.lua
index 6b2f4a06..5253e654 100644
--- a/lua/nvim-lsp-installer.lua
+++ b/lua/nvim-lsp-installer.lua
@@ -6,6 +6,7 @@ local status_win = require "nvim-lsp-installer.ui.status-win"
local servers = require "nvim-lsp-installer.servers"
local settings = require "nvim-lsp-installer.settings"
local log = require "nvim-lsp-installer.log"
+local platform = require "nvim-lsp-installer.platform"
local M = {}
@@ -16,11 +17,93 @@ function M.display()
status_win().open()
end
+---Raises an error with the provided message. If in a headless environment,
+---will also schedule an immediate shutdown with the provided exit code.
+---@param msg string
+---@param code number @The exit code to use when in headless mode.
+local function raise_error(msg, code)
+ if platform.is_headless then
+ vim.schedule(function()
+ -- We schedule the exit to make sure the call stack is exhausted
+ os.exit(code or 1)
+ end)
+ end
+ error(msg)
+end
+
+---Installs the provided servers synchronously (blocking call). It's recommended to only use this in headless environments.
+---@param server_identifiers string[] @A list of server identifiers (for example {"rust_analyzer@nightly", "tsserver"}).
+function M.install_sync(server_identifiers)
+ local completed_servers = {}
+ local failed_servers = {}
+ local server_tuples = {}
+
+ -- Collect all servers and exit early if unable to find one.
+ for _, server_identifier in pairs(server_identifiers) do
+ local server_name, version = servers.parse_server_identifier(server_identifier)
+ local ok, server = servers.get_server(server_name)
+ if not ok then
+ raise_error(("Could not find server %q."):format(server_name))
+ end
+ table.insert(server_tuples, { server, version })
+ end
+
+ -- Start all installations.
+ for _, server_tuple in ipairs(server_tuples) do
+ local server, version = unpack(server_tuple)
+
+ server:install_attached({
+ stdio_sink = process.simple_sink(),
+ requested_server_version = version,
+ }, function(success)
+ table.insert(completed_servers, server)
+ if not success then
+ table.insert(failed_servers, server)
+ end
+ end)
+ end
+
+ -- Poll for completion.
+ if vim.wait(60000 * 15, function()
+ return #completed_servers >= #server_identifiers
+ end, 100) then
+ if #failed_servers > 0 then
+ for _, server in pairs(failed_servers) do
+ log.fmt_error("Server %s failed to install.", server.name)
+ end
+ raise_error(("%d/%d servers failed to install."):format(#failed_servers, #completed_servers))
+ end
+
+ for _, server in pairs(completed_servers) do
+ log.fmt_info("Server %s was successfully installed.", server.name)
+ end
+ end
+end
+
+---Unnstalls the provided servers synchronously (blocking call). It's recommended to only use this in headless environments.
+---@param server_identifiers string[] @A list of server identifiers (for example {"rust_analyzer@nightly", "tsserver"}).
+function M.uninstall_sync(server_identifiers)
+ for _, server_identifier in pairs(server_identifiers) do
+ local server_name = servers.parse_server_identifier(server_identifier)
+ local ok, server = servers.get_server(server_name)
+ if not ok then
+ log.error(server)
+ raise_error(("Could not find server %q."):format(server_name))
+ end
+ local uninstall_ok, uninstall_error = pcall(server.uninstall, server)
+ if not uninstall_ok then
+ log.error(tostring(uninstall_error))
+ raise_error(("Failed to uninstall server %q."):format(server.name))
+ end
+ log.fmt_info("Successfully uninstalled server %s.", server.name)
+ end
+end
+
--- Queues a server to be installed. Will also open the status window.
--- Use the .on_server_ready(cb) function to register a handler to be executed when a server is ready to be set up.
---@param server_identifier string @The server to install. This can also include a requested version, for example "rust_analyzer@nightly".
function M.install(server_identifier)
- local server_name, version = unpack(servers.parse_server_identifier(server_identifier))
+ local server_name, version = servers.parse_server_identifier(server_identifier)
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)
@@ -41,35 +124,42 @@ function M.uninstall(server_name)
end
--- Queues all servers to be uninstalled. Will also open the status window.
-function M.uninstall_all()
- local choice = vim.fn.confirm(
- ("This will uninstall all servers currently installed at %q. Continue?"):format(
- vim.fn.fnamemodify(settings.current.install_root_dir, ":~")
- ),
- "&Yes\n&No",
- 2
- )
- if settings.current.install_root_dir ~= settings._DEFAULT_SETTINGS.install_root_dir then
- choice = vim.fn.confirm(
- (
- "WARNING: You are using a non-default install_root_dir (%q). This command will delete the entire directory. Continue?"
- ):format(vim.fn.fnamemodify(settings.current.install_root_dir, ":~")),
+function M.uninstall_all(no_confirm)
+ if not no_confirm then
+ local choice = vim.fn.confirm(
+ ("This will uninstall all servers currently installed at %q. Continue?"):format(
+ vim.fn.fnamemodify(settings.current.install_root_dir, ":~")
+ ),
"&Yes\n&No",
2
)
+ if settings.current.install_root_dir ~= settings._DEFAULT_SETTINGS.install_root_dir then
+ choice = vim.fn.confirm(
+ (
+ "WARNING: You are using a non-default install_root_dir (%q). This command will delete the entire directory. Continue?"
+ ):format(vim.fn.fnamemodify(settings.current.install_root_dir, ":~")),
+ "&Yes\n&No",
+ 2
+ )
+ end
+
+ if choice ~= 1 then
+ print "Uninstalling all servers was aborted."
+ return
+ end
end
- if choice == 1 then
- log.info "Uninstalling all servers."
- status_win().open()
- vim.schedule(function()
- if fs.dir_exists(settings.current.install_root_dir) then
- fs.rmrf(settings.current.install_root_dir)
- status_win().mark_all_servers_uninstalled()
- end
- end)
- else
- print "Uninstalling all servers was aborted."
+
+ log.info "Uninstalling all servers."
+ if fs.dir_exists(settings.current.install_root_dir) then
+ local ok, err = pcall(fs.rmrf, settings.current.install_root_dir)
+ if not ok then
+ log.error(err)
+ raise_error "Failed to uninstall all servers."
+ end
end
+ log.info "Successfully uninstalled all servers."
+ status_win().mark_all_servers_uninstalled()
+ status_win().open()
end
---@param cb fun(server: Server) @Callback to be executed whenever a server is ready to be set up.
diff --git a/lua/nvim-lsp-installer/log.lua b/lua/nvim-lsp-installer/log.lua
index d93fa444..a395a049 100644
--- a/lua/nvim-lsp-installer/log.lua
+++ b/lua/nvim-lsp-installer/log.lua
@@ -1,6 +1,7 @@
local Data = require "nvim-lsp-installer.data"
local path = require "nvim-lsp-installer.path"
local settings = require "nvim-lsp-installer.settings"
+local platform = require "nvim-lsp-installer.platform"
local tbl_pack = Data.tbl_pack
@@ -10,7 +11,7 @@ local config = {
-- Should print the output to neovim while running
-- values: 'sync','async',false
- use_console = false,
+ use_console = platform.is_headless,
-- Should highlighting be used in console (using echohl)
highlights = true,
diff --git a/lua/nvim-lsp-installer/platform.lua b/lua/nvim-lsp-installer/platform.lua
index 44b99199..9ab54c6a 100644
--- a/lua/nvim-lsp-installer/platform.lua
+++ b/lua/nvim-lsp-installer/platform.lua
@@ -28,4 +28,6 @@ M.is_linux = not M.is_mac and M.is_unix
-- PATH separator
M.path_sep = M.is_win and ";" or ":"
+M.is_headless = #vim.api.nvim_list_uis() == 0
+
return M
diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua
index ad17465c..7fe3625c 100644
--- a/lua/nvim-lsp-installer/process.lua
+++ b/lua/nvim-lsp-installer/process.lua
@@ -214,8 +214,8 @@ end
function M.simple_sink()
return {
- stdout = vim.schedule_wrap(print),
- stderr = vim.schedule_wrap(vim.api.nvim_err_writeln),
+ stdout = vim.schedule_wrap(vim.api.nvim_out_write),
+ stderr = vim.schedule_wrap(vim.api.nvim_err_write),
}
end
diff --git a/lua/nvim-lsp-installer/server.lua b/lua/nvim-lsp-installer/server.lua
index f1e0fdef..b1081d7a 100644
--- a/lua/nvim-lsp-installer/server.lua
+++ b/lua/nvim-lsp-installer/server.lua
@@ -65,10 +65,12 @@ function M.Server:setup(opts)
end
end
+---@return table @A deep copy of this server's default options. Note that these default options are nvim-lsp-installer specific, and does not include any default options provided by lspconfig.
function M.Server:get_default_options()
return vim.deepcopy(self._default_options)
end
+---@return string[] @The list of supported filetypes.
function M.Server:get_supported_filetypes()
local metadata = require "nvim-lsp-installer._generated.metadata"
@@ -79,6 +81,7 @@ function M.Server:get_supported_filetypes()
return {}
end
+---@return boolean
function M.Server:is_installed()
return servers.is_server_installed(self.name)
end
@@ -87,10 +90,13 @@ function M.Server:create_root_dir()
fs.mkdirp(self.root_dir)
end
+---Queues the server to be asynchronously installed. Also opens the UI window.
function M.Server:install()
status_win().install_server(self)
end
+---@param context ServerInstallContext
+---@param callback ServerInstallCallback
function M.Server:install_attached(context, callback)
local uninstall_ok, uninstall_err = pcall(self.uninstall, self)
if not uninstall_ok then
diff --git a/lua/nvim-lsp-installer/servers/init.lua b/lua/nvim-lsp-installer/servers/init.lua
index d98bd224..3f252b83 100644
--- a/lua/nvim-lsp-installer/servers/init.lua
+++ b/lua/nvim-lsp-installer/servers/init.lua
@@ -154,14 +154,10 @@ function M.is_server_installed(server_name)
return scanned_server_dirs[dirname] or false
end
----@class ServerTuple
----@field public [1] string The server name.
----@field public [2] string|nil The requested server version.
-
---@param server_identifier string @The server identifier to parse.
----@return ServerTuple
+---@return string, string|nil @Returns a (server_name, requested_version) tuple, where requested_version may be nil.
function M.parse_server_identifier(server_identifier)
- return vim.split(server_identifier, "@")
+ return unpack(vim.split(server_identifier, "@"))
end
---@param server_name string