From 10bc4ca7a4b3f14cfb57bf72a6da8aaa1490acf3 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 9 May 2026 16:42:50 +0800 Subject: Add lifecycle hooks to program execution --- mingling_core/src/program/exec.rs | 114 +++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 14 deletions(-) (limited to 'mingling_core/src/program/exec.rs') diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index 001b250..acd1bd6 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -13,19 +13,31 @@ pub async fn exec( program: &'static Program, ) -> Result where - C: ProgramCollect, + C: ProgramCollect + std::fmt::Display, { + // Run hooks + program.run_hook_on_begin(); + program.run_hook_pre_dispatch(&program.args); + #[cfg(not(feature = "dispatch_tree"))] let mut current = dispatch_args_dynamic(program, &program.args)?; #[cfg(feature = "dispatch_tree")] let mut current = C::dispatch_args_trie(&program.args)?; + // Run hook + program.run_hook_post_dispatch(¤t.member_id); + let mut stop_next = false; // If the program has Help enabled, skip actual logic and jump to Help if program.user_context.help { - return Ok(render_help::(program, current)); + let mut render_result = render_help::(program, current); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); } loop { @@ -34,17 +46,42 @@ where current = { // If a chain exists, execute as a chain if C::has_chain(¤t) { + // Run hook + program.run_hook_pre_chain(¤t.member_id, current.inner.as_ref()); + match C::do_chain(current).await { ChainProcess::Ok((any, Next::Renderer)) => { - return Ok(render::(program, any)); + let mut render_result = render::(program, any); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); + } + ChainProcess::Ok((any, Next::Chain)) => { + // Run hook + program.run_hook_post_chain(&any); + any + } + ChainProcess::Err(e) => { + // Run hook + program.run_hook_finish(); + return Err(e.into()); } - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), } } // If no chain exists, attempt to render else if C::has_renderer(¤t) { - return Ok(render::(program, current)); + // Run hook + program.run_hook_pre_render(¤t.member_id, current.inner.as_ref()); + + let mut render_result = render::(program, current); + + // Run hooks + program.run_hook_post_render(&render_result); + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); } // No renderer exists else { @@ -57,25 +94,42 @@ where break; } } - Ok(RenderResult::default()) + let mut render_result = RenderResult::default(); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + Ok(render_result) } #[cfg(not(feature = "async"))] pub fn exec(program: &'static Program) -> Result where - C: ProgramCollect, + C: ProgramCollect + std::fmt::Display, { + // Run hooks + program.run_hook_on_begin(); + program.run_hook_pre_dispatch(&program.args); + #[cfg(not(feature = "dispatch_tree"))] let mut current = dispatch_args_dynamic(program, &program.args)?; #[cfg(feature = "dispatch_tree")] let mut current = C::dispatch_args_trie(&program.args)?; + // Run hook + program.run_hook_post_dispatch(¤t.member_id); + let mut stop_next = false; // If the program has Help enabled, skip actual logic and jump to Help if program.user_context.help { - return Ok(render_help::(program, current)); + let mut render_result = render_help::(program, current); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); } loop { @@ -84,17 +138,44 @@ where current = { // If a chain exists, execute as a chain if C::has_chain(¤t) { + // Run hook + program.run_hook_pre_chain(¤t.member_id, current.inner.as_ref()); + match C::do_chain(current) { ChainProcess::Ok((any, Next::Renderer)) => { - return Ok(render::(program, any)); + { + let mut render_result = render::(program, any); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); + }; + } + ChainProcess::Ok((any, Next::Chain)) => { + // Run hook + program.run_hook_post_chain(&any); + any + } + ChainProcess::Err(e) => { + // Run hook + program.run_hook_finish(); + return Err(e.into()); } - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), } } // If no chain exists, attempt to render else if C::has_renderer(¤t) { - return Ok(render::(program, current)); + // Run hook + program.run_hook_pre_render(¤t.member_id, current.inner.as_ref()); + + let mut render_result = render::(program, current); + + // Run hooks + program.run_hook_post_render(&render_result); + render_result.exit_code = program.run_hook_finish(); + + return Ok(render_result); } // No renderer exists else { @@ -107,7 +188,12 @@ where break; } } - Ok(RenderResult::default()) + let mut render_result = RenderResult::default(); + + // Run hook + render_result.exit_code = program.run_hook_finish(); + + Ok(render_result) } /// Dynamically dispatch input arguments to registered entry types -- cgit