diff --git a/lua/mason-core/functional/init.lua b/lua/mason-core/functional/init.lua index a153e8fa4..ed502a4bc 100644 --- a/lua/mason-core/functional/init.lua +++ b/lua/mason-core/functional/init.lua @@ -50,6 +50,7 @@ _.flatten = list.flatten _.sort_by = list.sort_by _.uniq_by = list.uniq_by _.join = list.join +_.partition = list.partition ---@module "mason-core.functional.relation" local relation = lazy_require "mason-core.functional.relation" diff --git a/lua/mason-core/functional/list.lua b/lua/mason-core/functional/list.lua index 151b9b256..31b631b86 100644 --- a/lua/mason-core/functional/list.lua +++ b/lua/mason-core/functional/list.lua @@ -189,4 +189,16 @@ _.uniq_by = fun.curryN(function(id, list) return result end, 2) +---@generic T +---@param predicate fun(item: T): boolean +---@param list T[] +---@return T[][] # [T[], T[]] +_.partition = fun.curryN(function(predicate, list) + local partitions = { {}, {} } + for _, item in ipairs(list) do + table.insert(partitions[predicate(item) and 1 or 2], item) + end + return partitions +end, 2) + return _ diff --git a/lua/mason-core/installer/context.lua b/lua/mason-core/installer/context.lua index b6cc24e57..dd9b96171 100644 --- a/lua/mason-core/installer/context.lua +++ b/lua/mason-core/installer/context.lua @@ -147,6 +147,7 @@ InstallContext.__index = InstallContext ---@class InstallContextOpts ---@field requested_version string? +---@field debug boolean? ---@param handle InstallHandle ---@param opts InstallContextOpts diff --git a/lua/mason-core/installer/init.lua b/lua/mason-core/installer/init.lua index 2ab33bc63..ba45789ec 100644 --- a/lua/mason-core/installer/init.lua +++ b/lua/mason-core/installer/init.lua @@ -147,10 +147,16 @@ function M.execute(handle, opts) context.stdio_sink.stderr(tostring(failure)) context.stdio_sink.stderr "\n" - -- clean up installation dir - pcall(function() - fs.async.rmrf(context.cwd:get()) - end) + if not opts.debug then + -- clean up installation dir + pcall(function() + fs.async.rmrf(context.cwd:get()) + end) + else + context.stdio_sink.stdout( + ("[debug] Installation directory retained at %q.\n"):format(context.cwd:get()) + ) + end -- unlink linked executables (in the rare occasion an error occurs after linking) linker.unlink(context.package, context.receipt.links) diff --git a/lua/mason-core/package/init.lua b/lua/mason-core/package/init.lua index ad7f6037f..81d8ca317 100644 --- a/lua/mason-core/package/init.lua +++ b/lua/mason-core/package/init.lua @@ -84,7 +84,7 @@ function Package:new_handle() return handle end ----@param opts { version: string? }? +---@param opts? { version: string?, debug: boolean? } ---@return InstallHandle function Package:install(opts) opts = opts or {} @@ -125,6 +125,7 @@ function Package:install(opts) handle, { requested_version = opts.version, + debug = opts.debug, } ) return handle diff --git a/lua/mason/api/command.lua b/lua/mason/api/command.lua index c02b18c03..8cadbc337 100644 --- a/lua/mason/api/command.lua +++ b/lua/mason/api/command.lua @@ -78,7 +78,9 @@ local function join_handles(handles) end ---@param package_specifiers string[] -local function MasonInstall(package_specifiers) +---@param opts? { debug: boolean } +local function MasonInstall(package_specifiers, opts) + opts = opts or {} local Package = require "mason-core.package" local registry = require "mason-registry" local valid_packages = filter_valid_packages(package_specifiers) @@ -96,7 +98,7 @@ local function MasonInstall(package_specifiers) local handles = _.map(function(pkg_specifier) local package_name, version = Package.Parse(pkg_specifier) local pkg = registry.get_package(package_name) - return pkg:install { version = version } + return pkg:install { version = version, debug = opts.debug } end, valid_packages) if is_headless then @@ -110,8 +112,17 @@ local function MasonInstall(package_specifiers) end end +---@param args string[] +---@return table opts, string[] args +local function parse_args(args) + local opts_list, args = unpack(_.partition(_.starts_with "--", args)) + local opts = _.set_of(_.map(_.gsub("^%-%-", ""), opts_list)) + return opts, args +end + vim.api.nvim_create_user_command("MasonInstall", function(opts) - MasonInstall(opts.fargs) + local command_opts, packages = parse_args(opts.fargs) + MasonInstall(packages, command_opts) end, { desc = "Install one or more packages.", nargs = "+", diff --git a/tests/mason-core/functional/list_spec.lua b/tests/mason-core/functional/list_spec.lua index 029396e31..add9076e2 100644 --- a/tests/mason-core/functional/list_spec.lua +++ b/tests/mason-core/functional/list_spec.lua @@ -195,4 +195,12 @@ describe("functional: list", function() local list = { "Person.", "Woman.", "Man.", "Person.", "Woman.", "Camera.", "TV." } assert.same({ "Person.", "Woman.", "Man.", "Camera.", "TV." }, _.uniq_by(_.identity, list)) end) + + it("should partition lists", function() + local words = { "person", "Woman", "Man", "camera", "TV" } + assert.same({ + { "Woman", "Man", "TV" }, + { "person", "camera" }, + }, _.partition(_.matches "%u", words)) + end) end) diff --git a/tests/mason/api/command_spec.lua b/tests/mason/api/command_spec.lua index d2b2215e4..14b656190 100644 --- a/tests/mason/api/command_spec.lua +++ b/tests/mason/api/command_spec.lua @@ -36,6 +36,19 @@ describe(":MasonInstall", function() end) ) + it( + "should install provided packages in debug mode", + async_test(function() + local dummy = registry.get_package "dummy" + local dummy2 = registry.get_package "dummy2" + spy.on(Pkg, "install") + vim.cmd [[MasonInstall --debug dummy dummy2]] + assert.spy(Pkg.install).was_called(2) + assert.spy(Pkg.install).was_called_with(match.is_ref(dummy), { version = nil, debug = true }) + assert.spy(Pkg.install).was_called_with(match.is_ref(dummy2), { version = nil, debug = true }) + end) + ) + it( "should open the UI window", async_test(function()