From 78a3d4db5f621a09a713048ac155daa8d40b3115 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Sun, 9 Jun 2024 16:13:38 +0530 Subject: [PATCH] chore(types): include types for new process.spawn --- crates/lune-std-process/src/lib.rs | 1 + crates/lune-std-process/src/stream.rs | 3 + types/process.luau | 128 ++++++++++++++++++++++++-- 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/crates/lune-std-process/src/lib.rs b/crates/lune-std-process/src/lib.rs index e8b64e4..cc88cce 100644 --- a/crates/lune-std-process/src/lib.rs +++ b/crates/lune-std-process/src/lib.rs @@ -221,6 +221,7 @@ async fn process_spawn( .expect("ExitCode receiver was unexpectedly dropped"); }); + // TODO: If not piped, don't return readers and writers instead of panicking TableBuilder::new(lua)? .with_value( "stdout", diff --git a/crates/lune-std-process/src/stream.rs b/crates/lune-std-process/src/stream.rs index 9a67e0e..74b3106 100644 --- a/crates/lune-std-process/src/stream.rs +++ b/crates/lune-std-process/src/stream.rs @@ -19,6 +19,9 @@ impl ChildProcessReader { } pub async fn read_to_end(&mut self) -> LuaResult> { + // FIXME: This yields, but should rather only return the stdout + // till present moment instead, so we should have our own logic + // instead of using read_to_end let mut buf = vec![]; self.0.read_to_end(&mut buf).await?; Ok(buf) diff --git a/types/process.luau b/types/process.luau index 97fe1ee..d6924cd 100644 --- a/types/process.luau +++ b/types/process.luau @@ -5,6 +5,9 @@ export type SpawnOptionsStdioKind = "default" | "inherit" | "forward" | "none" export type SpawnOptionsStdio = { stdout: SpawnOptionsStdioKind?, stderr: SpawnOptionsStdioKind?, +} + +export type ExecuteOptionsStdio = SpawnOptionsStdio & { stdin: string?, } @@ -12,26 +15,110 @@ export type SpawnOptionsStdio = { @interface SpawnOptions @within Process - A dictionary of options for `process.exec`, with the following available values: + A dictionary of options for `process.spawn`, with the following available values: * `cwd` - The current working directory for the process * `env` - Extra environment variables to give to the process * `shell` - Whether to run in a shell or not - set to `true` to run using the default shell, or a string to run using a specific shell * `stdio` - How to treat output and error streams from the child process - see `SpawnOptionsStdioKind` and `SpawnOptionsStdio` for more info - * `stdin` - Optional standard input to pass to spawned child process ]=] export type SpawnOptions = { cwd: string?, env: { [string]: string }?, shell: (boolean | string)?, - stdio: (SpawnOptionsStdioKind | SpawnOptionsStdio)?, + stdio: (SpawnOptionsStdio | SpawnOptionsStdioKind)?, +} + +--[=[ + @interface ExecuteOptions + @within Process + + A dictionary of options for `process.exec`, with the following available values: + + * `cwd` - The current working directory for the process + * `env` - Extra environment variables to give to the process + * `shell` - Whether to run in a shell or not - set to `true` to run using the default shell, or a string to run using a specific shell + * `stdio` - How to treat output and error streams from the child process - see `SpawnOptionsStdioKind` and `ExecuteOptionsStdio` for more info + * `stdin` - Optional standard input to pass to executed child process +]=] +export type ExecuteOptions = SpawnOptions & { stdin: string?, -- TODO: Remove this since it is now available in stdio above, breaking change } +--[=[ + @class ChildProcessReader + @within Process + + A reader class to read data from a child process' streams in realtime. +]=] +local ChildProcessReader = {} + +--[=[ + @within ChildProcessReader + + Reads a chunk of data (8 bytes at a time) from the reader into a buffer. + Returns a buffer of size 0 if there is no more data to read. + + @return The buffer containing the data read from the reader +]=] +function ChildProcessReader:read(): buffer + return nil :: any +end + +--[=[ + @within ChildProcessReader + + Reads all the data currently present in the reader into a buffer. + + @return The buffer containing the data read from the reader +]=] +function ChildProcessReader:readToEnd(): buffer + return nil :: any +end + +--[=[ + @class ChildProcessWriter + @within Process + + A writer class to write data to a child process' streams in realtime. +]=] +local ChildProcessWriter = {} + +--[=[ + @within ChildProcessWriter + + Writes a buffer or string of data to the writer. + + @param data The data to write to the writer +]=] +function ChildProcessWriter:write(data: buffer | string): () + return nil :: any +end + --[=[ @interface SpawnResult @within Process + Result type for child processes in `process.spawn`. + + This is a dictionary containing the following values: + + * `stdin` - A writer to write to the child process' stdin - see `ChildProcessWriter` for more info + * `stdout` - A reader to read from the child process' stdout - see `ChildProcessReader` for more info + * `stderr` - A reader to read from the child process' stderr - see `ChildProcessReader` for more info + * `status` - A function that yields and returns the exit status of the child process +]=] +export type ChildProcess = { + stdin: typeof(ChildProcessWriter), + stdout: typeof(ChildProcessReader), + stderr: typeof(ChildProcessReader), + status: () -> { ok: boolean, code: number } +} + +--[=[ + @interface ExecuteResult + @within Process + Result type for child processes in `process.exec`. This is a dictionary containing the following values: @@ -41,7 +128,7 @@ export type SpawnOptions = { * `stdout` - The full contents written to stdout by the child process, or an empty string if nothing was written * `stderr` - The full contents written to stderr by the child process, or an empty string if nothing was written ]=] -export type SpawnResult = { +export type ExecuteResult = { ok: boolean, code: number, stdout: string, @@ -73,7 +160,7 @@ export type SpawnResult = { -- Getting the current os and processor architecture print("Running " .. process.os .. " on " .. process.arch .. "!") - -- Spawning a child process + -- Executeing a child process local result = process.exec("program", { "cli argument", "other cli argument" @@ -163,19 +250,44 @@ end --[=[ @within Process - Spawns a child process that will run the program `program`, and returns a dictionary that describes the final status and ouput of the child process. + Spawns a child process in the background that runs the program `program`, and immediately returns + readers and writers to communicate with it. + + In order to execute a command and wait for its output, see `process.exec`. The second argument, `params`, can be passed as a list of string parameters to give to the program. The third argument, `options`, can be passed as a dictionary of options to give to the child process. Refer to the documentation for `SpawnOptions` for specific option keys and their values. - @param program The program to spawn as a child process + @param program The program to Execute as a child process + @param params Additional parameters to pass to the program + @param options A dictionary of options for the child process + @return A dictionary with the readers and writers to communicate with the child process +]=] +function process.spawn(program: string, params: { string }?, options: SpawnOptions?): ChildProcess + return nil :: any +end + +--[=[ + @within Process + + Executes a child process that will execute the command `program`, waiting for it to exit. + Upon exit, it returns a dictionary that describes the final status and ouput of the child process. + + In order to spawn a child process in the background, see `process.spawn`. + + The second argument, `params`, can be passed as a list of string parameters to give to the program. + + The third argument, `options`, can be passed as a dictionary of options to give to the child process. + Refer to the documentation for `ExecuteOptions` for specific option keys and their values. + + @param program The program to Execute as a child process @param params Additional parameters to pass to the program @param options A dictionary of options for the child process @return A dictionary representing the result of the child process ]=] -function process.exec(program: string, params: { string }?, options: SpawnOptions?): SpawnResult +function process.exec(program: string, params: { string }?, options: ExecuteOptions?): ExecuteResult return nil :: any end