diff --git a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs index c4e1ea1078..ca3f164c61 100644 --- a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs +++ b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs @@ -51,7 +51,13 @@ namespace BizHawk.Client.Common void SpawnAndSetFileThread(string pathToLoad, LuaFile lf); - void ExecuteString(string command); + /// + /// Executes Lua code. Automatically prepends statement if possible. + /// + /// + /// Values returned by the Lua script, if any. + /// + object[] ExecuteString(string command); (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index f2b7fc07be..1e13fe4e10 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1373,7 +1373,6 @@ namespace BizHawk.Client.EmuHawk { if (e.KeyCode == Keys.Enter) { - string consoleBeforeCall = OutputBox.Text; var rawCommand = InputBox.Text; InputBox.Clear(); InputBox.Refresh(); // if the command is something like `client.seekframe`, the Lua Console (and MainForm) will freeze until it finishes, so at least make it obvious that the Enter press was received @@ -1388,18 +1387,15 @@ namespace BizHawk.Client.EmuHawk LuaSandbox.Sandbox(null, () => { - LuaImp.ExecuteString($"console.log({rawCommand})"); - }, () => - { - LuaSandbox.Sandbox(null, () => + var prevMessageCount = _messageCount; + var results = LuaImp.ExecuteString(rawCommand); + // empty array if the command was e.g. a variable assignment or a loop without return statement + // "void" functions return a single null + // if output didn't change, Print will take care of writing out "(no return)" + if (results is not ([ ] or [ null ]) || _messageCount == prevMessageCount) { - LuaImp.ExecuteString(rawCommand); - - if (OutputBox.Text == consoleBeforeCall) - { - WriteLine("Command successfully executed"); - } - }); + LuaLibraries.Print(results); + } }); _messageCount = 0; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs index 8e0cb22239..5ac0a3922f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs @@ -323,8 +323,29 @@ namespace BizHawk.Client.EmuHawk public void SpawnAndSetFileThread(string pathToLoad, LuaFile lf) => lf.Thread = SpawnCoroutine(pathToLoad); - public void ExecuteString(string command) - => _lua.DoString(command); + public object[] ExecuteString(string command) + { + const string ChunkName = "input"; // shows up in error messages + + // Use LoadString to separate parsing and execution, to tell syntax errors and runtime errors apart + LuaFunction func; + try + { + // Adding a return is necessary to get out return values of functions and turn expressions ("1+1" etc.) into valid statements + func = _lua.LoadString($"return {command}", ChunkName); + } + catch (Exception) + { + // command may be a valid statement without the added "return" + // if previous attempt couldn't be parsed, run the raw command + return _lua.DoString(command, ChunkName); + } + + using (func) + { + return func.Call(); + } + } public (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf) {