Implement echo to current frame + raw echo without CRLF

This commit is contained in:
Condorra 2024-08-17 21:36:15 +10:00
parent 1738cb1f80
commit 972b7c0cab
2 changed files with 71 additions and 9 deletions

View File

@ -11,6 +11,7 @@ fn reentrant_command_handler(
command_in: &str,
) {
echo_to_term_frame(globals, term_frame, "\r").unwrap_or(());
lua_state.set_current_frame(term_frame);
for command in parse_commands(command_in).commands {
match command.split_out_command() {
None => (),

View File

@ -1,5 +1,8 @@
use anyhow::Error;
use piccolo::{Callback, Closure, Context, Executor, IntoValue, Lua, StashedExecutor, Table};
use piccolo::{
Callback, Closure, Context, Executor, FromValue, Function, IntoValue, Lua, StashedExecutor,
StaticError, Table,
};
use crate::{echo_to_term_frame, GlobalCell, TermFrame};
use std::str;
@ -18,6 +21,20 @@ impl LuaState {
Ok(LuaState { interp, exec })
}
fn try_set_current_frame(&mut self, frame: &TermFrame) -> Result<(), StaticError> {
self.interp.try_enter(|ctx| {
let info_table = Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"info")))?;
info_table.set(ctx, ctx.intern_static(b"current_frame"), frame.0 as i64)?;
Ok(())
})
}
pub fn set_current_frame(&mut self, frame: &TermFrame) {
// We silently ignore errors here. Failure can happen if the Lua code does weird things
// like messes with the info global, so better to just ignore.
self.try_set_current_frame(frame).unwrap_or(())
}
pub fn execute(&mut self, command: &str) -> Result<(), String> {
self.interp
.try_enter(|ctx| {
@ -40,16 +57,30 @@ pub fn install_lua_globals(global: &GlobalCell) -> Result<(), String> {
.interp
.try_enter(|ctx| {
let cmd_table = Table::new(&ctx);
macro_rules! register_command {
($sym: ident) => {
cmd_table
.set(
ctx,
ctx.intern_static(b"echo_frame"),
echo_frame(ctx, global.clone()),
ctx.intern_static(stringify!($sym).as_bytes()),
$sym(ctx, global.clone()),
)
.map_err(|_| Error::msg("Can't add command"))?;
};
}
register_command!(echo_frame_raw);
register_command!(echo_frame);
register_command!(echo);
ctx.set_global(ctx.intern_static(b"commands").into_value(ctx), cmd_table)
.map(|_| ())
.map_err(|_| Error::msg("Can't set commands key"))?;
let info_table = Table::new(&ctx);
ctx.set_global(ctx.intern_static(b"info").into_value(ctx), info_table)
.map(|_| ())
.map_err(|_| Error::msg("Can't set info key"))?;
Ok(())
})
.map_err(|e| e.to_string())?;
@ -57,7 +88,7 @@ pub fn install_lua_globals(global: &GlobalCell) -> Result<(), String> {
Ok(())
}
fn echo_frame(ctx: Context, global: GlobalCell) -> Callback {
fn echo_frame_raw(ctx: Context, global: GlobalCell) -> Callback {
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
let frame_no: u64 = stack.from_front(ctx)?;
let message: piccolo::String = stack.from_front(ctx)?;
@ -68,3 +99,33 @@ fn echo_frame(ctx: Context, global: GlobalCell) -> Callback {
Ok(piccolo::CallbackReturn::Return)
})
}
fn echo_frame<'gc>(ctx: Context<'gc>, _global: GlobalCell) -> Callback<'gc> {
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
let commands: Table<'gc> =
Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"commands")))?;
let function = Function::from_value(ctx, commands.get(ctx, "echo_frame_raw"))?;
let message: piccolo::Value = stack.from_back(ctx)?;
let message = ctx.intern(&format!("{}\r\n", message).as_bytes());
stack.push_back(message.into());
Ok(piccolo::CallbackReturn::Call {
function,
then: None,
})
})
}
fn echo<'gc>(ctx: Context<'gc>, _global: GlobalCell) -> Callback<'gc> {
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
let commands: Table<'gc> =
Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"commands")))?;
let function = Function::from_value(ctx, commands.get(ctx, "echo_frame"))?;
let info: Table<'gc> = Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"info")))?;
let cur_frame = info.get(ctx, ctx.intern_static(b"current_frame"));
stack.push_front(cur_frame);
Ok(piccolo::CallbackReturn::Call {
function,
then: None,
})
})
}