diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-24 12:01:38 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-24 12:01:38 +0800 |
| commit | 1d1baf75a3acb5eb32913a8bdad42bae42844aa2 (patch) | |
| tree | 5dafbcbce48a5de3c61bba0c7d309e97dd80b1ce /mingling_core/src/program/exec.rs | |
| parent | addfbbf0b33a6251605990da73c2de5131766827 (diff) | |
Redesign hook system with structured info types and ProgramControls
Diffstat (limited to 'mingling_core/src/program/exec.rs')
| -rw-r--r-- | mingling_core/src/program/exec.rs | 320 |
1 files changed, 208 insertions, 112 deletions
diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index 0cadc6a..0ade92f 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -2,7 +2,7 @@ use crate::{ AnyOutput, ChainProcess, Dispatcher, NextProcess, Program, ProgramCollect, RenderResult, - error::ProgramInternalExecuteError, + error::ProgramInternalExecuteError, hook::ProgramControls, }; #[doc(hidden)] @@ -34,17 +34,37 @@ pub async fn exec_with_args<C>( where C: ProgramCollect<Enum = C>, { - // Run hooks - program.run_hook_pre_dispatch(args); + // Exit code + let mut exit_code: i32 = 0; + + // Current + let mut current = C::build_dispatcher_not_found(vec![]); + + macro_rules! control { + ($hook_call:expr) => { + let __ccc = $hook_call; + if let Some(r) = handle_program_control(program, __ccc, &mut current, &mut exit_code) { + return Ok(r); + } + }; + } - #[cfg(not(feature = "dispatch_tree"))] - let mut current = dispatch_args_dynamic(program, args)?; + // Run hooks + control!(program.run_hook_pre_dispatch(crate::hook::HookPreDispatchInfo { arguments: args })); - #[cfg(feature = "dispatch_tree")] - let mut current = C::dispatch_args_trie(args)?; + // Dispatch args - either via dynamic dispatch or trie dispatch based on feature flag + let mut current = if cfg!(not(feature = "dispatch_tree")) { + dispatch_args_dynamic(program, args)? + } else { + C::dispatch_args_trie(args)? + }; // Run hook - program.run_hook_post_dispatch(¤t.member_id); + control!( + program.run_hook_post_dispatch(crate::hook::HookPostDispatchInfo { + entry: ¤t.member_id, + }) + ); let mut stop_next = false; @@ -53,60 +73,76 @@ where let mut render_result = render_help::<C>(program, current); // Run hook - render_result.exit_code = program.run_hook_finish(); - + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; return Ok(render_result); } loop { let final_exec = stop_next; - 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, NextProcess::Renderer)) => { - let mut render_result = render::<C>(program, any); - - // Run hook - render_result.exit_code = program.run_hook_finish(); - - return Ok(render_result); - } - ChainProcess::Ok((any, NextProcess::Chain)) => { - // Run hook - program.run_hook_post_chain(&any); - any - } - ChainProcess::Err(e) => { - // Run hook - program.run_hook_finish(); - return Err(e.into()); + current = + { + // If a chain exists, execute as a chain + if C::has_chain(¤t) { + // Run hook + control!(program.run_hook_pre_chain(crate::hook::HookPreChainInfo { + input: ¤t.member_id, + raw: current.inner.as_ref(), + })); + + match C::do_chain(current).await { + ChainProcess::Ok((any, NextProcess::Renderer)) => { + { + let mut render_result = render::<C>(program, any); + + // Run hook + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; + return Ok(render_result); + }; + } + ChainProcess::Ok((any, NextProcess::Chain)) => { + // Run hook + control!(program.run_hook_post_chain(crate::hook::HookPostChainInfo { + output: &any + })); + any + } + ChainProcess::Err(e) => { + // Run hook + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + return Err(e.into()); + } } } - } - // If no chain exists, attempt to render - else if C::has_renderer(¤t) { - // Run hook - program.run_hook_pre_render(¤t.member_id, current.inner.as_ref()); - - let mut render_result = render::<C>(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 { - stop_next = true; - C::build_renderer_not_found(current.member_id) - } - }; + // If no chain exists, attempt to render + else if C::has_renderer(¤t) { + // Run hook + control!(program.run_hook_pre_render(crate::hook::HookPreRenderInfo { + input: ¤t.member_id, + raw: current.inner.as_ref(), + })); + + let mut render_result = render::<C>(program, current); + + // Run hooks + control!( + program.run_hook_post_render(crate::hook::HookPostRenderInfo { + result: &render_result, + }) + ); + + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; + return Ok(render_result); + } + // No renderer exists + else { + stop_next = true; + C::build_renderer_not_found(current.member_id) + } + }; if final_exec && stop_next { break; @@ -115,8 +151,8 @@ where let mut render_result = RenderResult::default(); // Run hook - render_result.exit_code = program.run_hook_finish(); - + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; Ok(render_result) } @@ -128,17 +164,37 @@ pub fn exec_with_args<C>( where C: ProgramCollect<Enum = C>, { - // Run hooks - program.run_hook_pre_dispatch(args); + // Exit code + let mut exit_code: i32 = 0; - #[cfg(not(feature = "dispatch_tree"))] - let mut current = dispatch_args_dynamic(program, args)?; + // Current + let mut current = C::build_dispatcher_not_found(vec![]); - #[cfg(feature = "dispatch_tree")] - let mut current = C::dispatch_args_trie(args)?; + macro_rules! control { + ($hook_call:expr) => { + let __ccc = $hook_call; + if let Some(r) = handle_program_control(program, __ccc, &mut current, &mut exit_code) { + return Ok(r); + } + }; + } + + // Run hooks + control!(program.run_hook_pre_dispatch(crate::hook::HookPreDispatchInfo { arguments: args })); + + // Dispatch args - either via dynamic dispatch or trie dispatch based on feature flag + let mut current = if cfg!(not(feature = "dispatch_tree")) { + dispatch_args_dynamic(program, args)? + } else { + C::dispatch_args_trie(args)? + }; // Run hook - program.run_hook_post_dispatch(¤t.member_id); + control!( + program.run_hook_post_dispatch(crate::hook::HookPostDispatchInfo { + entry: ¤t.member_id, + }) + ); let mut stop_next = false; @@ -147,62 +203,76 @@ where let mut render_result = render_help::<C>(program, current); // Run hook - render_result.exit_code = program.run_hook_finish(); - + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; return Ok(render_result); } loop { let final_exec = stop_next; - 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, NextProcess::Renderer)) => { - { - let mut render_result = render::<C>(program, any); - + current = + { + // If a chain exists, execute as a chain + if C::has_chain(¤t) { + // Run hook + control!(program.run_hook_pre_chain(crate::hook::HookPreChainInfo { + input: ¤t.member_id, + raw: current.inner.as_ref(), + })); + + match C::do_chain(current) { + ChainProcess::Ok((any, NextProcess::Renderer)) => { + { + let mut render_result = render::<C>(program, any); + + // Run hook + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; + return Ok(render_result); + }; + } + ChainProcess::Ok((any, NextProcess::Chain)) => { // Run hook - render_result.exit_code = program.run_hook_finish(); - - return Ok(render_result); - }; - } - ChainProcess::Ok((any, NextProcess::Chain)) => { - // Run hook - program.run_hook_post_chain(&any); - any - } - ChainProcess::Err(e) => { - // Run hook - program.run_hook_finish(); - return Err(e.into()); + control!(program.run_hook_post_chain(crate::hook::HookPostChainInfo { + output: &any + })); + any + } + ChainProcess::Err(e) => { + // Run hook + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + return Err(e.into()); + } } } - } - // If no chain exists, attempt to render - else if C::has_renderer(¤t) { - // Run hook - program.run_hook_pre_render(¤t.member_id, current.inner.as_ref()); - - let mut render_result = render::<C>(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 { - stop_next = true; - C::build_renderer_not_found(current.member_id) - } - }; + // If no chain exists, attempt to render + else if C::has_renderer(¤t) { + // Run hook + control!(program.run_hook_pre_render(crate::hook::HookPreRenderInfo { + input: ¤t.member_id, + raw: current.inner.as_ref(), + })); + + let mut render_result = render::<C>(program, current); + + // Run hooks + control!( + program.run_hook_post_render(crate::hook::HookPostRenderInfo { + result: &render_result, + }) + ); + + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; + return Ok(render_result); + } + // No renderer exists + else { + stop_next = true; + C::build_renderer_not_found(current.member_id) + } + }; if final_exec && stop_next { break; @@ -211,8 +281,8 @@ where let mut render_result = RenderResult::default(); // Run hook - render_result.exit_code = program.run_hook_finish(); - + control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + render_result.exit_code = exit_code; Ok(render_result) } @@ -287,6 +357,32 @@ where } #[inline] +pub(crate) fn handle_program_control<C: ProgramCollect<Enum = C>>( + program: &Program<C>, + controls: ProgramControls<C>, + current: &mut AnyOutput<C>, + exit_code: &mut i32, +) -> Option<RenderResult> { + for unit in controls.into_iter() { + match unit { + super::hook::ProgramControlUnit::OverrideExitCode(c) => *exit_code = c, + super::hook::ProgramControlUnit::RouteToChain(any_output) => *current = any_output, + super::hook::ProgramControlUnit::RouteToRender(any_output) => { + let mut r = render::<C>(program, any_output); + r.exit_code = *exit_code; + return Some(r); + } + super::hook::ProgramControlUnit::RouteToHelp(any_output) => { + let mut r = render_help::<C>(program, any_output); + r.exit_code = *exit_code; + return Some(r); + } + } + } + None +} + +#[inline] #[allow(unused_variables)] fn render<C: ProgramCollect<Enum = C>>(program: &Program<C>, any: AnyOutput<C>) -> RenderResult { #[cfg(not(feature = "general_renderer"))] |
