From da5a750965dbec5a2c003faa8fb9f1dd110ccce8 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 18 May 2026 17:25:29 +0800 Subject: Implement REPL execution with hooks and argument splitting --- mingling_core/src/program/repl_exec.rs | 103 +++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) (limited to 'mingling_core/src/program/repl_exec.rs') diff --git a/mingling_core/src/program/repl_exec.rs b/mingling_core/src/program/repl_exec.rs index feeaad9..c182f78 100644 --- a/mingling_core/src/program/repl_exec.rs +++ b/mingling_core/src/program/repl_exec.rs @@ -1,12 +1,107 @@ -use crate::{Program, ProgramCollect}; +use std::io::Write; + +mod splitter; + +use crate::error::{ProgramInternalExecuteError, ProgramPanic}; +use crate::program::repl_exec::splitter::split_input_string; +use crate::{Program, ProgramCollect, RenderResult}; #[cfg(not(feature = "async"))] impl Program where - C: ProgramCollect, + C: ProgramCollect + Send + Sync + 'static, { - pub fn exec_repl(self) {} + pub fn exec_repl(self) { + self.run_hook_repl_on_begin(); + + self.exec_wrapper(|p| -> ! { + loop { + let args = split_input_string(readline_or_empty()); + match exec_once(p, args) { + Ok(r) => { + p.run_hook_repl_on_receive_result(&r); + } + Err(ProgramInternalExecuteError::REPLPanic(panic)) => { + p.run_hook_repl_on_panic(&panic); + } + _ => {} + } + } + }); + } } #[cfg(feature = "async")] -impl Program where C: ProgramCollect {} +impl Program +where + C: ProgramCollect + Send + Sync, +{ + pub async fn exec_repl(self) { + self.run_hook_repl_on_begin(); + + self.exec_wrapper(|p| -> ! { + loop { + let args = split_input_string(readline_or_empty()); + match exec_once(p, args) { + Ok(r) => { + p.run_hook_repl_on_receive_result(&r); + } + Err(ProgramInternalExecuteError::REPLPanic(panic)) => { + p.run_hook_repl_on_panic(&panic); + } + _ => {} + } + } + }) + .await; + } +} + +fn readline() -> Result { + let mut input = String::new(); + std::io::stdout().flush()?; + std::io::stdin().read_line(&mut input)?; + Ok(input.trim().to_string()) +} + +fn readline_or_empty() -> String { + readline().unwrap_or("".to_string()) +} + +fn exec_once( + p: &'static Program, + args: Vec, +) -> Result +where + C: ProgramCollect + Send + Sync + 'static, +{ + #[cfg(panic = "abort")] + let exec_result = super::exec::exec_with_args(p, args); + + #[cfg(not(panic = "abort"))] + let exec_result = { + let exec_unwind_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + super::exec::exec_with_args(p, args) + })); + + match exec_unwind_result { + Err(panic_info) => { + let panic_payload = ProgramPanic { + payload: panic_info, + }; + let program = crate::program::THIS_PROGRAM + .get() + .unwrap() + .as_ref() + .unwrap() + .downcast_ref::>() + .unwrap(); + program.run_hook_repl_on_panic(&panic_payload); + Err(ProgramInternalExecuteError::REPLPanic(panic_payload)) + } + Ok(r) => r, + } + }; + + exec_result +} -- cgit