worldwideportal/src/command_handler.rs

122 lines
4.6 KiB
Rust

use crate::{
echo_to_term_frame,
lua_engine::LuaState,
parsing::{parse_commands, ParsedCommand},
FrameId, GlobalMemoCell,
};
use itertools::Itertools;
use wasm_bindgen::JsValue;
use web_sys::console;
pub 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: &GlobalMemoCell,
term_frame: &FrameId,
commands_in: &[ParsedCommand],
) {
lua_state.set_current_frame(term_frame);
for command in commands_in {
match command.split_out_command() {
None => (),
Some((cmd, rest)) => {
if let ("#", command_rest) = cmd.split_at(1) {
if cmd == "##" {
match lua_state.execute(&rest.forget_guards().to_string()) {
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
}
}
} else if let Ok(repeat_count) = command_rest.parse::<u16>() {
let cmds = &[rest];
for _ in 0..repeat_count {
reentrant_command_handler(lua_state, globals, term_frame, cmds);
}
} else {
match lua_state.execute_command(command_rest, &rest) {
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
}
}
}
} else {
// A normal command. Try dispatching it to the frame object in Lua...
match lua_state
.dispatch_normal_command(term_frame, &command.arguments.iter().join(" "))
{
Ok(()) => (),
Err(msg) => {
echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
.unwrap_or(())
}
}
}
}
}
}
}
pub fn command_handler(globals: &GlobalMemoCell, term_frame: &FrameId, command_in: &str) {
echo_to_term_frame(globals, term_frame, "\r").unwrap_or(());
{
let mut cq = globals.command_queue.borrow_mut();
for cmd in parse_commands(command_in).commands {
cq.push_back((term_frame.clone(), cmd));
}
}
execute_queue(globals);
}
pub fn execute_queue(globals: &GlobalMemoCell) {
let mut steps: u64 = 0;
const STEP_LIMIT: u64 = 500;
loop {
let queue_head = globals.command_queue.borrow_mut().pop_front();
match queue_head {
None => return,
Some((frame, command_in)) => {
steps += 1;
match globals.lua_engine.try_borrow_mut() {
Err(_) => console::log_1(&JsValue::from_str(
"Can't borrow lua_engine when executing queue!",
)),
Ok(mut lua_state_m) => {
reentrant_command_handler(
&mut lua_state_m,
globals,
&frame,
&[command_in.clone()],
);
if steps > STEP_LIMIT {
let new_queue = globals.command_queue.take();
if !new_queue.is_empty() {
echo_to_term_frame(
globals,
&frame,
&format!("Executing queued actions resulted in more than {} steps. This usually means a command is creating similar commands in a loop. The following commands were dropped from the queue to stop execution: {}.",
STEP_LIMIT,
&new_queue.iter().map(
|(_fr, cmd)| cmd.to_string())
.join("; "))).unwrap_or(());
return;
}
}
}
}
}
}
}
}