From 7071e4f6c979f0d8c40dac4715eaee745c2fdb1a Mon Sep 17 00:00:00 2001 From: Cazdotsys Date: Sat, 21 Dec 2024 16:28:32 -0500 Subject: [PATCH] ZLUA REPL!!!!! (#18) --- engine/Cargo.toml | 1 + engine/src/core/logger/mod.rs | 2 +- engine/src/core/repl/commands.rs | 103 ++++++++++++++++++++++++++++--- engine/src/core/repl/handler.rs | 1 + engine/src/core/repl/mod.rs | 7 ++- engine/src/main.rs | 5 +- 6 files changed, 106 insertions(+), 13 deletions(-) diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 82574fa..e5a9ad6 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -13,6 +13,7 @@ dirs-next = "2.0.0" lazy_static.workspace = true log = "0.4.22" +mlua = { version = "0.10.2", features = ["anyhow", "lua54", "vendored"] } once_cell = "1.20.2" parking_lot.workspace = true regex = "1.11.1" diff --git a/engine/src/core/logger/mod.rs b/engine/src/core/logger/mod.rs index 7cd8814..765f0e8 100644 --- a/engine/src/core/logger/mod.rs +++ b/engine/src/core/logger/mod.rs @@ -81,4 +81,4 @@ impl Log for DynamicLogger { let mut writer = self.writer.lock(); writer.flush().unwrap(); } -} \ No newline at end of file +} diff --git a/engine/src/core/repl/commands.rs b/engine/src/core/repl/commands.rs index 4708302..f21e58f 100644 --- a/engine/src/core/repl/commands.rs +++ b/engine/src/core/repl/commands.rs @@ -1,8 +1,11 @@ use std::{fs, path::PathBuf, str::FromStr}; - +use colored::Colorize; +use mlua::prelude::*; use anyhow::anyhow; +use mlua::{Lua, MultiValue}; use parking_lot::RwLock; use regex::Regex; +use rustyline::{error::ReadlineError, DefaultEditor}; use super::{handler::Command, input::tokenize}; use crate::core::repl::handler::COMMAND_MANAGER; @@ -187,7 +190,6 @@ impl Command for ExecFile { } } - #[derive(Default)] pub struct CounterCommand { counter: RwLock, @@ -260,10 +262,7 @@ impl Command for PanicCommmand { } } - - - -fn eval(input: String) -> Result>)>, anyhow::Error> { +fn eval(input: String) -> Result>)>, anyhow::Error> { if input.trim().is_empty() { return Err(anyhow!("Input was empty")); } @@ -290,8 +289,98 @@ fn eval(input: String) -> Result>)>, anyhow::Erro } else { None }; - evaluted.push((cmd_name.to_owned(),args)); + evaluted.push((cmd_name.to_owned(), args)); } Ok(evaluted) } +#[derive(Default)] +pub struct ZLua; + +impl Command for ZLua { + fn execute(&self, args: Option>) -> Result<(), anyhow::Error> { + let time = chrono::Local::now().format("%H:%M:%S.%3f").to_string(); + let prompt = format!("[{}/{}] {}", time, "ZLUA", ">>\t"); + let lua = Lua::new(); + let globals = lua.globals(); + let sum = lua.create_function(|_, (list1, list2): (i32, i32)| { + // This function just checks whether two string lists are equal, and in an inefficient way. + // Lua callbacks return `mlua::Result`, an Ok value is a normal return, and an Err return + // turns into a Lua 'error'. Again, any type that is convertible to Lua may be returned. + Ok(list1 == list2) + })?; + globals.set("sum", sum)?; + let log = lua.create_function(|_, (msg,): (String,)| { + println!("{}", msg); + Ok(()) + })?; + globals.set("log", log)?; + let mut editor = DefaultEditor::new().expect("Failed to create editor"); + + loop { + let mut prompt = &prompt; + let mut line = String::new(); + + loop { + match editor.readline(prompt) { + Ok(input) => line.push_str(&input), + Err(ReadlineError::Interrupted) => { + println!("Exiting ZLUA shell..."); + return Ok(()); + } + Err(_) => {} + } + + match lua.load(&line).eval::() { + Ok(values) => { + editor.add_history_entry(line).unwrap(); + println!( + "{}", + values + .iter() + .map(|value| format!("{:#?}", value)) + .collect::>() + .join("\t") + ); + break; + } + Err(mlua::Error::SyntaxError { + incomplete_input: true, + .. + }) => { + // continue reading input and append it to `line` + line.push_str("\n"); // separate input lines + prompt = prompt; + } + + Err(e) => { + eprintln!("error: {}", e); + break; + } + } + } + } + } + + fn undo(&self) {} + + fn redo(&self) {} + + fn get_description(&self) -> String { + String::from("Runs the ZLua interpreter") + } + + fn get_name(&self) -> String { + String::from("zlua") + } + + fn get_help(&self) -> String { + String::from("zlua") + } + + fn get_params(&self) -> String { + String::from("No parameters required.") + } +} + + diff --git a/engine/src/core/repl/handler.rs b/engine/src/core/repl/handler.rs index 4b7a340..d3892f7 100644 --- a/engine/src/core/repl/handler.rs +++ b/engine/src/core/repl/handler.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; + use colored::Colorize; use lazy_static::lazy_static; use parking_lot::RwLock; diff --git a/engine/src/core/repl/mod.rs b/engine/src/core/repl/mod.rs index 9e1dd63..a1d85e0 100644 --- a/engine/src/core/repl/mod.rs +++ b/engine/src/core/repl/mod.rs @@ -1,4 +1,6 @@ -use commands::{ClearCommand, CounterCommand, ExecFile, ExitCommand, HelpCommand, PanicCommmand}; +use commands::{ + ClearCommand, CounterCommand, ExecFile, ExitCommand, HelpCommand, PanicCommmand, ZLua, +}; use handler::{COMMAND_MANAGER, Category}; use crate::commands; @@ -13,7 +15,8 @@ pub fn setup() { ClearCommand, ExitCommand, CounterCommand, - PanicCommmand + PanicCommmand, + ZLua ); let cat = Category::new("cr", "Core", "Core commands"); COMMAND_MANAGER.write().add_category(cat.clone()); diff --git a/engine/src/main.rs b/engine/src/main.rs index ccd41b9..80dbecd 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -5,8 +5,8 @@ use core::{ splash, workspace, }; -use anyhow::Ok; use colored::Colorize; +use mlua::Lua; use tokio::runtime; pub mod core; @@ -26,9 +26,8 @@ fn main() -> anyhow::Result<()> { COMMAND_MANAGER.read().execute("help", None)?; let t = tokio::spawn(core::repl::input::handle_repl()); t.await??; - Ok(()) + Ok::<(), anyhow::Error>(()) })?; Ok(()) - }