From 753897222ab8b02101d483d3d88384b6a992771d Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Thu, 18 Apr 2024 22:10:08 +0200 Subject: [PATCH] Implement stdio.readToEnd API --- src/lune/builtins/stdio/mod.rs | 18 +++++++++++++++++- types/stdio.luau | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/lune/builtins/stdio/mod.rs b/src/lune/builtins/stdio/mod.rs index 14927f2..f851bc7 100644 --- a/src/lune/builtins/stdio/mod.rs +++ b/src/lune/builtins/stdio/mod.rs @@ -2,7 +2,7 @@ use mlua::prelude::*; use dialoguer::{theme::ColorfulTheme, Confirm, Input, MultiSelect, Select}; use mlua_luau_scheduler::LuaSpawnExt; -use tokio::io::{self, AsyncWriteExt}; +use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; use crate::lune::util::{ formatting::{ @@ -21,6 +21,7 @@ pub fn create(lua: &Lua) -> LuaResult> { .with_function("format", stdio_format)? .with_async_function("write", stdio_write)? .with_async_function("ewrite", stdio_ewrite)? + .with_async_function("readToEnd", stdio_read_to_end)? .with_async_function("prompt", stdio_prompt)? .build_readonly() } @@ -53,6 +54,21 @@ async fn stdio_ewrite(_: &Lua, s: LuaString<'_>) -> LuaResult<()> { Ok(()) } +/* + FUTURE: Figure out how to expose some kind of "readLine" function using a buffered reader. + + This is a bit tricky since we would want to be able to use **both** readLine and readToEnd + in the same script, doing something like readLine, readLine, readToEnd from lua, and + having that capture the first two lines and then read the rest of the input. +*/ + +async fn stdio_read_to_end(lua: &Lua, _: ()) -> LuaResult { + let mut input = Vec::new(); + let mut stdin = io::stdin(); + stdin.read_to_end(&mut input).await?; + lua.create_string(&input) +} + async fn stdio_prompt(lua: &Lua, options: PromptOptions) -> LuaResult { lua.spawn_blocking(move || prompt(options)) .await diff --git a/types/stdio.luau b/types/stdio.luau index 3c5198e..70a73e0 100644 --- a/types/stdio.luau +++ b/types/stdio.luau @@ -58,6 +58,11 @@ end stdio.write("World! ") stdio.write("All on the same line") stdio.ewrite("\nAnd some error text, too") + + -- Reading from stdin, either line-by-line or the entire input + local firstLine = stdio.readLine() + local secondLine = stdio.readLine() + local remaining = stdio.readToEnd() ``` ]=] local stdio = {} @@ -143,4 +148,16 @@ function stdio.write(s: string) end ]=] function stdio.ewrite(s: string) end +--[=[ + @within Stdio + @tag must_use + + Reads the entire input from stdin. + + @return The input from stdin +]=] +function stdio.readToEnd(): string + return nil :: any +end + return stdio