use std::path::PathBuf; use clap::Parser; mod repl; mod sandbox; mod stdlib; /// Runs a Lua script in a customized environment, or an interactive REPL when /// no script path is given. #[derive(Parser, Debug)] #[command(version, about)] struct Args { /// Path to the Lua script to execute. Omit to start an interactive REPL. filepath: Option, } #[tokio::main] async fn main() -> Result<(), Box> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); let args = Args::parse(); let lua = sandbox::create_sandboxed_lua()?; let Some(filepath) = args.filepath else { return repl::run(&lua).await; }; let source = tokio::fs::read_to_string(&filepath).await?; // Skip a leading shebang line like stock Lua's luaL_loadfilex does (it // skips any first line starting with '#'). The newline is kept so error // messages still report correct line numbers. let chunk = if source.starts_with('#') { &source[source.find('\n').unwrap_or(source.len())..] } else { source.as_str() }; lua.load(chunk) // "@" marks the chunk name as a file path in error messages / tracebacks .set_name(format!("@{}", filepath.display())) .exec_async() .await?; Ok(()) }