aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua')
-rw-r--r--lua/mason-core/package/init.lua10
-rw-r--r--lua/mason/init.lua19
-rw-r--r--lua/mason/terminator.lua101
3 files changed, 130 insertions, 0 deletions
diff --git a/lua/mason-core/package/init.lua b/lua/mason-core/package/init.lua
index 81d8ca31..e46219b7 100644
--- a/lua/mason-core/package/init.lua
+++ b/lua/mason-core/package/init.lua
@@ -80,7 +80,17 @@ function Package:new_handle()
log.fmt_trace("Creating new handle for %s", self)
local handle = InstallationHandle.new(self)
self.handle = handle
+
+ -- First emit a private autocmd via the native event bus. This is to enable some internal perf improvements (helps avoid loading some Lua modules).
+ if vim.fn.has "nvim-0.8.0" == 1 then
+ vim.api.nvim_exec_autocmds("User", { pattern = "__MasonPackageHandle", data = self.name })
+ else
+ vim.api.nvim_exec_autocmds("User", { pattern = "__MasonPackageHandle" })
+ end
+
self:emit("handle", handle)
+ registry:emit("package:handle", self, handle)
+
return handle
end
diff --git a/lua/mason/init.lua b/lua/mason/init.lua
index 37926acc..f6c46ef4 100644
--- a/lua/mason/init.lua
+++ b/lua/mason/init.lua
@@ -4,6 +4,24 @@ local platform = require "mason-core.platform"
local M = {}
+local function setup_autocmds()
+ -- lazily set up terminator
+ vim.api.nvim_create_autocmd("User", {
+ pattern = "__MasonPackageHandle", -- private autocmd specific for this very use case
+ callback = function()
+ require("mason.terminator").setup()
+ end,
+ once = true,
+ })
+
+ vim.api.nvim_create_autocmd("VimLeavePre", {
+ callback = function()
+ require("mason.terminator").terminate()
+ end,
+ once = true,
+ })
+end
+
---@param config MasonSettings?
function M.setup(config)
if config then
@@ -17,6 +35,7 @@ function M.setup(config)
end
require "mason.api.command"
+ setup_autocmds()
end
return M
diff --git a/lua/mason/terminator.lua b/lua/mason/terminator.lua
new file mode 100644
index 00000000..7a9290a0
--- /dev/null
+++ b/lua/mason/terminator.lua
@@ -0,0 +1,101 @@
+local registry = require "mason-registry"
+local a = require "mason-core.async"
+
+-- Hasta la vista, baby.
+-- ______
+-- <((((((\\\
+-- / . }\
+-- ;--..--._|}
+-- (\ '--/\--' )
+-- \\ | '-' :'|
+-- \\ . -==- .-|
+-- \\ \.__.' \--._
+-- [\\ __.--| // _/'--.
+-- \ \\ .'-._ ('-----'/ __/ \
+-- \ \\ / __>| | '--. |
+-- \ \\ | \ | / / /
+-- \ '\ / \ | | _/ /
+-- \ \ \ | | / /
+-- snd \ \ \ /
+
+local M = {}
+
+---@async
+---@param handles InstallHandle[]
+local function terminate_handles(handles)
+ a.wait_all(vim.tbl_map(
+ ---@param handle InstallHandle
+ function(handle)
+ if not handle:is_closed() then
+ handle:terminate()
+ end
+ return function()
+ a.wait(function(resolve)
+ if handle:is_closed() then
+ resolve()
+ else
+ handle:once("closed", resolve)
+ end
+ end)
+ end
+ end,
+ handles
+ ))
+end
+
+local active_handles = {}
+
+function M.setup()
+ registry:on("package:handle", function(_, handle)
+ if handle:is_closed() then
+ return
+ end
+ active_handles[handle] = true
+ handle:once("closed", function()
+ active_handles[handle] = nil
+ end)
+ end)
+end
+
+function M.terminate()
+ local handles = vim.tbl_keys(active_handles)
+ if #handles > 0 then
+ local package_names = vim.tbl_map(function(h)
+ return h.package.name
+ end, handles)
+ table.sort(package_names)
+
+ -- 1. Print warning message.
+ vim.api.nvim_echo({
+ {
+ "[mason.nvim] Neovim is exiting while packages are still installing. Terminating all installations…",
+ "WarningMsg",
+ },
+ }, true, {})
+ vim.cmd "redraw"
+
+ -- 2. Synchronously terminate all installation handles.
+ a.run_blocking(function()
+ a.wait_first {
+ function()
+ a.sleep(5000)
+ end,
+ function()
+ terminate_handles(handles)
+ end,
+ }
+ end)
+
+ -- 3. Schedule error message to be displayed so that Neovim prints it to the tty.
+ -- XXX: does this need to be conditional on which UIs are attached?
+ vim.schedule(function()
+ vim.api.nvim_err_writeln(
+ ("[mason.nvim] Neovim exited while the following packages were installing. Installation was aborted.\n- %s"):format(
+ table.concat(package_names, #package_names > 5 and ", " or "\n- ")
+ )
+ )
+ end)
+ end
+end
+
+return M