feat(process): close method

This commit is contained in:
Rónán Carrigan 2024-04-02 15:14:54 +01:00
parent 33c62b3ead
commit 173f285eeb
3 changed files with 59 additions and 12 deletions

View file

@ -81,7 +81,7 @@ result, with the same signature as the callback for `nio.run`.
This is useful for APIs where users don't want to create async
contexts but which are still used in async contexts internally.
Parameters~
{func} `(async fun(...))`
{func} `(async)` function
{argc?} `(integer)` The number of arguments of func. Must be included if there
are arguments.
@ -403,13 +403,15 @@ Fields~
{pid} `(integer)` ID of the invoked process
{signal} `(fun(signal: integer|uv.aliases.signals))` Send a signal to the
process
{result} `(async fun(): number)` Wait for the process to exit and return the
exit code
{result} `(async fun(close: boolean): number,(string|nil)[])` Wait for the
process to exit and return the exit code, optionally closing all streams.
{stdin} `(nio.streams.OSStreamWriter)` Stream to write to the process stdin.
{stdout} `(nio.streams.OSStreamReader)` Stream to read from the process
stdout.
{stderr} `(nio.streams.OSStreamReader)` Stream to read from the process
stderr.
{close} `(async fun():(string|nil)[])` Close all streams, returning any errors
that occurred.
*nio.process.run()*
`run`({opts})
@ -422,6 +424,8 @@ Run a process asynchronously.
local output = second.stdout.read()
print(output)
process.close()
<
Processes can be chained together, passing output of one process as input to
@ -437,6 +441,9 @@ another.
local output = second.stdout.read()
print(output)
first.close()
second.close()
<
The stdio fields can also be file objects.
@ -454,6 +461,8 @@ The stdio fields can also be file objects.
local output = file.read(nil, 0)
print(output)
process.close() -- Closes the file
<
Parameters~
{opts} `(nio.process.RunOpts)`

View file

@ -11,10 +11,11 @@ nio.process = {}
---@class nio.process.Process
---@field pid integer ID of the invoked process
---@field signal fun(signal: integer|uv.aliases.signals) Send a signal to the process
---@field result async fun(): number Wait for the process to exit and return the exit code
---@field result async fun(close: boolean): number,(string|nil)[] Wait for the process to exit and return the exit code, optionally closing all streams.
---@field stdin nio.streams.OSStreamWriter Stream to write to the process stdin.
---@field stdout nio.streams.OSStreamReader Stream to read from the process stdout.
---@field stderr nio.streams.OSStreamReader Stream to read from the process stderr.
---@field close async fun():(string|nil)[] Close all streams, returning any errors that occurred.
--- Run a process asynchronously.
--- ```lua
@ -24,6 +25,8 @@ nio.process = {}
---
--- local output = second.stdout.read()
--- print(output)
---
--- process.close()
--- ```
---
--- Processes can be chained together, passing output of one process as input to
@ -39,6 +42,9 @@ nio.process = {}
---
--- local output = second.stdout.read()
--- print(output)
---
--- first.close()
--- second.close()
--- ```
---
--- The stdio fields can also be file objects.
@ -56,6 +62,8 @@ nio.process = {}
---
--- local output = file.read(nil, 0)
--- print(output)
---
--- process.close() -- Closes the file
--- ```
---@param opts nio.process.RunOpts
---@return nio.process.Process? Process object for the running process
@ -114,7 +122,8 @@ function nio.process.run(opts)
end
---@type nio.process.Process
local process = {
local process
process = {
pid = pid_or_error,
signal = function(signal)
vim.loop.process_kill(handle, signal)
@ -134,7 +143,17 @@ function nio.process.run(opts)
fd = stderr_fd,
close = stderr.close,
},
result = exit_code_future.wait,
result = function(close)
local result = exit_code_future.wait()
local errors = {}
if close then
errors = process.close()
end
return result, errors
end,
close = function()
return { stdin.close(), stdout.close(), stderr.close() }
end,
}
return process
end

View file

@ -196,17 +196,36 @@ describe("process", function()
end)
a.it("returns exit code", function()
local pipe = assert(vim.loop.new_pipe())
local process = assert(nio.process.run({
cmd = "bash",
args = { "-c", "exit 1" },
stdin = pipe,
}))
process.signal(15)
local exit_code = process.result()
assert.equal(0, exit_code)
assert.equal(1, exit_code)
end)
a.it("with returns exit code", function()
local process = assert(nio.process.run({
cmd = "bash",
args = { "-c", "exit 1" },
}))
local exit_code = process.with(function() end)
assert.equal(1, exit_code)
end)
a.it("with closes streams", function()
local process = assert(nio.process.run({
cmd = "echo",
args = { "test" },
}))
process.with(function() end)
local stdout, stdout_err = process.stdout.read()
assert.equal("", stdout)
assert.Not.Nil(stdout_err)
end)
end)