Allow defining commands in Lua, and executing them.
This commit is contained in:
		
							parent
							
								
									fae004f76c
								
							
						
					
					
						commit
						c2bd680299
					
				@ -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(())
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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(())
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user