aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2025-02-16 17:07:22 +0100
committerWilliam Boman <william@redwill.se>2025-02-19 12:15:49 +0100
commit5063ba98dc220a754caf68e510fb192755b1bdf0 (patch)
tree174abf2bd4339e3ea1db3652610469f3f09e24b2 /lua/mason-core
parentfeat(context): add ctx:fetch() (diff)
downloadmason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar.gz
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar.bz2
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar.lz
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar.xz
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.tar.zst
mason-5063ba98dc220a754caf68e510fb192755b1bdf0.zip
refactor: turn StdioSink into a proper class
Diffstat (limited to 'lua/mason-core')
-rw-r--r--lua/mason-core/installer/InstallHandle.lua24
-rw-r--r--lua/mason-core/installer/InstallRunner.lua6
-rw-r--r--lua/mason-core/installer/compiler/schemas.lua4
-rw-r--r--lua/mason-core/installer/compiler/util.lua10
-rw-r--r--lua/mason-core/installer/context/InstallContextSpawn.lua2
-rw-r--r--lua/mason-core/installer/context/init.lua4
-rw-r--r--lua/mason-core/installer/managers/cargo.lua2
-rw-r--r--lua/mason-core/installer/managers/composer.lua2
-rw-r--r--lua/mason-core/installer/managers/gem.lua28
-rw-r--r--lua/mason-core/installer/managers/golang.lua2
-rw-r--r--lua/mason-core/installer/managers/luarocks.lua2
-rw-r--r--lua/mason-core/installer/managers/npm.lua6
-rw-r--r--lua/mason-core/installer/managers/nuget.lua2
-rw-r--r--lua/mason-core/installer/managers/opam.lua2
-rw-r--r--lua/mason-core/installer/managers/pypi.lua10
-rw-r--r--lua/mason-core/installer/managers/std.lua6
-rw-r--r--lua/mason-core/process.lua126
-rw-r--r--lua/mason-core/spawn.lua37
18 files changed, 157 insertions, 118 deletions
diff --git a/lua/mason-core/installer/InstallHandle.lua b/lua/mason-core/installer/InstallHandle.lua
index f5a42c53..22c654a3 100644
--- a/lua/mason-core/installer/InstallHandle.lua
+++ b/lua/mason-core/installer/InstallHandle.lua
@@ -45,7 +45,7 @@ end
---@class InstallHandle : EventEmitter
---@field package AbstractPackage
---@field state InstallHandleState
----@field stdio { buffers: { stdout: string[], stderr: string[] }, sink: StdioSink }
+---@field stdio_sink BufferedSink
---@field is_terminated boolean
---@field location InstallLocation
---@field private spawn_handles InstallHandleSpawnHandle[]
@@ -53,33 +53,17 @@ local InstallHandle = {}
InstallHandle.__index = InstallHandle
setmetatable(InstallHandle, { __index = EventEmitter })
----@param handle InstallHandle
-local function new_sink(handle)
- local stdout, stderr = {}, {}
- return {
- buffers = { stdout = stdout, stderr = stderr },
- sink = {
- stdout = function(chunk)
- stdout[#stdout + 1] = chunk
- handle:emit("stdout", chunk)
- end,
- stderr = function(chunk)
- stderr[#stderr + 1] = chunk
- handle:emit("stderr", chunk)
- end,
- },
- }
-end
-
---@param pkg AbstractPackage
---@param location InstallLocation
function InstallHandle:new(pkg, location)
---@type InstallHandle
local instance = EventEmitter.new(self)
+ local sink = process.BufferedSink:new()
+ sink:connect_events(instance)
instance.state = "IDLE"
instance.package = pkg
instance.spawn_handles = {}
- instance.stdio = new_sink(instance)
+ instance.stdio_sink = sink
instance.is_terminated = false
instance.location = location
return instance
diff --git a/lua/mason-core/installer/InstallRunner.lua b/lua/mason-core/installer/InstallRunner.lua
index fa2b3fcf..342dc443 100644
--- a/lua/mason-core/installer/InstallRunner.lua
+++ b/lua/mason-core/installer/InstallRunner.lua
@@ -55,13 +55,13 @@ function InstallRunner:execute(opts, callback)
---@async
local function finalize_logs(success, result)
if not success then
- context.stdio_sink.stderr(tostring(result))
- context.stdio_sink.stderr "\n"
+ context.stdio_sink:stderr(tostring(result))
+ context.stdio_sink:stderr "\n"
end
if opts.debug then
context.fs:write_file("mason-debug.log", table.concat(tailed_output, ""))
- context.stdio_sink.stdout(("[debug] Installation directory retained at %q.\n"):format(context.cwd:get()))
+ context.stdio_sink:stdout(("[debug] Installation directory retained at %q.\n"):format(context.cwd:get()))
end
end
diff --git a/lua/mason-core/installer/compiler/schemas.lua b/lua/mason-core/installer/compiler/schemas.lua
index 5e578dbd..889a2ad9 100644
--- a/lua/mason-core/installer/compiler/schemas.lua
+++ b/lua/mason-core/installer/compiler/schemas.lua
@@ -20,7 +20,7 @@ local function download_lsp_schema(ctx, url)
if is_vscode_schema then
local url = unpack(_.match("^vscode:(.+)$", url))
- ctx.stdio_sink.stdout(("Downloading LSP configuration schema from %q…\n"):format(url))
+ ctx.stdio_sink:stdout(("Downloading LSP configuration schema from %q…\n"):format(url))
local json = try(fetch(url))
---@type { contributes?: { configuration?: table } }
@@ -34,7 +34,7 @@ local function download_lsp_schema(ctx, url)
return Result.failure "Unable to find LSP entry in VSCode schema."
end
else
- ctx.stdio_sink.stdout(("Downloading LSP configuration schema from %q…\n"):format(url))
+ ctx.stdio_sink:stdout(("Downloading LSP configuration schema from %q…\n"):format(url))
try(std.download_file(url, out_file))
ctx.links.share[share_file] = out_file
end
diff --git a/lua/mason-core/installer/compiler/util.lua b/lua/mason-core/installer/compiler/util.lua
index b3735c9c..c244cca8 100644
--- a/lua/mason-core/installer/compiler/util.lua
+++ b/lua/mason-core/installer/compiler/util.lua
@@ -44,7 +44,7 @@ function M.ensure_valid_version(versions_thunk)
local version = ctx.opts.version
if version and not ctx.opts.force then
- ctx.stdio_sink.stdout "Fetching available versions…\n"
+ ctx.stdio_sink:stdout "Fetching available versions…\n"
local all_versions = versions_thunk()
if all_versions:is_failure() then
log.warn("Failed to fetch versions for package", ctx.package)
@@ -54,10 +54,10 @@ function M.ensure_valid_version(versions_thunk)
all_versions = all_versions:get_or_else {}
if not _.any(_.equals(version), all_versions) then
- ctx.stdio_sink.stderr(("Tried to install invalid version %q. Available versions:\n"):format(version))
- ctx.stdio_sink.stderr(_.compose(_.join "\n", _.map(_.join ", "), _.split_every(15))(all_versions))
- ctx.stdio_sink.stderr "\n\n"
- ctx.stdio_sink.stderr(
+ ctx.stdio_sink:stderr(("Tried to install invalid version %q. Available versions:\n"):format(version))
+ ctx.stdio_sink:stderr(_.compose(_.join "\n", _.map(_.join ", "), _.split_every(15))(all_versions))
+ ctx.stdio_sink:stderr "\n\n"
+ ctx.stdio_sink:stderr(
("Run with --force flag to bypass version validation:\n :MasonInstall --force %s@%s\n\n"):format(
ctx.package.name,
version
diff --git a/lua/mason-core/installer/context/InstallContextSpawn.lua b/lua/mason-core/installer/context/InstallContextSpawn.lua
index f2ce8df2..29e62101 100644
--- a/lua/mason-core/installer/context/InstallContextSpawn.lua
+++ b/lua/mason-core/installer/context/InstallContextSpawn.lua
@@ -25,7 +25,7 @@ function InstallContextSpawn:__index(cmd)
---@param args JobSpawnOpts
return function(args)
args.cwd = args.cwd or self.cwd:get()
- args.stdio_sink = args.stdio_sink or self.handle.stdio.sink
+ args.stdio_sink = args.stdio_sink or self.handle.stdio_sink
local on_spawn = args.on_spawn
local captured_handle
args.on_spawn = function(handle, stdio, pid, ...)
diff --git a/lua/mason-core/installer/context/init.lua b/lua/mason-core/installer/context/init.lua
index 6f0d4c57..44490782 100644
--- a/lua/mason-core/installer/context/init.lua
+++ b/lua/mason-core/installer/context/init.lua
@@ -2,9 +2,9 @@ local InstallContextCwd = require "mason-core.installer.context.InstallContextCw
local InstallContextFs = require "mason-core.installer.context.InstallContextFs"
local InstallContextSpawn = require "mason-core.installer.context.InstallContextSpawn"
local Result = require "mason-core.result"
-local fetch = require "mason-core.fetch"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
+local fetch = require "mason-core.fetch"
local fs = require "mason-core.fs"
local log = require "mason-core.log"
local path = require "mason-core.path"
@@ -39,7 +39,7 @@ function InstallContext:new(handle, opts)
package = handle.package, -- for convenience
fs = fs,
receipt = receipt.InstallReceiptBuilder:new(),
- stdio_sink = handle.stdio.sink,
+ stdio_sink = handle.stdio_sink,
links = {
bin = {},
share = {},
diff --git a/lua/mason-core/installer/managers/cargo.lua b/lua/mason-core/installer/managers/cargo.lua
index 8a3c35cf..22ec9ed6 100644
--- a/lua/mason-core/installer/managers/cargo.lua
+++ b/lua/mason-core/installer/managers/cargo.lua
@@ -15,7 +15,7 @@ function M.install(crate, version, opts)
opts = opts or {}
log.fmt_debug("cargo: install %s %s %s", crate, version, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing crate %s@%s…\n"):format(crate, version))
+ ctx.stdio_sink:stdout(("Installing crate %s@%s…\n"):format(crate, version))
return ctx.spawn.cargo {
"install",
"--root",
diff --git a/lua/mason-core/installer/managers/composer.lua b/lua/mason-core/installer/managers/composer.lua
index a4a94270..3afd3ff8 100644
--- a/lua/mason-core/installer/managers/composer.lua
+++ b/lua/mason-core/installer/managers/composer.lua
@@ -14,7 +14,7 @@ local M = {}
function M.install(package, version)
log.fmt_debug("composer: install %s %s", package, version)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing composer package %s@%s…\n"):format(package, version))
+ ctx.stdio_sink:stdout(("Installing composer package %s@%s…\n"):format(package, version))
return Result.try(function(try)
try(ctx.spawn.composer {
"init",
diff --git a/lua/mason-core/installer/managers/gem.lua b/lua/mason-core/installer/managers/gem.lua
index e8723d7e..30bff29d 100644
--- a/lua/mason-core/installer/managers/gem.lua
+++ b/lua/mason-core/installer/managers/gem.lua
@@ -15,7 +15,7 @@ function M.install(pkg, version, opts)
opts = opts or {}
log.fmt_debug("gem: install %s %s %s", pkg, version, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing gem %s@%s…\n"):format(pkg, version))
+ ctx.stdio_sink:stdout(("Installing gem %s@%s…\n"):format(pkg, version))
return ctx.spawn.gem {
"install",
"--no-user-install",
@@ -50,22 +50,16 @@ function M.create_bin_wrapper(bin)
return Result.failure(("Cannot link Gem executable %q because it doesn't exist."):format(bin))
end
- return Result.pcall(
- ctx.write_shell_exec_wrapper,
- ctx,
- bin,
- path.concat { ctx:get_install_path(), bin_path },
- {
- GEM_PATH = platform.when {
- unix = function()
- return ("%s:$GEM_PATH"):format(ctx:get_install_path())
- end,
- win = function()
- return ("%s;%%GEM_PATH%%"):format(ctx:get_install_path())
- end,
- },
- }
- )
+ return Result.pcall(ctx.write_shell_exec_wrapper, ctx, bin, path.concat { ctx:get_install_path(), bin_path }, {
+ GEM_PATH = platform.when {
+ unix = function()
+ return ("%s:$GEM_PATH"):format(ctx:get_install_path())
+ end,
+ win = function()
+ return ("%s;%%GEM_PATH%%"):format(ctx:get_install_path())
+ end,
+ },
+ })
end
return M
diff --git a/lua/mason-core/installer/managers/golang.lua b/lua/mason-core/installer/managers/golang.lua
index 2d7b9b0b..04b24741 100644
--- a/lua/mason-core/installer/managers/golang.lua
+++ b/lua/mason-core/installer/managers/golang.lua
@@ -15,7 +15,7 @@ function M.install(pkg, version, opts)
opts = opts or {}
log.fmt_debug("golang: install %s %s %s", pkg, version, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing go package %s@%s…\n"):format(pkg, version))
+ ctx.stdio_sink:stdout(("Installing go package %s@%s…\n"):format(pkg, version))
local env = {
GOBIN = ctx.cwd:get(),
}
diff --git a/lua/mason-core/installer/managers/luarocks.lua b/lua/mason-core/installer/managers/luarocks.lua
index 7a2e2b45..f40124cd 100644
--- a/lua/mason-core/installer/managers/luarocks.lua
+++ b/lua/mason-core/installer/managers/luarocks.lua
@@ -15,7 +15,7 @@ function M.install(pkg, version, opts)
opts = opts or {}
log.fmt_debug("luarocks: install %s %s %s", pkg, version, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing luarocks package %s@%s…\n"):format(pkg, version))
+ ctx.stdio_sink:stdout(("Installing luarocks package %s@%s…\n"):format(pkg, version))
ctx:promote_cwd() -- luarocks encodes absolute paths during installation
return ctx.spawn.luarocks {
"install",
diff --git a/lua/mason-core/installer/managers/npm.lua b/lua/mason-core/installer/managers/npm.lua
index df8ece35..d31fe768 100644
--- a/lua/mason-core/installer/managers/npm.lua
+++ b/lua/mason-core/installer/managers/npm.lua
@@ -50,7 +50,7 @@ function M.init()
end
end))
- ctx.stdio_sink.stdout "Initialized npm root.\n"
+ ctx.stdio_sink:stdout "Initialized npm root.\n"
end)
end
@@ -62,7 +62,7 @@ function M.install(pkg, version, opts)
opts = opts or {}
log.fmt_debug("npm: install %s %s %s", pkg, version, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing npm package %s@%s…\n"):format(pkg, version))
+ ctx.stdio_sink:stdout(("Installing npm package %s@%s…\n"):format(pkg, version))
return ctx.spawn.npm {
"install",
("%s@%s"):format(pkg, version),
@@ -74,7 +74,7 @@ end
---@param pkg string
function M.uninstall(pkg)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Uninstalling npm package %s…\n"):format(pkg))
+ ctx.stdio_sink:stdout(("Uninstalling npm package %s…\n"):format(pkg))
return ctx.spawn.npm { "uninstall", pkg }
end
diff --git a/lua/mason-core/installer/managers/nuget.lua b/lua/mason-core/installer/managers/nuget.lua
index 9f1badc7..5a4021d0 100644
--- a/lua/mason-core/installer/managers/nuget.lua
+++ b/lua/mason-core/installer/managers/nuget.lua
@@ -12,7 +12,7 @@ local M = {}
function M.install(package, version)
log.fmt_debug("nuget: install %s %s", package, version)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing nuget package %s@%s…\n"):format(package, version))
+ ctx.stdio_sink:stdout(("Installing nuget package %s@%s…\n"):format(package, version))
return ctx.spawn.dotnet {
"tool",
"update",
diff --git a/lua/mason-core/installer/managers/opam.lua b/lua/mason-core/installer/managers/opam.lua
index 875ee12b..20990953 100644
--- a/lua/mason-core/installer/managers/opam.lua
+++ b/lua/mason-core/installer/managers/opam.lua
@@ -14,7 +14,7 @@ local M = {}
function M.install(package, version)
log.fmt_debug("opam: install %s %s", package, version)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing opam package %s@%s…\n"):format(package, version))
+ ctx.stdio_sink:stdout(("Installing opam package %s@%s…\n"):format(package, version))
return ctx.spawn.opam {
"install",
"--destdir=.",
diff --git a/lua/mason-core/installer/managers/pypi.lua b/lua/mason-core/installer/managers/pypi.lua
index 85fadc9f..e12b4561 100644
--- a/lua/mason-core/installer/managers/pypi.lua
+++ b/lua/mason-core/installer/managers/pypi.lua
@@ -116,14 +116,14 @@ local function create_venv(pkg)
and not pep440_check_version(tostring(target.version), supported_python_versions)
then
if ctx.opts.force then
- ctx.stdio_sink.stderr(
+ ctx.stdio_sink:stderr(
("Warning: The resolved python3 version %s is not compatible with the required Python versions: %s.\n"):format(
target.version,
supported_python_versions
)
)
else
- ctx.stdio_sink.stderr "Run with :MasonInstall --force to bypass this version validation.\n"
+ ctx.stdio_sink:stderr "Run with :MasonInstall --force to bypass this version validation.\n"
return Result.failure(
("Failed to find a python3 installation in PATH that meets the required versions (%s). Found version: %s."):format(
supported_python_versions,
@@ -134,7 +134,7 @@ local function create_venv(pkg)
end
log.fmt_debug("Found python3 installation version=%s, executable=%s", target.version, target.executable)
- ctx.stdio_sink.stdout "Creating virtual environment…\n"
+ ctx.stdio_sink:stdout "Creating virtual environment…\n"
return ctx.spawn[target.executable] { "-m", "venv", "--system-site-packages", VENV_DIR }
end
@@ -193,7 +193,7 @@ function M.init(opts)
try(create_venv(opts.package))
if opts.upgrade_pip then
- ctx.stdio_sink.stdout "Upgrading pip inside the virtual environment…\n"
+ ctx.stdio_sink:stdout "Upgrading pip inside the virtual environment…\n"
try(pip_install({ "pip" }, opts.install_extra_args))
end
end)
@@ -207,7 +207,7 @@ function M.install(pkg, version, opts)
opts = opts or {}
log.fmt_debug("pypi: install %s %s %s", pkg, version, opts or "")
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Installing pip package %s@%s…\n"):format(pkg, version))
+ ctx.stdio_sink:stdout(("Installing pip package %s@%s…\n"):format(pkg, version))
return pip_install({
opts.extra and ("%s[%s]==%s"):format(pkg, opts.extra, version) or ("%s==%s"):format(pkg, version),
opts.extra_packages or vim.NIL,
diff --git a/lua/mason-core/installer/managers/std.lua b/lua/mason-core/installer/managers/std.lua
index b4eb11ab..701bb6c9 100644
--- a/lua/mason-core/installer/managers/std.lua
+++ b/lua/mason-core/installer/managers/std.lua
@@ -95,7 +95,7 @@ end
function M.download_file(url, out_file)
log.fmt_debug("std: downloading file %s", url, out_file)
local ctx = installer.context()
- ctx.stdio_sink.stdout(("Downloading file %q…\n"):format(url))
+ ctx.stdio_sink:stdout(("Downloading file %q…\n"):format(url))
return fetch(url, {
out_file = path.concat { ctx.cwd:get(), out_file },
}):map_err(function(err)
@@ -234,7 +234,7 @@ local unpack_by_filename = _.cond {
function M.unpack(rel_path)
log.fmt_debug("std: unpack %s", rel_path)
local ctx = installer.context()
- ctx.stdio_sink.stdout((("Unpacking %q…\n"):format(rel_path)))
+ ctx.stdio_sink:stdout((("Unpacking %q…\n"):format(rel_path)))
return unpack_by_filename(rel_path)
end
@@ -246,7 +246,7 @@ function M.clone(git_url, opts)
opts = opts or {}
log.fmt_debug("std: clone %s %s", git_url, opts)
local ctx = installer.context()
- ctx.stdio_sink.stdout((("Cloning git repository %q…\n"):format(git_url)))
+ ctx.stdio_sink:stdout((("Cloning git repository %q…\n"):format(git_url)))
return Result.try(function(try)
try(ctx.spawn.git {
"clone",
diff --git a/lua/mason-core/process.lua b/lua/mason-core/process.lua
index 1690c116..22610ef1 100644
--- a/lua/mason-core/process.lua
+++ b/lua/mason-core/process.lua
@@ -6,9 +6,82 @@ local uv = vim.loop
---@alias luv_pipe any
---@alias luv_handle any
----@class StdioSink
----@field stdout fun(chunk: string)
----@field stderr fun(chunk: string)
+---@class IStdioSink
+local IStdioSink = {}
+---@param chunk string
+function IStdioSink:stdout(chunk) end
+---@param chunk string
+function IStdioSink:stderr(chunk) end
+
+---@class StdioSink : IStdioSink
+---@field stdout_sink? fun(chunk: string)
+---@field stderr_sink? fun(chunk: string)
+local StdioSink = {}
+StdioSink.__index = StdioSink
+
+---@param opts { stdout?: fun(chunk: string), stderr?: fun(chunk: string) }
+function StdioSink:new(opts)
+ ---@type StdioSink
+ local instance = {}
+ setmetatable(instance, self)
+ instance.stdout_sink = opts.stdout
+ instance.stderr_sink = opts.stderr
+ return instance
+end
+
+---@param chunk string
+function StdioSink:stdout(chunk)
+ if self.stdout_sink then
+ self.stdout_sink(chunk)
+ end
+end
+
+---@param chunk string
+function StdioSink:stderr(chunk)
+ if self.stderr_sink then
+ self.stderr_sink(chunk)
+ end
+end
+
+---@class BufferedSink : IStdioSink
+---@field buffers { stdout: string[], stderr: string[] }
+---@field events? EventEmitter
+local BufferedSink = {}
+BufferedSink.__index = BufferedSink
+
+function BufferedSink:new()
+ ---@type BufferedSink
+ local instance = {}
+ setmetatable(instance, self)
+ instance.buffers = {
+ stdout = {},
+ stderr = {},
+ }
+ return instance
+end
+
+---@param events EventEmitter
+function BufferedSink:connect_events(events)
+ self.events = events
+end
+
+---@param chunk string
+function BufferedSink:stdout(chunk)
+ local stdout = self.buffers.stdout
+ stdout[#stdout + 1] = chunk
+ if self.events then
+ self.events:emit("stdout", chunk)
+ end
+end
+
+---@param chunk string
+function BufferedSink:stderr(chunk)
+ local stderr = self.buffers.stderr
+ stderr[#stderr + 1] = chunk
+ if self.events then
+ self.events:emit("stderr", chunk)
+ end
+end
local M = {}
@@ -91,7 +164,7 @@ end
---@field env string[]? List of "key=value" string.
---@field args string[]
---@field cwd string
----@field stdio_sink StdioSink
+---@field stdio_sink IStdioSink
---@param cmd string The command/executable.
---@param opts JobSpawnOpts
@@ -151,9 +224,9 @@ function M.spawn(cmd, opts, callback)
if handle == nil then
log.fmt_error("Failed to spawn process. cmd=%s, err=%s", cmd, pid_or_err)
if type(pid_or_err) == "string" and pid_or_err:find "ENOENT" == 1 then
- opts.stdio_sink.stderr(("Could not find executable %q in path.\n"):format(cmd))
+ opts.stdio_sink:stderr(("Could not find executable %q in path.\n"):format(cmd))
else
- opts.stdio_sink.stderr(("Failed to spawn process cmd=%s err=%s\n"):format(cmd, pid_or_err))
+ opts.stdio_sink:stderr(("Failed to spawn process cmd=%s err=%s\n"):format(cmd, pid_or_err))
end
callback(false)
return nil, nil, nil
@@ -161,42 +234,16 @@ function M.spawn(cmd, opts, callback)
log.debug("Spawned with pid", pid_or_err)
- stdout:read_start(connect_sink(stdout, opts.stdio_sink.stdout))
- stderr:read_start(connect_sink(stderr, opts.stdio_sink.stderr))
+ stdout:read_start(connect_sink(stdout, function(...)
+ opts.stdio_sink:stdout(...)
+ end))
+ stderr:read_start(connect_sink(stderr, function(...)
+ opts.stdio_sink:stderr(...)
+ end))
return handle, stdio, pid_or_err
end
-function M.empty_sink()
- local function noop() end
- return {
- stdout = noop,
- stderr = noop,
- }
-end
-
-function M.simple_sink()
- return {
- stdout = vim.schedule_wrap(vim.api.nvim_out_write),
- stderr = vim.schedule_wrap(vim.api.nvim_err_write),
- }
-end
-
-function M.in_memory_sink()
- local stdout, stderr = {}, {}
- return {
- buffers = { stdout = stdout, stderr = stderr },
- sink = {
- stdout = function(chunk)
- stdout[#stdout + 1] = chunk
- end,
- stderr = function(chunk)
- stderr[#stderr + 1] = chunk
- end,
- },
- }
-end
-
---@param luv_handle luv_handle
---@param signal integer
function M.kill(luv_handle, signal)
@@ -211,4 +258,7 @@ function M.kill(luv_handle, signal)
uv.process_kill(luv_handle, signal)
end
+M.StdioSink = StdioSink
+M.BufferedSink = BufferedSink
+
return M
diff --git a/lua/mason-core/spawn.lua b/lua/mason-core/spawn.lua
index 33af9ea4..26434bd9 100644
--- a/lua/mason-core/spawn.lua
+++ b/lua/mason-core/spawn.lua
@@ -70,10 +70,8 @@ setmetatable(spawn, {
args = cmd_args,
}
- local stdio
if not spawn_args.stdio_sink then
- stdio = process.in_memory_sink()
- spawn_args.stdio_sink = stdio.sink
+ spawn_args.stdio_sink = process.BufferedSink:new()
end
local cmd = self._aliases[normalized_cmd] or normalized_cmd
@@ -93,17 +91,30 @@ setmetatable(spawn, {
end)
if exit_code == 0 and signal == 0 then
- return Result.success {
- stdout = stdio and table.concat(stdio.buffers.stdout, "") or nil,
- stderr = stdio and table.concat(stdio.buffers.stderr, "") or nil,
- }
+ if getmetatable(spawn_args.stdio_sink) == process.BufferedSink then
+ local sink = spawn_args.stdio_sink --[[@as BufferedSink]]
+ return Result.success {
+ stdout = table.concat(sink.buffers.stdout, "") or nil,
+ stderr = table.concat(sink.buffers.stderr, "") or nil,
+ }
+ else
+ return Result.success()
+ end
else
- return Failure({
- exit_code = exit_code,
- signal = signal,
- stdout = stdio and table.concat(stdio.buffers.stdout, "") or nil,
- stderr = stdio and table.concat(stdio.buffers.stderr, "") or nil,
- }, cmd)
+ if getmetatable(spawn_args.stdio_sink) == process.BufferedSink then
+ local sink = spawn_args.stdio_sink --[[@as BufferedSink]]
+ return Failure({
+ exit_code = exit_code,
+ signal = signal,
+ stdout = table.concat(sink.buffers.stdout, "") or nil,
+ stderr = table.concat(sink.buffers.stderr, "") or nil,
+ }, cmd)
+ else
+ return Failure({
+ exit_code = exit_code,
+ signal = signal,
+ }, cmd)
+ end
end
end
end,