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.rs | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'mingling_core/src/program.rs') diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 4d943cf..0d23770 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -11,6 +11,7 @@ use crate::{ AnyOutput, ChainProcess, GlobalResources, Groupped, RenderResult, asset::dispatcher::Dispatcher, error::{ChainProcessError, ProgramExecuteError}, + hook::{ProgramAnonymousHook, ProgramHook}, }; use std::{ collections::HashMap, @@ -24,6 +25,8 @@ use std::pin::Pin; #[doc(hidden)] pub mod exec; #[doc(hidden)] +pub mod hook; +#[doc(hidden)] pub mod setup; mod config; @@ -41,7 +44,7 @@ static THIS_PROGRAM: OnceLock>> = On /// Returns a reference to the current program instance, panics if not set. pub fn this() -> &'static Program where - C: ProgramCollect + 'static, + C: ProgramCollect + 'static, { try_get_this_program().expect("Program not initialized") } @@ -49,7 +52,7 @@ where /// Returns a reference to the current program instance, if set. fn try_get_this_program() -> Option<&'static Program> where - C: ProgramCollect + 'static, + C: ProgramCollect + 'static, { THIS_PROGRAM.get()?.as_ref()?.downcast_ref::>() } @@ -58,7 +61,7 @@ where #[derive(Default)] pub struct Program where - C: ProgramCollect, + C: ProgramCollect, { pub(crate) collect: std::marker::PhantomData, @@ -73,6 +76,9 @@ where #[cfg(feature = "general_renderer")] pub general_renderer_name: GeneralRendererSetting, + pub(crate) hooks: Vec>, + pub(crate) anonymous_hooks: Vec, + pub(crate) resources: GlobalResources, } @@ -113,6 +119,9 @@ where #[cfg(feature = "general_renderer")] general_renderer_name: GeneralRendererSetting::Disable, + hooks: Vec::new(), + anonymous_hooks: Vec::new(), + resources: Arc::new(Mutex::new(HashMap::new())), } } @@ -167,7 +176,7 @@ where #[cfg(feature = "async")] impl Program where - C: ProgramCollect, + C: ProgramCollect + std::fmt::Display, { /// Sets the current program instance and runs the provided async function. async fn set_instance_and_run(self, f: F) -> Fut::Output @@ -237,7 +246,7 @@ where #[cfg(not(feature = "async"))] impl Program where - C: ProgramCollect, + C: ProgramCollect + Display, { /// Sets the current program instance and runs the provided function. fn set_instance_and_run(self, f: F) -> R @@ -266,7 +275,7 @@ where } /// Run the command line program - pub fn exec(self) + pub fn exec(self) -> i32 where C: 'static + Send + Sync, { @@ -276,29 +285,44 @@ where Err(e) => match e { ProgramExecuteError::DispatcherNotFound => { eprintln!("Dispatcher not found"); - return; + return 1; } ProgramExecuteError::RendererNotFound(renderer_name) => { eprintln!("Renderer `{}` not found", renderer_name); - return; + return 1; } ProgramExecuteError::Other(e) => { eprintln!("{}", e); - return; + return 1; } }, }; // Render result if stdout_setting.render_output && !result.is_empty() { + let exit_code = result.exit_code; print!("{}", result); + if let Err(e) = std::io::Write::flush(&mut std::io::stdout()) && stdout_setting.error_output { eprintln!("{}", e); + 1 + } else { + exit_code } + } else { + 0 } } + + /// Run the command line program, then exit + pub fn exec_and_exit(self) + where + C: 'static + Send + Sync, + { + std::process::exit(self.exec()) + } } /// Collected program context -- cgit