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::() { 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; } } } } } } } }