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

View file

@ -11,10 +11,11 @@ nio.process = {}
---@class nio.process.Process ---@class nio.process.Process
---@field pid integer ID of the invoked process ---@field pid integer ID of the invoked process
---@field signal fun(signal: integer|uv.aliases.signals) Send a signal to the 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 stdin nio.streams.OSStreamWriter Stream to write to the process stdin.
---@field stdout nio.streams.OSStreamReader Stream to read from the process stdout. ---@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 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. --- Run a process asynchronously.
--- ```lua --- ```lua
@ -24,6 +25,8 @@ nio.process = {}
--- ---
--- local output = second.stdout.read() --- local output = second.stdout.read()
--- print(output) --- print(output)
---
--- process.close()
--- ``` --- ```
--- ---
--- Processes can be chained together, passing output of one process as input to --- Processes can be chained together, passing output of one process as input to
@ -39,6 +42,9 @@ nio.process = {}
--- ---
--- local output = second.stdout.read() --- local output = second.stdout.read()
--- print(output) --- print(output)
---
--- first.close()
--- second.close()
--- ``` --- ```
--- ---
--- The stdio fields can also be file objects. --- The stdio fields can also be file objects.
@ -56,6 +62,8 @@ nio.process = {}
--- ---
--- local output = file.read(nil, 0) --- local output = file.read(nil, 0)
--- print(output) --- print(output)
---
--- process.close() -- Closes the file
--- ``` --- ```
---@param opts nio.process.RunOpts ---@param opts nio.process.RunOpts
---@return nio.process.Process? Process object for the running process ---@return nio.process.Process? Process object for the running process
@ -114,7 +122,8 @@ function nio.process.run(opts)
end end
---@type nio.process.Process ---@type nio.process.Process
local process = { local process
process = {
pid = pid_or_error, pid = pid_or_error,
signal = function(signal) signal = function(signal)
vim.loop.process_kill(handle, signal) vim.loop.process_kill(handle, signal)
@ -134,7 +143,17 @@ function nio.process.run(opts)
fd = stderr_fd, fd = stderr_fd,
close = stderr.close, 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 return process
end end

View file

@ -196,17 +196,36 @@ describe("process", function()
end) end)
a.it("returns exit code", function() a.it("returns exit code", function()
local pipe = assert(vim.loop.new_pipe())
local process = assert(nio.process.run({ local process = assert(nio.process.run({
cmd = "bash", cmd = "bash",
args = { "-c", "exit 1" }, args = { "-c", "exit 1" },
stdin = pipe,
})) }))
process.signal(15)
local exit_code = process.result() 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)
end) end)