diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-05-18 17:25:29 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-05-18 17:26:37 +0800 |
| commit | da5a750965dbec5a2c003faa8fb9f1dd110ccce8 (patch) | |
| tree | b793769ec40494c1ab056c65748c3393b5a849ed /mingling_core/src/program/repl_exec.rs | |
| parent | ab7c5785fb290541ad4361c0d46241817c3ff5f9 (diff) | |
Implement REPL execution with hooks and argument splitting
Diffstat (limited to 'mingling_core/src/program/repl_exec.rs')
| -rw-r--r-- | mingling_core/src/program/repl_exec.rs | 103 |
1 files changed, 99 insertions, 4 deletions
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<C> Program<C> where - C: ProgramCollect<Enum = C>, + C: ProgramCollect<Enum = C> + 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<C> Program<C> where C: ProgramCollect<Enum = C> {} +impl<C> Program<C> +where + C: ProgramCollect<Enum = C> + 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<String, std::io::Error> { + 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<C>( + p: &'static Program<C>, + args: Vec<String>, +) -> Result<RenderResult, ProgramInternalExecuteError> +where + C: ProgramCollect<Enum = C> + 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::<Program<C>>() + .unwrap(); + program.run_hook_repl_on_panic(&panic_payload); + Err(ProgramInternalExecuteError::REPLPanic(panic_payload)) + } + Ok(r) => r, + } + }; + + exec_result +} |
