diff --git a/src/cli/cli.rs b/src/cli/cli.rs
index e93a991..4195b52 100644
--- a/src/cli/cli.rs
+++ b/src/cli/cli.rs
@@ -3,7 +3,7 @@ use std::fs::read_to_string;
use anyhow::Result;
use clap::{CommandFactory, Parser};
-use lune::Lune;
+use lune::run_lune;
use crate::utils::{files::find_parse_file_path, github::Client as GithubClient};
@@ -96,11 +96,7 @@ impl Cli {
// Display the file path relative to cwd with no extensions in stack traces
let file_display_name = file_path.with_extension("").display().to_string();
// Create a new lune object with all globals & run the script
- Lune::new()?
- .with_args(self.script_args)?
- .with_default_globals()?
- .run_with_name(&file_contents, &file_display_name)
- .await?;
+ run_lune(&file_display_name, &file_contents, self.script_args).await?;
Ok(())
}
}
diff --git a/src/lib/globals/mod.rs b/src/lib/globals/mod.rs
index 4ecc1c5..18515f9 100644
--- a/src/lib/globals/mod.rs
+++ b/src/lib/globals/mod.rs
@@ -9,3 +9,5 @@ pub use fs::new as new_fs;
pub use net::new as new_net;
pub use process::new as new_process;
pub use task::new as new_task;
+
+pub use task::WaitingThread as WaitingTaskThread;
diff --git a/src/lib/globals/task.rs b/src/lib/globals/task.rs
index 7c30a15..801af47 100644
--- a/src/lib/globals/task.rs
+++ b/src/lib/globals/task.rs
@@ -1,13 +1,24 @@
-use std::time::Duration;
+use std::{
+ sync::{Arc, Mutex},
+ time::Duration,
+};
-use mlua::{Function, Lua, Result, Table, Value, Variadic};
+use mlua::{Function, Lua, Result, Table, Thread, Value, Variadic};
use tokio::time;
use crate::utils::table_builder::ReadonlyTableBuilder;
const DEFAULT_SLEEP_DURATION: f32 = 1.0 / 60.0;
-pub fn new(lua: &Lua) -> Result
{
+pub struct WaitingThread<'a> {
+ is_delayed_for: Option,
+ is_deferred: Option,
+ thread: Thread<'a>,
+ args: Variadic>,
+}
+
+pub fn new<'a>(lua: &'a Lua, threads: &Arc>>>) -> Result> {
+ // TODO: Figure out how to insert into threads vec
ReadonlyTableBuilder::new(lua)?
.with_async_function(
"defer",
diff --git a/src/lib/lib.rs b/src/lib/lib.rs
index b3d539d..d5af275 100644
--- a/src/lib/lib.rs
+++ b/src/lib/lib.rs
@@ -1,4 +1,6 @@
-use anyhow::Result;
+use std::sync::{Arc, Mutex};
+
+use anyhow::{bail, Result};
use mlua::Lua;
pub mod globals;
@@ -6,63 +8,39 @@ pub mod utils;
use crate::{
globals::{new_console, new_fs, new_net, new_process, new_task},
- utils::formatting::{pretty_print_luau_error, print_label},
+ utils::formatting::{format_label, pretty_format_luau_error},
};
-pub struct Lune {
- lua: Lua,
- args: Vec,
-}
-
-impl Lune {
- pub fn new() -> Result {
- let lua = Lua::new();
- lua.sandbox(true)?;
- Ok(Self { lua, args: vec![] })
+pub async fn run_lune(name: &str, chunk: &str, args: Vec) -> Result<()> {
+ let lua = Lua::new();
+ let threads = Arc::new(Mutex::new(Vec::new()));
+ lua.sandbox(true)?;
+ // Add in all globals
+ {
+ let globals = lua.globals();
+ globals.raw_set("console", new_console(&lua)?)?;
+ globals.raw_set("fs", new_fs(&lua)?)?;
+ globals.raw_set("net", new_net(&lua)?)?;
+ globals.raw_set("process", new_process(&lua, args.clone())?)?;
+ globals.raw_set("task", new_task(&lua, &threads)?)?;
+ globals.set_readonly(true);
}
-
- pub fn with_args(mut self, args: Vec) -> Result {
- self.args = args;
- Ok(self)
- }
-
- pub fn with_default_globals(self) -> Result {
- {
- let globals = self.lua.globals();
- globals.raw_set("console", new_console(&self.lua)?)?;
- globals.raw_set("fs", new_fs(&self.lua)?)?;
- globals.raw_set("net", new_net(&self.lua)?)?;
- globals.raw_set("process", new_process(&self.lua, self.args.clone())?)?;
- globals.raw_set("task", new_task(&self.lua)?)?;
- globals.set_readonly(true);
- }
- Ok(self)
- }
-
- pub async fn run(&self, chunk: &str) -> Result<()> {
- self.handle_result(self.lua.load(chunk).exec_async().await)
- }
-
- pub async fn run_with_name(&self, chunk: &str, name: &str) -> Result<()> {
- self.handle_result(self.lua.load(chunk).set_name(name)?.exec_async().await)
- }
-
- fn handle_result(&self, result: mlua::Result<()>) -> Result<()> {
- match result {
- Ok(_) => Ok(()),
- Err(e) => {
- eprintln!();
- print_label("ERROR").unwrap();
- eprintln!();
- pretty_print_luau_error(&e);
- Err(e.into())
- }
- }
+ // Run the requested chunk asynchronously
+ let result = lua.load(chunk).set_name(name)?.exec_async().await;
+ match result {
+ Ok(_) => Ok(()),
+ Err(e) => bail!(
+ "\n{}\n{}",
+ format_label("ERROR"),
+ pretty_format_luau_error(&e)
+ ),
}
}
#[cfg(test)]
mod tests {
+ use crate::run_lune;
+
macro_rules! run_tests {
($($name:ident: $value:expr,)*) => {
$(
@@ -75,16 +53,10 @@ mod tests {
let path = std::env::current_dir()
.unwrap()
.join(format!("src/tests/{}.luau", $value));
- let lune = crate::Lune::new()
- .unwrap()
- .with_args(args)
- .unwrap()
- .with_default_globals()
- .unwrap();
let script = tokio::fs::read_to_string(&path)
.await
.unwrap();
- if let Err(e) = lune.run_with_name(&script, $value).await {
+ if let Err(e) = run_lune($value, &script, args).await {
panic!("Test '{}' failed!\n{}", $value, e.to_string())
}
}
diff --git a/src/lib/utils/formatting.rs b/src/lib/utils/formatting.rs
index b601482..08f85e5 100644
--- a/src/lib/utils/formatting.rs
+++ b/src/lib/utils/formatting.rs
@@ -39,8 +39,8 @@ fn can_be_plain_lua_table_key(s: &mlua::String) -> bool {
}
}
-pub fn print_label>(s: S) -> mlua::Result<()> {
- print!(
+pub fn format_label>(s: S) -> String {
+ format!(
"{}[{}{}{}{}]{} ",
STYLE_BOLD,
match s.as_ref().to_ascii_lowercase().as_str() {
@@ -53,7 +53,11 @@ pub fn print_label>(s: S) -> mlua::Result<()> {
COLOR_RESET,
STYLE_BOLD,
STYLE_RESET
- );
+ )
+}
+
+pub fn print_label>(s: S) -> mlua::Result<()> {
+ print!("{}", format_label(s));
flush_stdout()?;
Ok(())
}
@@ -186,34 +190,45 @@ pub fn pretty_format_multi_value(multi: &MultiValue) -> mlua::Result {
Ok(buffer)
}
-pub fn pretty_print_luau_error(e: &mlua::Error) {
+pub fn pretty_format_luau_error(e: &mlua::Error) -> String {
match e {
mlua::Error::RuntimeError(e) => {
- eprintln!("{e}");
+ let err_string = e.to_string();
+ let mut err_lines = err_string.lines().collect::>();
+ for (index, line) in err_lines.clone().iter().enumerate().rev() {
+ if *line == "stack traceback:" {
+ err_lines[index] = "Stack Begin";
+ break;
+ }
+ }
+ err_lines.push("Stack End");
+ err_lines.join("\n")
}
mlua::Error::CallbackError { cause, traceback } => {
- pretty_print_luau_error(cause.as_ref());
- eprintln!("Traceback:");
- eprintln!("{}", traceback.strip_prefix("stack traceback:\n").unwrap());
+ format!(
+ "{}\nStack Begin{}Stack End",
+ pretty_format_luau_error(cause.as_ref()),
+ traceback.strip_prefix("stack traceback:\n").unwrap()
+ )
}
mlua::Error::ToLuaConversionError { from, to, message } => {
let msg = message
.clone()
.map_or_else(String::new, |m| format!("\nDetails:\n\t{m}"));
- eprintln!(
+ format!(
"Failed to convert Rust type '{}' into Luau type '{}'!{}",
from, to, msg
- );
+ )
}
mlua::Error::FromLuaConversionError { from, to, message } => {
let msg = message
.clone()
.map_or_else(String::new, |m| format!("\nDetails:\n\t{m}"));
- eprintln!(
+ format!(
"Failed to convert Luau type '{}' into Rust type '{}'!{}",
from, to, msg
- );
+ )
}
- e => eprintln!("{e}"),
+ e => format!("{e}"),
}
}