Allow defining commands in Lua, and executing them.

This commit is contained in:
Condorra 2024-08-17 23:19:41 +10:00
parent fae004f76c
commit c2bd680299
3 changed files with 67 additions and 13 deletions

View File

@ -4,6 +4,15 @@ use crate::{
echo_to_term_frame, lua_state::LuaState, parsing::parse_commands, GlobalCell, TermFrame,
};
fn debrace(inp: &str) -> &str {
let v = inp.trim();
if v.starts_with("{") && v.ends_with("}") {
&v[1..(v.len() - 1)]
} else {
v
}
}
fn reentrant_command_handler(
lua_state: &mut LuaState,
globals: &GlobalCell,
@ -16,12 +25,23 @@ fn reentrant_command_handler(
match command.split_out_command() {
None => (),
Some((cmd, rest)) => {
if cmd == "##" {
match lua_state.execute(&join(rest.arguments.iter(), " ")) {
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
if cmd.starts_with('#') {
if cmd == "##" {
match lua_state.execute(debrace(&join(rest.arguments.iter(), " "))) {
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
}
}
} else {
let cmd = &cmd[1..];
match lua_state.execute_command(cmd, &rest.arguments) {
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
}
}
}
}

View File

@ -1,11 +1,11 @@
use anyhow::Error;
use piccolo::{
Callback, Closure, Context, Executor, FromValue, Function, IntoValue, Lua, StashedExecutor,
StaticError, Table,
StaticError, Table, Value, Variadic,
};
use crate::{echo_to_term_frame, GlobalCell, TermFrame};
use std::str;
use std::{collections::VecDeque, str};
pub struct LuaState {
pub interp: Lua,
@ -48,6 +48,35 @@ impl LuaState {
.execute::<()>(&self.exec)
.map_err(|err| format!("{}", err))
}
pub fn execute_command(
&mut self,
command: &str,
arguments: &VecDeque<&str>,
) -> Result<(), String> {
self.interp
.try_enter(|ctx| {
let commands =
Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"commands")))?;
let command_fn =
Function::from_value(ctx, commands.get(ctx, ctx.intern(command.as_bytes())))?;
ctx.fetch(&self.exec).restart(
ctx,
command_fn,
Variadic(
arguments
.iter()
.map(|s| ctx.intern(s.as_bytes()).into())
.collect::<Vec<Value>>(),
),
);
Ok(())
})
.map_err(|err| format!("{}", err))?;
self.interp
.execute::<()>(&self.exec)
.map_err(|err| format!("{}", err))
}
}
pub fn install_lua_globals(global: &GlobalCell) -> Result<(), String> {
@ -105,8 +134,14 @@ fn echo_frame<'gc>(ctx: Context<'gc>, _global: GlobalCell) -> Callback<'gc> {
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());
let frame_no: Value = stack.pop_front();
let all_parts: Vec<String> = stack
.consume::<Variadic<Vec<Value>>>(ctx)?
.into_iter()
.map(|v| format!("{}", v))
.collect();
stack.push_front(frame_no);
let message = ctx.intern((all_parts.join(" ") + "\r\n").as_bytes());
stack.push_back(message.into());
Ok(piccolo::CallbackReturn::Call {
function,

View File

@ -121,8 +121,7 @@ fn get_or_make_term_frame<'a>(
)
}),
initial_size,
)
.into(),
),
retained_closures: None,
};
@ -207,7 +206,7 @@ pub fn echo_to_term_frame(
.frame_registry
.borrow()
.get(frame_id)
.ok_or_else(|| "Attempt to echo to frame that doesn't exist.")?
.ok_or("Attempt to echo to frame that doesn't exist.")?
.term
.write(message);
Ok(())