aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/program/repl_exec.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-05-18 17:25:29 +0800
committer魏曹先生 <1992414357@qq.com>2026-05-18 17:26:37 +0800
commitda5a750965dbec5a2c003faa8fb9f1dd110ccce8 (patch)
treeb793769ec40494c1ab056c65748c3393b5a849ed /mingling_core/src/program/repl_exec.rs
parentab7c5785fb290541ad4361c0d46241817c3ff5f9 (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.rs103
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
+}