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, 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( fn reentrant_command_handler(
lua_state: &mut LuaState, lua_state: &mut LuaState,
globals: &GlobalCell, globals: &GlobalCell,
@ -16,12 +25,23 @@ fn reentrant_command_handler(
match command.split_out_command() { match command.split_out_command() {
None => (), None => (),
Some((cmd, rest)) => { Some((cmd, rest)) => {
if cmd == "##" { if cmd.starts_with('#') {
match lua_state.execute(&join(rest.arguments.iter(), " ")) { if cmd == "##" {
Ok(()) => (), match lua_state.execute(debrace(&join(rest.arguments.iter(), " "))) {
Err(msg) => { Ok(()) => (),
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg)) Err(msg) => {
.unwrap_or(()) 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 anyhow::Error;
use piccolo::{ use piccolo::{
Callback, Closure, Context, Executor, FromValue, Function, IntoValue, Lua, StashedExecutor, Callback, Closure, Context, Executor, FromValue, Function, IntoValue, Lua, StashedExecutor,
StaticError, Table, StaticError, Table, Value, Variadic,
}; };
use crate::{echo_to_term_frame, GlobalCell, TermFrame}; use crate::{echo_to_term_frame, GlobalCell, TermFrame};
use std::str; use std::{collections::VecDeque, str};
pub struct LuaState { pub struct LuaState {
pub interp: Lua, pub interp: Lua,
@ -48,6 +48,35 @@ impl LuaState {
.execute::<()>(&self.exec) .execute::<()>(&self.exec)
.map_err(|err| format!("{}", err)) .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> { 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> = let commands: Table<'gc> =
Table::from_value(ctx, ctx.get_global(ctx.intern_static(b"commands")))?; 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 function = Function::from_value(ctx, commands.get(ctx, "echo_frame_raw"))?;
let message: piccolo::Value = stack.from_back(ctx)?; let frame_no: Value = stack.pop_front();
let message = ctx.intern(&format!("{}\r\n", message).as_bytes()); 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()); stack.push_back(message.into());
Ok(piccolo::CallbackReturn::Call { Ok(piccolo::CallbackReturn::Call {
function, function,

View File

@ -121,8 +121,7 @@ fn get_or_make_term_frame<'a>(
) )
}), }),
initial_size, initial_size,
) ),
.into(),
retained_closures: None, retained_closures: None,
}; };
@ -207,7 +206,7 @@ pub fn echo_to_term_frame(
.frame_registry .frame_registry
.borrow() .borrow()
.get(frame_id) .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 .term
.write(message); .write(message);
Ok(()) Ok(())